@@ -218,64 +218,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
218218 self . inverse_outlives . add ( fr_b, fr_a) ;
219219 }
220220
221+ #[ instrument( level = "debug" , skip( self ) ) ]
221222 pub ( crate ) fn create ( mut self ) -> CreateResult < ' tcx > {
222- let unnormalized_input_output_tys = self
223- . universal_regions
224- . unnormalized_input_tys
225- . iter ( )
226- . cloned ( )
227- . chain ( Some ( self . universal_regions . unnormalized_output_ty ) ) ;
228-
229- // For each of the input/output types:
230- // - Normalize the type. This will create some region
231- // constraints, which we buffer up because we are
232- // not ready to process them yet.
233- // - Then compute the implied bounds. This will adjust
234- // the `region_bound_pairs` and so forth.
235- // - After this is done, we'll process the constraints, once
236- // the `relations` is built.
237- let mut normalized_inputs_and_output =
238- Vec :: with_capacity ( self . universal_regions . unnormalized_input_tys . len ( ) + 1 ) ;
239- let constraint_sets: Vec < _ > = unnormalized_input_output_tys
240- . flat_map ( |ty| {
241- debug ! ( "build: input_or_output={:?}" , ty) ;
242- // We add implied bounds from both the unnormalized and normalized ty.
243- // See issue #87748
244- let constraints_implied1 = self . add_implied_bounds ( ty) ;
245- let TypeOpOutput { output : norm_ty, constraints : constraints1, .. } = self
246- . param_env
247- . and ( type_op:: normalize:: Normalize :: new ( ty) )
248- . fully_perform ( self . infcx )
249- . unwrap_or_else ( |_| {
250- self . infcx
251- . tcx
252- . sess
253- . delay_span_bug ( DUMMY_SP , & format ! ( "failed to normalize {:?}" , ty) ) ;
254- TypeOpOutput {
255- output : self . infcx . tcx . ty_error ( ) ,
256- constraints : None ,
257- error_info : None ,
258- }
259- } ) ;
260- // Note: we need this in examples like
261- // ```
262- // trait Foo {
263- // type Bar;
264- // fn foo(&self) -> &Self::Bar;
265- // }
266- // impl Foo for () {
267- // type Bar = ();
268- // fn foo(&self) -> &() {}
269- // }
270- // ```
271- // Both &Self::Bar and &() are WF
272- let constraints_implied2 =
273- if ty != norm_ty { self . add_implied_bounds ( norm_ty) } else { None } ;
274- normalized_inputs_and_output. push ( norm_ty) ;
275- constraints1. into_iter ( ) . chain ( constraints_implied1) . chain ( constraints_implied2)
276- } )
277- . collect ( ) ;
278-
279223 // Insert the facts we know from the predicates. Why? Why not.
280224 let param_env = self . param_env ;
281225 self . add_outlives_bounds ( outlives:: explicit_outlives_bounds ( param_env) ) ;
@@ -294,19 +238,109 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
294238 self . relate_universal_regions ( fr, fr_fn_body) ;
295239 }
296240
297- for data in & constraint_sets {
298- constraint_conversion:: ConstraintConversion :: new (
299- self . infcx ,
300- & self . universal_regions ,
301- & self . region_bound_pairs ,
302- self . implicit_region_bound ,
303- self . param_env ,
304- Locations :: All ( DUMMY_SP ) ,
305- DUMMY_SP ,
306- ConstraintCategory :: Internal ,
307- & mut self . constraints ,
308- )
309- . convert_all ( data) ;
241+ let unnormalized_input_output_tys = self
242+ . universal_regions
243+ . unnormalized_input_tys
244+ . iter ( )
245+ . cloned ( )
246+ . chain ( Some ( self . universal_regions . unnormalized_output_ty ) ) ;
247+
248+ // For each of the input/output types:
249+ // - Normalize the type. This will create some region
250+ // constraints, which we buffer up because we are
251+ // not ready to process them yet.
252+ // - Then compute the implied bounds. This will adjust
253+ // the `region_bound_pairs` and so forth.
254+ // - After this is done, we'll process the constraints, once
255+ // the `relations` is built.
256+ let mut normalized_inputs_and_output =
257+ Vec :: with_capacity ( self . universal_regions . unnormalized_input_tys . len ( ) + 1 ) ;
258+ for ty in unnormalized_input_output_tys {
259+ debug ! ( "build: input_or_output={:?}" , ty) ;
260+ // We add implied bounds from both the unnormalized and normalized ty.
261+ // See issue #87748
262+ let constraints_unnorm = self . add_implied_bounds ( ty) ;
263+ let TypeOpOutput { output : norm_ty, constraints : constraints_normalize, .. } = self
264+ . param_env
265+ . and ( type_op:: normalize:: Normalize :: new ( ty) )
266+ . fully_perform ( self . infcx )
267+ . unwrap_or_else ( |_| {
268+ self . infcx
269+ . tcx
270+ . sess
271+ . delay_span_bug ( DUMMY_SP , & format ! ( "failed to normalize {:?}" , ty) ) ;
272+ TypeOpOutput {
273+ output : self . infcx . tcx . ty_error ( ) ,
274+ constraints : None ,
275+ error_info : None ,
276+ }
277+ } ) ;
278+
279+ // Note: we need this in examples like
280+ // ```
281+ // trait Foo {
282+ // type Bar;
283+ // fn foo(&self) -> &Self::Bar;
284+ // }
285+ // impl Foo for () {
286+ // type Bar = ();
287+ // fn foo(&self) ->&() {}
288+ // }
289+ // ```
290+ // Both &Self::Bar and &() are WF
291+ let constraints_norm = self . add_implied_bounds ( norm_ty) ;
292+
293+ // Okay, I should explain why these are all the way down here. Turns
294+ // out, it's actually a bit subtle. I'll use the test `issue-52057`
295+ // as an example (well, because it's the only test that failed
296+ // putting these calls immediately after the `add_implied_bounds`
297+ // calls.)
298+ //
299+ // So, the key bit is this impl:
300+ // ```rust,ignore (example)
301+ // impl<'a, I, P: ?Sized> Parser for &'a mut P
302+ // where P: Parser<Input = I>,
303+ // {
304+ // type Input = I;
305+ // fn parse_first<'x>(_: &'x mut Self::Input) {}
306+ // }
307+ //
308+ // As part of querying the implied bounds for `&mut Self::Input`
309+ // (note the unnormalized form), we query the obligations to prove
310+ // that it is WF. This turns out to be
311+ // [
312+ // <&'_#0r mut P as Parser>::Input: '_#1r,
313+ // Self: Parser,
314+ // P: '_#0r,
315+ // ]
316+ //
317+ // The wf code normalizes these obligations, so we actually end up with
318+ // [
319+ // _#0t: '_#1r,
320+ // &'_#0r mut P as Parser>::Input == _#0t,
321+ // Self: Parser,
322+ // P: '_#0r,
323+ // ]
324+ //
325+ // The implied bounds code then registers both the first two
326+ // predicates to be solved, since they contain type variables. Then
327+ // the implied bounds code goes through each of these obligations to
328+ // check if they should be registered as implied bounds. For
329+ // `_#0t: '_#1r`, there is an unresolved type variable, so it gets
330+ // skipped. The next two predicates never would registered. The last
331+ // predicate gets registered.
332+ //
333+ // At the end of this, for the unnormalized type
334+ // `&'x mut Self::Input`, `P: '_#0r' ends up as a implied bound and
335+ // `I: '_#1r` ends up as a constraint.
336+ //
337+ // Later, for the normalized type (`&'x mut I`), we don't do any
338+ // normalization, so we only end up with the implied bound `I: 'x`.
339+ constraints_unnorm. map ( |c| self . push_region_constraints ( c) ) ;
340+ constraints_normalize. map ( |c| self . push_region_constraints ( c) ) ;
341+ constraints_norm. map ( |c| self . push_region_constraints ( c) ) ;
342+
343+ normalized_inputs_and_output. push ( norm_ty) ;
310344 }
311345
312346 CreateResult {
@@ -320,6 +354,24 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
320354 }
321355 }
322356
357+ #[ instrument( skip( self , data) , level = "debug" ) ]
358+ fn push_region_constraints ( & mut self , data : & QueryRegionConstraints < ' tcx > ) {
359+ debug ! ( "constraints generated: {:#?}" , data) ;
360+
361+ constraint_conversion:: ConstraintConversion :: new (
362+ self . infcx ,
363+ & self . universal_regions ,
364+ & self . region_bound_pairs ,
365+ self . implicit_region_bound ,
366+ self . param_env ,
367+ Locations :: All ( DUMMY_SP ) ,
368+ DUMMY_SP ,
369+ ConstraintCategory :: Internal ,
370+ & mut self . constraints ,
371+ )
372+ . convert_all ( data) ;
373+ }
374+
323375 /// Update the type of a single local, which should represent
324376 /// either the return type of the MIR or one of its arguments. At
325377 /// the same time, compute and add any implied bounds that come
0 commit comments