]>
Commit | Line | Data |
---|---|---|
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 | 10 | use crate::type_check::constraint_conversion::ConstraintConversion; |
c295e0f8 | 11 | use rustc_index::vec::Idx; |
74b04a01 | 12 | use rustc_infer::infer::LateBoundRegionConversionTime; |
ba9703b0 | 13 | use rustc_middle::mir::*; |
3c0e092e | 14 | use rustc_middle::ty::Ty; |
dfeec247 | 15 | use rustc_span::Span; |
3c0e092e XL |
16 | use rustc_span::DUMMY_SP; |
17 | use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; | |
18 | use rustc_trait_selection::traits::query::Fallible; | |
19 | use type_op::TypeOpOutput; | |
ff7c6d11 | 20 | |
c295e0f8 | 21 | use crate::universal_regions::UniversalRegions; |
60c5eb7d | 22 | |
83c7162d | 23 | use super::{Locations, TypeChecker}; |
ff7c6d11 | 24 | |
dc9dc135 | 25 | impl<'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 | ||
228 | for data in constraints.into_iter().collect::<Vec<_>>() { | |
229 | ConstraintConversion::new( | |
230 | self.infcx, | |
231 | &self.borrowck_context.universal_regions, | |
232 | &self.region_bound_pairs, | |
233 | Some(self.implicit_region_bound), | |
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 | } |