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