@@ -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,27 @@ 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
+ // - outlives is reflexive, so `'r: 'r` for every region `'r`
230
+ // - `'static: 'r` for every region `'r`
231
+ // - `'r: 'fn_body` for every (other) universally quantified
232
+ // region `'r`, all of which are provided by our caller
233
+ let fr_static = self . universal_regions . fr_static ;
234
+ let fr_fn_body = self . universal_regions . fr_fn_body ;
235
+ for fr in self . universal_regions . universal_regions ( ) {
236
+ debug ! ( "build: relating free region {:?} to itself and to 'static" , fr) ;
237
+ self . relate_universal_regions ( fr, fr) ;
238
+ self . relate_universal_regions ( fr_static, fr) ;
239
+ self . relate_universal_regions ( fr, fr_fn_body) ;
240
+ }
241
+
222
242
let unnormalized_input_output_tys = self
223
243
. universal_regions
224
244
. unnormalized_input_tys
@@ -236,78 +256,58 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
236
256
// the `relations` is built.
237
257
let mut normalized_inputs_and_output =
238
258
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 ( ) ;
259
+ let mut constraints = vec ! [ ] ;
260
+ for ty in unnormalized_input_output_tys {
261
+ debug ! ( "build: input_or_output={:?}" , ty) ;
262
+ // We add implied bounds from both the unnormalized and normalized ty.
263
+ // See issue #87748
264
+ let constraints_unnorm = self . add_implied_bounds ( ty) ;
265
+ if let Some ( c) = constraints_unnorm {
266
+ constraints. push ( c)
267
+ }
268
+ let TypeOpOutput { output : norm_ty, constraints : constraints_normalize, .. } = self
269
+ . param_env
270
+ . and ( type_op:: normalize:: Normalize :: new ( ty) )
271
+ . fully_perform ( self . infcx )
272
+ . unwrap_or_else ( |_| {
273
+ self . infcx
274
+ . tcx
275
+ . sess
276
+ . delay_span_bug ( span, & format ! ( "failed to normalize {:?}" , ty) ) ;
277
+ TypeOpOutput {
278
+ output : self . infcx . tcx . ty_error ( ) ,
279
+ constraints : None ,
280
+ error_info : None ,
281
+ }
282
+ } ) ;
283
+ if let Some ( c) = constraints_normalize {
284
+ constraints. push ( c)
285
+ }
279
286
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) ) ;
287
+ // Note: we need this in examples like
288
+ // ```
289
+ // trait Foo {
290
+ // type Bar;
291
+ // fn foo(&self) -> &Self::Bar;
292
+ // }
293
+ // impl Foo for () {
294
+ // type Bar = ();
295
+ // fn foo(&self) ->&() {}
296
+ // }
297
+ // ```
298
+ // Both &Self::Bar and &() are WF
299
+ if ty != norm_ty {
300
+ let constraints_norm = self . add_implied_bounds ( norm_ty) ;
301
+ if let Some ( c) = constraints_norm {
302
+ constraints. push ( c)
303
+ }
304
+ }
283
305
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) ;
306
+ normalized_inputs_and_output. push ( norm_ty) ;
296
307
}
297
308
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) ;
309
+ for c in constraints {
310
+ self . push_region_constraints ( c, span) ;
311
311
}
312
312
313
313
CreateResult {
@@ -321,6 +321,24 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
321
321
}
322
322
}
323
323
324
+ #[ instrument( skip( self , data) , level = "debug" ) ]
325
+ fn push_region_constraints ( & mut self , data : & QueryRegionConstraints < ' tcx > , span : Span ) {
326
+ debug ! ( "constraints generated: {:#?}" , data) ;
327
+
328
+ constraint_conversion:: ConstraintConversion :: new (
329
+ self . infcx ,
330
+ & self . universal_regions ,
331
+ & self . region_bound_pairs ,
332
+ self . implicit_region_bound ,
333
+ self . param_env ,
334
+ Locations :: All ( span) ,
335
+ span,
336
+ ConstraintCategory :: Internal ,
337
+ & mut self . constraints ,
338
+ )
339
+ . convert_all ( data) ;
340
+ }
341
+
324
342
/// Update the type of a single local, which should represent
325
343
/// either the return type of the MIR or one of its arguments. At
326
344
/// the same time, compute and add any implied bounds that come
@@ -332,6 +350,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
332
350
. and ( type_op:: implied_outlives_bounds:: ImpliedOutlivesBounds { ty } )
333
351
. fully_perform ( self . infcx )
334
352
. unwrap_or_else ( |_| bug ! ( "failed to compute implied bounds {:?}" , ty) ) ;
353
+ debug ! ( ?bounds, ?constraints) ;
335
354
self . add_outlives_bounds ( bounds) ;
336
355
constraints
337
356
}
0 commit comments