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