@@ -12,10 +12,10 @@ use rustc_data_structures::fx::FxHashSet;
12
12
use rustc_data_structures:: graph:: scc:: { self , Sccs } ;
13
13
use rustc_index:: IndexVec ;
14
14
use rustc_infer:: infer:: NllRegionVariableOrigin ;
15
- use rustc_infer:: infer:: outlives:: test_type_match:: MatchAgainstHigherRankedOutlives ;
16
15
use rustc_infer:: infer:: region_constraints:: { GenericKind , VarInfos , VerifyBound } ;
17
16
use 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 } ;
19
19
use rustc_span:: Span ;
20
20
use tracing:: { debug, instrument, trace} ;
21
21
@@ -627,33 +627,27 @@ fn rewrite_verify_bound<'t>(
627
627
// are both empty. This bit ensures that whatever comes out of the
628
628
// bound also matches the placeholder reachability of the lower bound.
629
629
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 ) ;
631
631
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
+ }
637
637
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 ( ) {
639
639
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 )
644
641
} else {
645
642
verify_if_eq. bound
646
643
} ;
647
644
648
- let r_vid = universal_regions. to_region_vid ( r) ;
649
- let r_scc = scc_annotations[ sccs. scc ( r_vid) ] ;
650
645
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) ;
655
647
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
+ {
657
651
Either :: Left ( bound)
658
652
} else {
659
653
Either :: Right ( RewrittenVerifyBound :: Unsatisfied )
@@ -750,3 +744,122 @@ impl<'t> TypeTest<'t> {
750
744
}
751
745
}
752
746
}
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