@@ -12,10 +12,10 @@ use rustc_data_structures::fx::FxHashSet;
1212use rustc_data_structures:: graph:: scc:: { self , Sccs } ;
1313use rustc_index:: IndexVec ;
1414use rustc_infer:: infer:: NllRegionVariableOrigin ;
15- use rustc_infer:: infer:: outlives:: test_type_match:: MatchAgainstHigherRankedOutlives ;
1615use rustc_infer:: infer:: region_constraints:: { GenericKind , VarInfos , VerifyBound } ;
1716use rustc_infer:: infer:: relate:: TypeRelation ;
18- use rustc_middle:: ty:: { self , Region , RegionVid , TyCtxt , UniverseIndex } ;
17+ use rustc_middle:: ty:: relate:: { self , Relate , RelateResult } ;
18+ use rustc_middle:: ty:: { self , Region , RegionVid , Ty , TyCtxt , UniverseIndex } ;
1919use rustc_span:: Span ;
2020use tracing:: { debug, instrument, trace} ;
2121
@@ -627,33 +627,27 @@ fn rewrite_verify_bound<'t>(
627627 // are both empty. This bit ensures that whatever comes out of the
628628 // bound also matches the placeholder reachability of the lower bound.
629629 VerifyBound :: IfEq ( verify_if_eq_b) => {
630- let mut m = MatchAgainstHigherRankedOutlives :: new ( tcx) ;
630+ let mut m = MatchUniverses :: new ( tcx, sccs , scc_annotations , universal_regions ) ;
631631 let verify_if_eq = verify_if_eq_b. skip_binder ( ) ;
632- // We ignore the error here because we are not concerned with if the
633- // match actually held -- we can't tell that yet -- we just want to
634- // see if the resulting region can't match for universe-related
635- // reasons.
636- let _what_error = m . relate ( verify_if_eq . ty , generic_kind . to_ty ( tcx ) ) ;
632+ let what_error = m . relate ( verify_if_eq . ty , generic_kind . to_ty ( tcx ) ) ;
633+ if let Err ( e ) = what_error {
634+ debug ! ( "Type test {verify_if_eq_b:?} {generic_kind:?} failed to match with {e:?}" ) ;
635+ return Either :: Right ( RewrittenVerifyBound :: Unsatisfied ) ;
636+ }
637637
638- let r = if let ty:: RegionKind :: ReBound ( depth, br ) = verify_if_eq. bound . kind ( ) {
638+ let r = if let ty:: RegionKind :: ReBound ( depth, _ ) = verify_if_eq. bound . kind ( ) {
639639 assert ! ( depth == ty:: INNERMOST ) ;
640- match m. map . get ( & br) {
641- Some ( & r) => r,
642- None => tcx. lifetimes . re_static ,
643- }
640+ m. max_universe_region . map_or ( tcx. lifetimes . re_static , |pair| pair. 1 )
644641 } else {
645642 verify_if_eq. bound
646643 } ;
647644
648- let r_vid = universal_regions. to_region_vid ( r) ;
649- let r_scc = scc_annotations[ sccs. scc ( r_vid) ] ;
650645 let l_scc = scc_annotations[ lower_scc] ;
651- let in_same_universe =
652- r_scc. universe_compatible_with ( l_scc) && l_scc. universe_compatible_with ( r_scc) ;
653- let reaches_same_placeholders =
654- r_scc. reachable_placeholders == l_scc. reachable_placeholders ;
646+ let rvid = universal_regions. to_region_vid ( r) ;
655647
656- if in_same_universe && reaches_same_placeholders {
648+ if rvid == universal_regions. fr_static
649+ || scc_annotations[ sccs. scc ( rvid) ] . universe_compatible_with ( l_scc)
650+ {
657651 Either :: Left ( bound)
658652 } else {
659653 Either :: Right ( RewrittenVerifyBound :: Unsatisfied )
@@ -750,3 +744,122 @@ impl<'t> TypeTest<'t> {
750744 }
751745 }
752746}
747+
748+ impl < ' tcx , ' v > TypeRelation < TyCtxt < ' tcx > > for MatchUniverses < ' tcx , ' v > {
749+ fn cx ( & self ) -> TyCtxt < ' tcx > {
750+ self . tcx
751+ }
752+
753+ #[ instrument( level = "trace" , skip( self ) ) ]
754+ fn relate_with_variance < T : Relate < TyCtxt < ' tcx > > > (
755+ & mut self ,
756+ variance : ty:: Variance ,
757+ _: ty:: VarianceDiagInfo < TyCtxt < ' tcx > > ,
758+ a : T ,
759+ b : T ,
760+ ) -> RelateResult < ' tcx , T > {
761+ // Opaque types args have lifetime parameters.
762+ // We must not check them to be equal, as we never insert anything to make them so.
763+ if variance != ty:: Bivariant { self . relate ( a, b) } else { Ok ( a) }
764+ }
765+
766+ #[ instrument( skip( self ) , level = "trace" ) ]
767+ fn regions (
768+ & mut self ,
769+ pattern : ty:: Region < ' tcx > ,
770+ value : ty:: Region < ' tcx > ,
771+ ) -> RelateResult < ' tcx , ty:: Region < ' tcx > > {
772+ // `pattern` is from inside `VerifyBound::IfEq`, and `value` from `generic_kind` (what we're looking for).
773+ if pattern == value {
774+ self . update_max_universe ( pattern) ;
775+ } else {
776+ assert ! (
777+ pattern. is_bound( ) || self . universe_of( pattern) . is_root( ) ,
778+ "{pattern:?} neither bound nor in root universe. Universe is: {:?}, kind: {:?}" ,
779+ self . universe_of( pattern) ,
780+ pattern. kind( )
781+ ) ;
782+ }
783+
784+ if let Some ( ( _, max_universed_region) ) = self . max_universe_region . as_ref ( ) {
785+ Ok ( * max_universed_region)
786+ } else {
787+ Ok ( pattern)
788+ }
789+ }
790+
791+ #[ instrument( skip( self ) , level = "trace" ) ]
792+ fn tys ( & mut self , pattern : Ty < ' tcx > , value : Ty < ' tcx > ) -> RelateResult < ' tcx , Ty < ' tcx > > {
793+ relate:: structurally_relate_tys ( self , pattern, value)
794+ }
795+
796+ #[ instrument( skip( self ) , level = "trace" ) ]
797+ fn consts (
798+ & mut self ,
799+ pattern : ty:: Const < ' tcx > ,
800+ value : ty:: Const < ' tcx > ,
801+ ) -> RelateResult < ' tcx , ty:: Const < ' tcx > > {
802+ relate:: structurally_relate_consts ( self , pattern, value)
803+ }
804+
805+ #[ instrument( skip( self ) , level = "trace" ) ]
806+ fn binders < T > (
807+ & mut self ,
808+ pattern : ty:: Binder < ' tcx , T > ,
809+ value : ty:: Binder < ' tcx , T > ,
810+ ) -> RelateResult < ' tcx , ty:: Binder < ' tcx , T > >
811+ where
812+ T : Relate < TyCtxt < ' tcx > > ,
813+ {
814+ self . pattern_depth . shift_in ( 1 ) ;
815+ let result = Ok ( pattern. rebind ( self . relate ( pattern. skip_binder ( ) , value. skip_binder ( ) ) ?) ) ;
816+ self . pattern_depth . shift_out ( 1 ) ;
817+ result
818+ }
819+ }
820+
821+ struct MatchUniverses < ' tcx , ' v > {
822+ tcx : TyCtxt < ' tcx > ,
823+ pattern_depth : ty:: DebruijnIndex ,
824+ max_universe_region : Option < ( UniverseIndex , ty:: Region < ' tcx > ) > ,
825+ sccs : & ' v Sccs < RegionVid , ConstraintSccIndex > ,
826+ scc_annotations : & ' v IndexVec < ConstraintSccIndex , RegionTracker > ,
827+ universal_regions : & ' v UniversalRegions < ' tcx > ,
828+ }
829+
830+ impl < ' tcx , ' v > MatchUniverses < ' tcx , ' v > {
831+ fn new (
832+ tcx : TyCtxt < ' tcx > ,
833+ sccs : & ' v Sccs < RegionVid , ConstraintSccIndex > ,
834+ scc_annotations : & ' v IndexVec < ConstraintSccIndex , RegionTracker > ,
835+ universal_regions : & ' v UniversalRegions < ' tcx > ,
836+ ) -> MatchUniverses < ' tcx , ' v > {
837+ MatchUniverses {
838+ tcx,
839+ pattern_depth : ty:: INNERMOST ,
840+ max_universe_region : None ,
841+ scc_annotations,
842+ sccs,
843+ universal_regions,
844+ }
845+ }
846+
847+ fn universe_of ( & self , r : ty:: Region < ' tcx > ) -> UniverseIndex {
848+ self . scc_annotations [ self . sccs . scc ( self . universal_regions . to_region_vid ( r) ) ] . min_universe ( )
849+ }
850+
851+ #[ instrument( skip( self ) , level = "trace" ) ]
852+ fn update_max_universe ( & mut self , r : ty:: Region < ' tcx > ) {
853+ let r_universe = self . universe_of ( r) ;
854+
855+ let Some ( ( current_max_u, current_max_r) ) = self . max_universe_region else {
856+ self . max_universe_region = Some ( ( r_universe, r) ) ;
857+ return ;
858+ } ;
859+ self . max_universe_region = if r_universe > current_max_u {
860+ Some ( ( r_universe, r) )
861+ } else {
862+ Some ( ( current_max_u, current_max_r) )
863+ }
864+ }
865+ }
0 commit comments