@@ -8,6 +8,7 @@ use rustc_infer::infer::InferCtxt;
8
8
use rustc_middle:: mir:: ConstraintCategory ;
9
9
use rustc_middle:: traits:: query:: OutlivesBound ;
10
10
use rustc_middle:: ty:: { self , RegionVid , Ty } ;
11
+ use rustc_span:: Span ;
11
12
use rustc_trait_selection:: traits:: query:: type_op:: { self , TypeOp } ;
12
13
use std:: rc:: Rc ;
13
14
use type_op:: TypeOpOutput ;
@@ -217,8 +218,28 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
217
218
self . inverse_outlives . add ( fr_b, fr_a) ;
218
219
}
219
220
221
+ #[ instrument( level = "debug" , skip( self ) ) ]
220
222
pub ( crate ) fn create ( mut self ) -> CreateResult < ' tcx > {
221
223
let span = self . infcx . tcx . def_span ( self . universal_regions . defining_ty . def_id ( ) ) ;
224
+
225
+ // Insert the facts we know from the predicates. Why? Why not.
226
+ let param_env = self . param_env ;
227
+ self . add_outlives_bounds ( outlives:: explicit_outlives_bounds ( param_env) ) ;
228
+
229
+ // Finally:
230
+ // - outlives is reflexive, so `'r: 'r` for every region `'r`
231
+ // - `'static: 'r` for every region `'r`
232
+ // - `'r: 'fn_body` for every (other) universally quantified
233
+ // region `'r`, all of which are provided by our caller
234
+ let fr_static = self . universal_regions . fr_static ;
235
+ let fr_fn_body = self . universal_regions . fr_fn_body ;
236
+ for fr in self . universal_regions . universal_regions ( ) {
237
+ debug ! ( "build: relating free region {:?} to itself and to 'static" , fr) ;
238
+ self . relate_universal_regions ( fr, fr) ;
239
+ self . relate_universal_regions ( fr_static, fr) ;
240
+ self . relate_universal_regions ( fr, fr_fn_body) ;
241
+ }
242
+
222
243
let unnormalized_input_output_tys = self
223
244
. universal_regions
224
245
. unnormalized_input_tys
@@ -236,78 +257,52 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
236
257
// the `relations` is built.
237
258
let mut normalized_inputs_and_output =
238
259
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
- let reported = self
251
- . infcx
252
- . tcx
253
- . sess
254
- . delay_span_bug ( span, & format ! ( "failed to normalize {:?}" , ty) ) ;
255
- TypeOpOutput {
256
- output : self . infcx . tcx . ty_error_with_guaranteed ( reported) ,
257
- constraints : None ,
258
- error_info : None ,
259
- }
260
- } ) ;
261
- // Note: we need this in examples like
262
- // ```
263
- // trait Foo {
264
- // type Bar;
265
- // fn foo(&self) -> &Self::Bar;
266
- // }
267
- // impl Foo for () {
268
- // type Bar = ();
269
- // fn foo(&self) -> &() {}
270
- // }
271
- // ```
272
- // Both &Self::Bar and &() are WF
273
- let constraints_implied2 =
274
- if ty != norm_ty { self . add_implied_bounds ( norm_ty) } else { None } ;
275
- normalized_inputs_and_output. push ( norm_ty) ;
276
- constraints1. into_iter ( ) . chain ( constraints_implied1) . chain ( constraints_implied2)
277
- } )
278
- . collect ( ) ;
279
-
280
- // Insert the facts we know from the predicates. Why? Why not.
281
- let param_env = self . param_env ;
282
- self . add_outlives_bounds ( outlives:: explicit_outlives_bounds ( param_env) ) ;
260
+ let mut constraints = vec ! [ ] ;
261
+ for ty in unnormalized_input_output_tys {
262
+ debug ! ( "build: input_or_output={:?}" , ty) ;
263
+ // We add implied bounds from both the unnormalized and normalized ty.
264
+ // See issue #87748
265
+ let constraints_unnorm = self . add_implied_bounds ( ty) ;
266
+ constraints_unnorm. map ( |c| constraints. push ( c) ) ;
267
+ let TypeOpOutput { output : norm_ty, constraints : constraints_normalize, .. } = self
268
+ . param_env
269
+ . and ( type_op:: normalize:: Normalize :: new ( ty) )
270
+ . fully_perform ( self . infcx )
271
+ . unwrap_or_else ( |_| {
272
+ self . infcx
273
+ . tcx
274
+ . sess
275
+ . delay_span_bug ( span, & format ! ( "failed to normalize {:?}" , ty) ) ;
276
+ TypeOpOutput {
277
+ output : self . infcx . tcx . ty_error ( ) ,
278
+ constraints : None ,
279
+ error_info : None ,
280
+ }
281
+ } ) ;
282
+ constraints_normalize. map ( |c| constraints. push ( c) ) ;
283
+
284
+ // Note: we need this in examples like
285
+ // ```
286
+ // trait Foo {
287
+ // type Bar;
288
+ // fn foo(&self) -> &Self::Bar;
289
+ // }
290
+ // impl Foo for () {
291
+ // type Bar = ();
292
+ // fn foo(&self) ->&() {}
293
+ // }
294
+ // ```
295
+ // Both &Self::Bar and &() are WF
296
+ if ty != norm_ty {
297
+ let constraints_norm = self . add_implied_bounds ( norm_ty) ;
298
+ constraints_norm. map ( |c| constraints. push ( c) ) ;
299
+ }
283
300
284
- // Finally:
285
- // - outlives is reflexive, so `'r: 'r` for every region `'r`
286
- // - `'static: 'r` for every region `'r`
287
- // - `'r: 'fn_body` for every (other) universally quantified
288
- // region `'r`, all of which are provided by our caller
289
- let fr_static = self . universal_regions . fr_static ;
290
- let fr_fn_body = self . universal_regions . fr_fn_body ;
291
- for fr in self . universal_regions . universal_regions ( ) {
292
- debug ! ( "build: relating free region {:?} to itself and to 'static" , fr) ;
293
- self . relate_universal_regions ( fr, fr) ;
294
- self . relate_universal_regions ( fr_static, fr) ;
295
- self . relate_universal_regions ( fr, fr_fn_body) ;
301
+ normalized_inputs_and_output. push ( norm_ty) ;
296
302
}
297
303
298
- for data in & constraint_sets {
299
- constraint_conversion:: ConstraintConversion :: new (
300
- self . infcx ,
301
- & self . universal_regions ,
302
- & self . region_bound_pairs ,
303
- self . implicit_region_bound ,
304
- self . param_env ,
305
- Locations :: All ( span) ,
306
- span,
307
- ConstraintCategory :: Internal ,
308
- & mut self . constraints ,
309
- )
310
- . convert_all ( data) ;
304
+ for c in constraints {
305
+ self . push_region_constraints ( c, span) ;
311
306
}
312
307
313
308
CreateResult {
@@ -321,6 +316,24 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
321
316
}
322
317
}
323
318
319
+ #[ instrument( skip( self , data) , level = "debug" ) ]
320
+ fn push_region_constraints ( & mut self , data : & QueryRegionConstraints < ' tcx > , span : Span ) {
321
+ debug ! ( "constraints generated: {:#?}" , data) ;
322
+
323
+ constraint_conversion:: ConstraintConversion :: new (
324
+ self . infcx ,
325
+ & self . universal_regions ,
326
+ & self . region_bound_pairs ,
327
+ self . implicit_region_bound ,
328
+ self . param_env ,
329
+ Locations :: All ( span) ,
330
+ span,
331
+ ConstraintCategory :: Internal ,
332
+ & mut self . constraints ,
333
+ )
334
+ . convert_all ( data) ;
335
+ }
336
+
324
337
/// Update the type of a single local, which should represent
325
338
/// either the return type of the MIR or one of its arguments. At
326
339
/// the same time, compute and add any implied bounds that come
@@ -332,6 +345,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
332
345
. and ( type_op:: implied_outlives_bounds:: ImpliedOutlivesBounds { ty } )
333
346
. fully_perform ( self . infcx )
334
347
. unwrap_or_else ( |_| bug ! ( "failed to compute implied bounds {:?}" , ty) ) ;
348
+ debug ! ( ?bounds, ?constraints) ;
335
349
self . add_outlives_bounds ( bounds) ;
336
350
constraints
337
351
}
0 commit comments