@@ -339,76 +339,36 @@ fn check_gat_where_clauses(
339
339
// reflected in a where clause on the GAT itself.
340
340
for ( region, region_idx) in & visitor. regions {
341
341
for ( ty, ty_idx) in & visitor. types {
342
- // Unfortunately, we have to use a new `InferCtxt` for each
343
- // pair, because region constraints get added and solved there,
344
- // and we need to test each pair individually.
345
- tcx. infer_ctxt ( ) . enter ( |infcx| {
346
- let mut outlives_environment = OutlivesEnvironment :: new ( param_env) ;
347
- outlives_environment. add_implied_bounds ( & infcx, wf_tys. clone ( ) , id, DUMMY_SP ) ;
348
- outlives_environment. save_implied_bounds ( id) ;
349
- let region_bound_pairs =
350
- outlives_environment. region_bound_pairs_map ( ) . get ( & id) . unwrap ( ) ;
351
-
352
- let cause =
353
- ObligationCause :: new ( DUMMY_SP , id, ObligationCauseCode :: MiscObligation ) ;
354
-
355
- let sup_type = * ty;
356
- let sub_region = region;
357
-
358
- let origin = SubregionOrigin :: from_obligation_cause ( & cause, || {
359
- infer:: RelateParamBound ( cause. span , sup_type, None )
360
- } ) ;
361
-
362
- let outlives = & mut TypeOutlives :: new (
363
- & infcx,
364
- tcx,
365
- & region_bound_pairs,
366
- Some ( tcx. lifetimes . re_root_empty ) ,
367
- param_env,
368
- ) ;
369
- // In our example, requires that Self: 'a
370
- outlives. type_must_outlive ( origin, sup_type, sub_region) ;
371
-
372
- let errors = infcx. resolve_regions (
373
- trait_item. def_id . to_def_id ( ) ,
374
- & outlives_environment,
375
- RegionckMode :: default ( ) ,
376
- ) ;
377
-
378
- debug ! ( ?errors, "errors" ) ;
379
-
380
- // If we were able to prove that Self: 'a without an error,
381
- // it must be because of the implied or explicit bounds...
382
- if errors. is_empty ( ) {
383
- debug ! ( ?ty_idx, ?region_idx) ;
384
- debug ! ( "required clause: {} must outlive {}" , ty, region) ;
385
- // Translate into the generic parameters of the GAT. In
386
- // our example, the type was Self, which will also be
387
- // Self in the GAT.
388
- let ty_param = generics. param_at ( * ty_idx, tcx) ;
389
- let ty_param = tcx. mk_ty ( ty:: Param ( ty:: ParamTy {
390
- index : ty_param. index ,
391
- name : ty_param. name ,
342
+ // In our example, requires that Self: 'a
343
+ if ty_known_to_outlive ( tcx, id, param_env, & wf_tys, * ty, * region) {
344
+ debug ! ( ?ty_idx, ?region_idx) ;
345
+ debug ! ( "required clause: {} must outlive {}" , ty, region) ;
346
+ // Translate into the generic parameters of the GAT. In
347
+ // our example, the type was Self, which will also be
348
+ // Self in the GAT.
349
+ let ty_param = generics. param_at ( * ty_idx, tcx) ;
350
+ let ty_param = tcx. mk_ty ( ty:: Param ( ty:: ParamTy {
351
+ index : ty_param. index ,
352
+ name : ty_param. name ,
353
+ } ) ) ;
354
+ // Same for the region. In our example, 'a corresponds
355
+ // to the 'me parameter.
356
+ let region_param = generics. param_at ( * region_idx, tcx) ;
357
+ let region_param =
358
+ tcx. mk_region ( ty:: RegionKind :: ReEarlyBound ( ty:: EarlyBoundRegion {
359
+ def_id : region_param. def_id ,
360
+ index : region_param. index ,
361
+ name : region_param. name ,
392
362
} ) ) ;
393
- // Same for the region. In our example, 'a corresponds
394
- // to the 'me parameter.
395
- let region_param = generics. param_at ( * region_idx, tcx) ;
396
- let region_param =
397
- tcx. mk_region ( ty:: RegionKind :: ReEarlyBound ( ty:: EarlyBoundRegion {
398
- def_id : region_param. def_id ,
399
- index : region_param. index ,
400
- name : region_param. name ,
401
- } ) ) ;
402
- // The predicate we expect to see. (In our example,
403
- // `Self: 'me`.)
404
- let clause = ty:: PredicateKind :: TypeOutlives ( ty:: OutlivesPredicate (
405
- ty_param,
406
- region_param,
407
- ) ) ;
408
- let clause = tcx. mk_predicate ( ty:: Binder :: dummy ( clause) ) ;
409
- function_clauses. insert ( clause) ;
410
- }
411
- } ) ;
363
+ // The predicate we expect to see. (In our example,
364
+ // `Self: 'me`.)
365
+ let clause = ty:: PredicateKind :: TypeOutlives ( ty:: OutlivesPredicate (
366
+ ty_param,
367
+ region_param,
368
+ ) ) ;
369
+ let clause = tcx. mk_predicate ( ty:: Binder :: dummy ( clause) ) ;
370
+ function_clauses. insert ( clause) ;
371
+ }
412
372
}
413
373
}
414
374
@@ -422,62 +382,33 @@ fn check_gat_where_clauses(
422
382
continue ;
423
383
}
424
384
425
- // Unfortunately, we have to use a new `InferCtxt` for each
426
- // pair, because region constraints get added and solved there,
427
- // and we need to test each pair individually.
428
- tcx. infer_ctxt ( ) . enter ( |infcx| {
429
- let mut outlives_environment = OutlivesEnvironment :: new ( param_env) ;
430
- outlives_environment. add_implied_bounds ( & infcx, wf_tys. clone ( ) , id, DUMMY_SP ) ;
431
- outlives_environment. save_implied_bounds ( id) ;
432
-
433
- let cause =
434
- ObligationCause :: new ( DUMMY_SP , id, ObligationCauseCode :: MiscObligation ) ;
435
-
436
- let origin = SubregionOrigin :: from_obligation_cause ( & cause, || {
437
- infer:: RelateRegionParamBound ( cause. span )
438
- } ) ;
439
-
440
- use rustc_infer:: infer:: outlives:: obligations:: TypeOutlivesDelegate ;
441
- ( & infcx) . push_sub_region_constraint ( origin, region_a, region_b) ;
442
-
443
- let errors = infcx. resolve_regions (
444
- trait_item. def_id . to_def_id ( ) ,
445
- & outlives_environment,
446
- RegionckMode :: default ( ) ,
447
- ) ;
448
-
449
- debug ! ( ?errors, "errors" ) ;
450
-
451
- // If we were able to prove that Self: 'a without an error,
452
- // it must be because of the implied or explicit bounds...
453
- if errors. is_empty ( ) {
454
- debug ! ( ?region_a_idx, ?region_b_idx) ;
455
- debug ! ( "required clause: {} must outlive {}" , region_a, region_b) ;
456
- // Translate into the generic parameters of the GAT.
457
- let region_a_param = generics. param_at ( * region_a_idx, tcx) ;
458
- let region_a_param =
459
- tcx. mk_region ( ty:: RegionKind :: ReEarlyBound ( ty:: EarlyBoundRegion {
460
- def_id : region_a_param. def_id ,
461
- index : region_a_param. index ,
462
- name : region_a_param. name ,
463
- } ) ) ;
464
- // Same for the region.
465
- let region_b_param = generics. param_at ( * region_b_idx, tcx) ;
466
- let region_b_param =
467
- tcx. mk_region ( ty:: RegionKind :: ReEarlyBound ( ty:: EarlyBoundRegion {
468
- def_id : region_b_param. def_id ,
469
- index : region_b_param. index ,
470
- name : region_b_param. name ,
471
- } ) ) ;
472
- // The predicate we expect to see.
473
- let clause = ty:: PredicateKind :: RegionOutlives ( ty:: OutlivesPredicate (
474
- region_a_param,
475
- region_b_param,
476
- ) ) ;
477
- let clause = tcx. mk_predicate ( ty:: Binder :: dummy ( clause) ) ;
478
- function_clauses. insert ( clause) ;
479
- }
480
- } ) ;
385
+ if region_known_to_outlive ( tcx, id, param_env, & wf_tys, * region_a, * region_b) {
386
+ debug ! ( ?region_a_idx, ?region_b_idx) ;
387
+ debug ! ( "required clause: {} must outlive {}" , region_a, region_b) ;
388
+ // Translate into the generic parameters of the GAT.
389
+ let region_a_param = generics. param_at ( * region_a_idx, tcx) ;
390
+ let region_a_param =
391
+ tcx. mk_region ( ty:: RegionKind :: ReEarlyBound ( ty:: EarlyBoundRegion {
392
+ def_id : region_a_param. def_id ,
393
+ index : region_a_param. index ,
394
+ name : region_a_param. name ,
395
+ } ) ) ;
396
+ // Same for the region.
397
+ let region_b_param = generics. param_at ( * region_b_idx, tcx) ;
398
+ let region_b_param =
399
+ tcx. mk_region ( ty:: RegionKind :: ReEarlyBound ( ty:: EarlyBoundRegion {
400
+ def_id : region_b_param. def_id ,
401
+ index : region_b_param. index ,
402
+ name : region_b_param. name ,
403
+ } ) ) ;
404
+ // The predicate we expect to see.
405
+ let clause = ty:: PredicateKind :: RegionOutlives ( ty:: OutlivesPredicate (
406
+ region_a_param,
407
+ region_b_param,
408
+ ) ) ;
409
+ let clause = tcx. mk_predicate ( ty:: Binder :: dummy ( clause) ) ;
410
+ function_clauses. insert ( clause) ;
411
+ }
481
412
}
482
413
}
483
414
@@ -530,6 +461,96 @@ fn check_gat_where_clauses(
530
461
}
531
462
}
532
463
464
+ /// Given a known `param_env` and a set of well formed types, can we prove that
465
+ /// `ty` outlives `region`.
466
+ fn ty_known_to_outlive < ' tcx > (
467
+ tcx : TyCtxt < ' tcx > ,
468
+ id : hir:: HirId ,
469
+ param_env : ty:: ParamEnv < ' tcx > ,
470
+ wf_tys : & FxHashSet < Ty < ' tcx > > ,
471
+ ty : Ty < ' tcx > ,
472
+ region : ty:: Region < ' tcx > ,
473
+ ) -> bool {
474
+ // Unfortunately, we have to use a new `InferCtxt` each call, because
475
+ // region constraints get added and solved there and we need to test each
476
+ // call individually.
477
+ tcx. infer_ctxt ( ) . enter ( |infcx| {
478
+ let mut outlives_environment = OutlivesEnvironment :: new ( param_env) ;
479
+ outlives_environment. add_implied_bounds ( & infcx, wf_tys. clone ( ) , id, DUMMY_SP ) ;
480
+ outlives_environment. save_implied_bounds ( id) ;
481
+ let region_bound_pairs = outlives_environment. region_bound_pairs_map ( ) . get ( & id) . unwrap ( ) ;
482
+
483
+ let cause = ObligationCause :: new ( DUMMY_SP , id, ObligationCauseCode :: MiscObligation ) ;
484
+
485
+ let sup_type = ty;
486
+ let sub_region = region;
487
+
488
+ let origin = SubregionOrigin :: from_obligation_cause ( & cause, || {
489
+ infer:: RelateParamBound ( cause. span , sup_type, None )
490
+ } ) ;
491
+
492
+ let outlives = & mut TypeOutlives :: new (
493
+ & infcx,
494
+ tcx,
495
+ & region_bound_pairs,
496
+ Some ( infcx. tcx . lifetimes . re_root_empty ) ,
497
+ param_env,
498
+ ) ;
499
+ outlives. type_must_outlive ( origin, sup_type, sub_region) ;
500
+
501
+ let errors = infcx. resolve_regions (
502
+ id. expect_owner ( ) . to_def_id ( ) ,
503
+ & outlives_environment,
504
+ RegionckMode :: default ( ) ,
505
+ ) ;
506
+
507
+ debug ! ( ?errors, "errors" ) ;
508
+
509
+ // If we were able to prove that the type outlives the region without
510
+ // an error, it must be because of the implied or explicit bounds...
511
+ errors. is_empty ( )
512
+ } )
513
+ }
514
+
515
+ fn region_known_to_outlive < ' tcx > (
516
+ tcx : TyCtxt < ' tcx > ,
517
+ id : hir:: HirId ,
518
+ param_env : ty:: ParamEnv < ' tcx > ,
519
+ wf_tys : & FxHashSet < Ty < ' tcx > > ,
520
+ region_a : ty:: Region < ' tcx > ,
521
+ region_b : ty:: Region < ' tcx > ,
522
+ ) -> bool {
523
+ // Unfortunately, we have to use a new `InferCtxt` each call, because
524
+ // region constraints get added and solved there and we need to test each
525
+ // call individually.
526
+ tcx. infer_ctxt ( ) . enter ( |infcx| {
527
+ let mut outlives_environment = OutlivesEnvironment :: new ( param_env) ;
528
+ outlives_environment. add_implied_bounds ( & infcx, wf_tys. clone ( ) , id, DUMMY_SP ) ;
529
+ outlives_environment. save_implied_bounds ( id) ;
530
+
531
+ let cause = ObligationCause :: new ( DUMMY_SP , id, ObligationCauseCode :: MiscObligation ) ;
532
+
533
+ let origin = SubregionOrigin :: from_obligation_cause ( & cause, || {
534
+ infer:: RelateRegionParamBound ( cause. span )
535
+ } ) ;
536
+
537
+ use rustc_infer:: infer:: outlives:: obligations:: TypeOutlivesDelegate ;
538
+ ( & infcx) . push_sub_region_constraint ( origin, region_a, region_b) ;
539
+
540
+ let errors = infcx. resolve_regions (
541
+ id. expect_owner ( ) . to_def_id ( ) ,
542
+ & outlives_environment,
543
+ RegionckMode :: default ( ) ,
544
+ ) ;
545
+
546
+ debug ! ( ?errors, "errors" ) ;
547
+
548
+ // If we were able to prove that the type outlives the region without
549
+ // an error, it must be because of the implied or explicit bounds...
550
+ errors. is_empty ( )
551
+ } )
552
+ }
553
+
533
554
/// TypeVisitor that looks for uses of GATs like
534
555
/// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into
535
556
/// the two vectors, `regions` and `types` (depending on their kind). For each
0 commit comments