@@ -339,76 +339,36 @@ fn check_gat_where_clauses(
339339 // reflected in a where clause on the GAT itself.
340340 for ( region, region_idx) in & visitor. regions {
341341 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 ,
392362 } ) ) ;
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+ }
412372 }
413373 }
414374
@@ -422,62 +382,33 @@ fn check_gat_where_clauses(
422382 continue ;
423383 }
424384
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+ }
481412 }
482413 }
483414
@@ -530,6 +461,96 @@ fn check_gat_where_clauses(
530461 }
531462}
532463
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+
533554/// TypeVisitor that looks for uses of GATs like
534555/// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into
535556/// the two vectors, `regions` and `types` (depending on their kind). For each
0 commit comments