]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_borrowck/src/type_check/input_output.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / compiler / rustc_borrowck / src / type_check / input_output.rs
CommitLineData
ff7c6d11
XL
1//! This module contains code to equate the input/output types appearing
2//! in the MIR with the expected input/output types from the function
3//! signature. This requires a bit of processing, as the expected types
416331ca 4//! are supplied to us before normalization and may contain opaque
ff7c6d11
XL
5//! `impl Trait` instances. In contrast, the input/output types found in
6//! the MIR (specifically, in the special local variables for the
0bf4aa26 7//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
ff7c6d11
XL
8//! contain revealed `impl Trait` values).
9
3c0e092e 10use crate::type_check::constraint_conversion::ConstraintConversion;
c295e0f8 11use rustc_index::vec::Idx;
74b04a01 12use rustc_infer::infer::LateBoundRegionConversionTime;
ba9703b0 13use rustc_middle::mir::*;
3c0e092e 14use rustc_middle::ty::Ty;
dfeec247 15use rustc_span::Span;
3c0e092e
XL
16use rustc_span::DUMMY_SP;
17use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
18use rustc_trait_selection::traits::query::Fallible;
19use type_op::TypeOpOutput;
ff7c6d11 20
c295e0f8 21use crate::universal_regions::UniversalRegions;
60c5eb7d 22
83c7162d 23use super::{Locations, TypeChecker};
ff7c6d11 24
dc9dc135 25impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
c295e0f8 26 #[instrument(skip(self, body, universal_regions), level = "debug")]
ff7c6d11
XL
27 pub(super) fn equate_inputs_and_outputs(
28 &mut self,
dc9dc135 29 body: &Body<'tcx>,
ff7c6d11 30 universal_regions: &UniversalRegions<'tcx>,
8faf50e0 31 normalized_inputs_and_output: &[Ty<'tcx>],
ff7c6d11 32 ) {
8faf50e0
XL
33 let (&normalized_output_ty, normalized_input_tys) =
34 normalized_inputs_and_output.split_last().unwrap();
0bf4aa26 35
3c0e092e
XL
36 debug!(?normalized_output_ty);
37 debug!(?normalized_input_tys);
38
29967ef6
XL
39 let mir_def_id = body.source.def_id().expect_local();
40
0bf4aa26
XL
41 // If the user explicitly annotated the input types, extract
42 // those.
43 //
0731742a 44 // e.g., `|x: FxHashMap<_, &'static u32>| ...`
0bf4aa26 45 let user_provided_sig;
29967ef6 46 if !self.tcx().is_closure(mir_def_id.to_def_id()) {
0bf4aa26
XL
47 user_provided_sig = None;
48 } else {
29967ef6 49 let typeck_results = self.tcx().typeck(mir_def_id);
5869c6ff
XL
50 user_provided_sig = typeck_results.user_provided_sigs.get(&mir_def_id.to_def_id()).map(
51 |user_provided_poly_sig| {
29967ef6
XL
52 // Instantiate the canonicalized variables from
53 // user-provided signature (e.g., the `_` in the code
54 // above) with fresh variables.
94222f64 55 let poly_sig = self.instantiate_canonical_with_fresh_inference_vars(
29967ef6
XL
56 body.span,
57 &user_provided_poly_sig,
58 );
59
60 // Replace the bound items in the fn sig with fresh
61 // variables, so that they represent the view from
62 // "inside" the closure.
923072b8
FG
63 self.infcx.replace_bound_vars_with_fresh_vars(
64 body.span,
65 LateBoundRegionConversionTime::FnCall,
66 poly_sig,
67 )
5869c6ff
XL
68 },
69 );
70 }
ff7c6d11 71
c295e0f8 72 debug!(?normalized_input_tys, ?body.local_decls);
ba9703b0 73
ff7c6d11 74 // Equate expected input tys with those in the MIR.
29967ef6 75 for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
cdc7bbd5
XL
76 if argument_index + 1 >= body.local_decls.len() {
77 self.tcx()
78 .sess
79 .delay_span_bug(body.span, "found more normalized_input_ty than local_decls");
80 break;
81 }
3c0e092e 82
0bf4aa26
XL
83 // In MIR, argument N is stored in local N+1.
84 let local = Local::new(argument_index + 1);
85
dc9dc135 86 let mir_input_ty = body.local_decls[local].ty;
3c0e092e 87
dc9dc135 88 let mir_input_span = body.local_decls[local].source_info.span;
0bf4aa26
XL
89 self.equate_normalized_input_or_output(
90 normalized_input_ty,
91 mir_input_ty,
92 mir_input_span,
93 );
94 }
95
96 if let Some(user_provided_sig) = user_provided_sig {
29967ef6
XL
97 for (argument_index, &user_provided_input_ty) in
98 user_provided_sig.inputs().iter().enumerate()
0bf4aa26
XL
99 {
100 // In MIR, closures begin an implicit `self`, so
101 // argument N is stored in local N+2.
102 let local = Local::new(argument_index + 2);
dc9dc135
XL
103 let mir_input_ty = body.local_decls[local].ty;
104 let mir_input_span = body.local_decls[local].source_info.span;
0bf4aa26
XL
105
106 // If the user explicitly annotated the input types, enforce those.
107 let user_provided_input_ty =
108 self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
3c0e092e 109
0bf4aa26
XL
110 self.equate_normalized_input_or_output(
111 user_provided_input_ty,
112 mir_input_ty,
113 mir_input_span,
114 );
115 }
ff7c6d11
XL
116 }
117
a2a8927a
XL
118 debug!(
119 "equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}",
120 body.yield_ty(),
121 universal_regions.yield_ty
122 );
123
124 // We will not have a universal_regions.yield_ty if we yield (by accident)
125 // outside of a generator and return an `impl Trait`, so emit a delay_span_bug
126 // because we don't want to panic in an assert here if we've already got errors.
127 if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() {
128 self.tcx().sess.delay_span_bug(
129 body.span,
130 &format!(
131 "Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})",
132 body.yield_ty(),
133 universal_regions.yield_ty,
134 ),
135 );
136 }
137
138 if let (Some(mir_yield_ty), Some(ur_yield_ty)) =
139 (body.yield_ty(), universal_regions.yield_ty)
140 {
dc9dc135 141 let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
0bf4aa26 142 self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
2c00a5a8
XL
143 }
144
416331ca 145 // Return types are a bit more complex. They may contain opaque `impl Trait` types.
dc9dc135
XL
146 let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
147 let output_span = body.local_decls[RETURN_PLACE].source_info.span;
5e7ed085 148 if let Err(terr) = self.eq_types(
0bf4aa26 149 normalized_output_ty,
5e7ed085 150 mir_output_ty,
0bf4aa26
XL
151 Locations::All(output_span),
152 ConstraintCategory::BoringNoLocation,
153 ) {
154 span_mirbug!(
155 self,
156 Location::START,
157 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
158 normalized_output_ty,
159 mir_output_ty,
160 terr
161 );
162 };
163
164 // If the user explicitly annotated the output types, enforce those.
60c5eb7d 165 // Note that this only happens for closures.
0bf4aa26
XL
166 if let Some(user_provided_sig) = user_provided_sig {
167 let user_provided_output_ty = user_provided_sig.output();
168 let user_provided_output_ty =
169 self.normalize(user_provided_output_ty, Locations::All(output_span));
5e7ed085 170 if let Err(err) = self.eq_types(
60c5eb7d 171 user_provided_output_ty,
5e7ed085 172 mir_output_ty,
60c5eb7d 173 Locations::All(output_span),
dfeec247 174 ConstraintCategory::BoringNoLocation,
60c5eb7d
XL
175 ) {
176 span_mirbug!(
177 self,
178 Location::START,
179 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
180 mir_output_ty,
181 user_provided_output_ty,
182 err
183 );
184 }
ff7c6d11
XL
185 }
186 }
187
c295e0f8 188 #[instrument(skip(self, span), level = "debug")]
0bf4aa26 189 fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
94222f64 190 if let Err(_) =
dfeec247
XL
191 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
192 {
94222f64
XL
193 // FIXME(jackh726): This is a hack. It's somewhat like
194 // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
195 // like to normalize *before* inserting into `local_decls`, but
196 // doing so ends up causing some other trouble.
3c0e092e
XL
197 let b = match self.normalize_and_add_constraints(b) {
198 Ok(n) => n,
94222f64
XL
199 Err(_) => {
200 debug!("equate_inputs_and_outputs: NoSolution");
201 b
202 }
203 };
3c0e092e 204
c295e0f8
XL
205 // Note: if we have to introduce new placeholders during normalization above, then we won't have
206 // added those universes to the universe info, which we would want in `relate_tys`.
94222f64
XL
207 if let Err(terr) =
208 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
209 {
210 span_mirbug!(
211 self,
212 Location::START,
213 "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
214 a,
215 b,
216 terr
217 );
218 }
ff7c6d11
XL
219 }
220 }
3c0e092e
XL
221
222 pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> {
223 let TypeOpOutput { output: norm_ty, constraints, .. } =
224 self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?;
225
226 debug!("{:?} normalized to {:?}", t, norm_ty);
227
064997fb 228 for data in constraints {
3c0e092e
XL
229 ConstraintConversion::new(
230 self.infcx,
231 &self.borrowck_context.universal_regions,
232 &self.region_bound_pairs,
064997fb 233 self.implicit_region_bound,
3c0e092e
XL
234 self.param_env,
235 Locations::All(DUMMY_SP),
04454e1e 236 DUMMY_SP,
3c0e092e
XL
237 ConstraintCategory::Internal,
238 &mut self.borrowck_context.constraints,
239 )
240 .convert_all(&*data);
241 }
242
243 Ok(norm_ty)
244 }
ff7c6d11 245}