@@ -126,6 +126,31 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
126126 ) ;
127127 }
128128
129+ // FIXME(BoxyUwU): This should probably be part of a larger borrowck dev-guide chapter
130+ //
131+ /// Enforce that the types of the locals corresponding to the inputs and output of
132+ /// the body are equal to those of the (normalized) signature.
133+ ///
134+ /// This is necessary for two reasons:
135+ /// - Locals in the MIR all start out with `'erased` regions and then are replaced
136+ /// with unconstrained nll vars. If we have a function returning `&'a u32` then
137+ /// the local `_0: &'?10 u32` needs to have its region var equated with the nll
138+ /// var representing `'a`. i.e. borrow check must uphold that `'?10 = 'a`.
139+ /// - When computing the normalized signature we may introduce new unconstrained nll
140+ /// vars due to higher ranked where clauses ([#136547]). We then wind up with implied
141+ /// bounds involving these vars.
142+ ///
143+ /// For this reason it is important that we equate with the *normalized* signature
144+ /// which was produced when computing implied bounds. If we do not do so then we will
145+ /// wind up with implied bounds on nll vars which cannot actually be used as the nll
146+ /// var never gets related to anything.
147+ ///
148+ /// For 'closure-like' bodies this function effectively relates the *inferred* signature
149+ /// of the closure against the locals corresponding to the closure's inputs/output. It *does
150+ /// not* relate the user provided types for the signature to the locals, this is handled
151+ /// separately by: [`TypeChecker::check_signature_annotation`].
152+ ///
153+ /// [#136547]: <https://www.github.com/rust-lang/rust/issues/136547>
129154 #[ instrument( skip( self ) , level = "debug" ) ]
130155 pub ( super ) fn equate_inputs_and_outputs ( & mut self , normalized_inputs_and_output : & [ Ty < ' tcx > ] ) {
131156 let ( & normalized_output_ty, normalized_input_tys) =
@@ -173,38 +198,44 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
173198 ) ;
174199 }
175200
176- // Return types are a bit more complex. They may contain opaque `impl Trait` types.
177- let mir_output_ty = self . body . local_decls [ RETURN_PLACE ] . ty ;
201+ // Equate expected output ty with the type of the RETURN_PLACE in MIR
202+ let mir_output_ty = self . body . return_ty ( ) ;
178203 let output_span = self . body . local_decls [ RETURN_PLACE ] . source_info . span ;
179204 self . equate_normalized_input_or_output ( normalized_output_ty, mir_output_ty, output_span) ;
180205 }
181206
182207 #[ instrument( skip( self ) , level = "debug" ) ]
183208 fn equate_normalized_input_or_output ( & mut self , a : Ty < ' tcx > , b : Ty < ' tcx > , span : Span ) {
209+ if self . infcx . next_trait_solver ( ) {
210+ return self
211+ . eq_types ( a, b, Locations :: All ( span) , ConstraintCategory :: BoringNoLocation )
212+ . unwrap_or_else ( |terr| {
213+ span_mirbug ! (
214+ self ,
215+ Location :: START ,
216+ "equate_normalized_input_or_output: `{a:?}=={b:?}` failed with `{terr:?}`" ,
217+ ) ;
218+ } ) ;
219+ }
220+
221+ // This is a hack. `body.local_decls` are not necessarily normalized in the old
222+ // solver due to not deeply normalizing in writeback. So we must re-normalize here.
223+ //
224+ // However, in most cases normalizing is unnecessary so we only do so if it may be
225+ // necessary for type equality to hold. This leads to some (very minor) performance
226+ // wins.
184227 if let Err ( _) =
185228 self . eq_types ( a, b, Locations :: All ( span) , ConstraintCategory :: BoringNoLocation )
186229 {
187- // FIXME(jackh726): This is a hack. It's somewhat like
188- // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
189- // like to normalize *before* inserting into `local_decls`, but
190- // doing so ends up causing some other trouble.
191230 let b = self . normalize ( b, Locations :: All ( span) ) ;
192-
193- // Note: if we have to introduce new placeholders during normalization above, then we
194- // won't have added those universes to the universe info, which we would want in
195- // `relate_tys`.
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- }
208- }
231+ self . eq_types ( a, b, Locations :: All ( span) , ConstraintCategory :: BoringNoLocation )
232+ . unwrap_or_else ( |terr| {
233+ span_mirbug ! (
234+ self ,
235+ Location :: START ,
236+ "equate_normalized_input_or_output: `{a:?}=={b:?}` failed with `{terr:?}`" ,
237+ ) ;
238+ } ) ;
239+ } ;
209240 }
210241}
0 commit comments