@@ -218,64 +218,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
218
218
self . inverse_outlives . add ( fr_b, fr_a) ;
219
219
}
220
220
221
+ #[ instrument( level = "debug" , skip( self ) ) ]
221
222
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
-
279
223
// Insert the facts we know from the predicates. Why? Why not.
280
224
let param_env = self . param_env ;
281
225
self . add_outlives_bounds ( outlives:: explicit_outlives_bounds ( param_env) ) ;
@@ -294,19 +238,109 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
294
238
self . relate_universal_regions ( fr, fr_fn_body) ;
295
239
}
296
240
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) ;
310
344
}
311
345
312
346
CreateResult {
@@ -320,6 +354,24 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
320
354
}
321
355
}
322
356
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
+
323
375
/// Update the type of a single local, which should represent
324
376
/// either the return type of the MIR or one of its arguments. At
325
377
/// the same time, compute and add any implied bounds that come
0 commit comments