@@ -69,6 +69,15 @@ pub struct RegionInferenceContext<'tcx> {
6969 /// visible from this index.
7070 scc_universes : IndexVec < ConstraintSccIndex , ty:: UniverseIndex > ,
7171
72+ /// Contains a "representative" from each SCC. This will be the
73+ /// minimal RegionVid belonging to that universe. It is used as a
74+ /// kind of hacky way to manage checking outlives relationships,
75+ /// since we can 'canonicalize' each region to the representative
76+ /// of its SCC and be sure that -- if they have the same repr --
77+ /// they *must* be equal (though not having the same repr does not
78+ /// mean they are unequal).
79+ scc_representatives : IndexVec < ConstraintSccIndex , ty:: RegionVid > ,
80+
7281 /// The final inferred values of the region variables; we compute
7382 /// one value per SCC. To get the value for any given *region*,
7483 /// you first find which scc it is a part of.
@@ -208,13 +217,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
208217
209218 let scc_universes = Self :: compute_scc_universes ( & constraint_sccs, & definitions) ;
210219
220+ let scc_representatives = Self :: compute_scc_representatives ( & constraint_sccs, & definitions) ;
221+
211222 let mut result = Self {
212223 definitions,
213224 liveness_constraints,
214225 constraints,
215226 constraint_graph,
216227 constraint_sccs,
217228 scc_universes,
229+ scc_representatives,
218230 scc_values,
219231 type_tests,
220232 universal_regions,
@@ -251,6 +263,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
251263 scc_universes
252264 }
253265
266+ /// For each SCC, we compute a unique `RegionVid` (in fact, the
267+ /// minimal one that belongs to the SCC). See
268+ /// `scc_representatives` field of `RegionInferenceContext` for
269+ /// more details.
270+ fn compute_scc_representatives (
271+ constraints_scc : & Sccs < RegionVid , ConstraintSccIndex > ,
272+ definitions : & IndexVec < RegionVid , RegionDefinition < ' tcx > > ,
273+ ) -> IndexVec < ConstraintSccIndex , ty:: RegionVid > {
274+ let num_sccs = constraints_scc. num_sccs ( ) ;
275+ let next_region_vid = definitions. next_index ( ) ;
276+ let mut scc_representatives = IndexVec :: from_elem_n ( next_region_vid, num_sccs) ;
277+
278+ for region_vid in definitions. indices ( ) {
279+ let scc = constraints_scc. scc ( region_vid) ;
280+ let prev_min = scc_representatives[ scc] ;
281+ scc_representatives[ scc] = region_vid. min ( prev_min) ;
282+ }
283+
284+ scc_representatives
285+ }
286+
254287 /// Initializes the region variables for each universally
255288 /// quantified region (lifetime parameter). The first N variables
256289 /// always correspond to the regions appearing in the function
@@ -545,7 +578,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
545578 for type_test in & self . type_tests {
546579 debug ! ( "check_type_test: {:?}" , type_test) ;
547580
548- if self . eval_verify_bound ( mir, type_test. lower_bound , & type_test. verify_bound ) {
581+ let generic_ty = type_test. generic_kind . to_ty ( tcx) ;
582+ if self . eval_verify_bound (
583+ tcx,
584+ mir,
585+ generic_ty,
586+ type_test. lower_bound ,
587+ & type_test. verify_bound ,
588+ ) {
549589 continue ;
550590 }
551591
@@ -679,7 +719,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
679719 // where `ur` is a local bound -- we are sometimes in a
680720 // position to prove things that our caller cannot. See
681721 // #53570 for an example.
682- if self . eval_verify_bound ( mir, ur, & type_test. verify_bound ) {
722+ if self . eval_verify_bound ( tcx , mir, generic_ty , ur, & type_test. verify_bound ) {
683723 continue ;
684724 }
685725
@@ -853,7 +893,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
853893 /// `point`, and returns true or false.
854894 fn eval_verify_bound (
855895 & self ,
896+ tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
856897 mir : & Mir < ' tcx > ,
898+ generic_ty : Ty < ' tcx > ,
857899 lower_bound : RegionVid ,
858900 verify_bound : & VerifyBound < ' tcx > ,
859901 ) -> bool {
@@ -863,23 +905,85 @@ impl<'tcx> RegionInferenceContext<'tcx> {
863905 ) ;
864906
865907 match verify_bound {
866- VerifyBound :: IfEq ( ..) => false , // FIXME
908+ VerifyBound :: IfEq ( test_ty, verify_bound1) => {
909+ self . eval_if_eq ( tcx, mir, generic_ty, lower_bound, test_ty, verify_bound1)
910+ }
867911
868912 VerifyBound :: OutlivedBy ( r) => {
869913 let r_vid = self . to_region_vid ( r) ;
870914 self . eval_outlives ( mir, r_vid, lower_bound)
871915 }
872916
873- VerifyBound :: AnyBound ( verify_bounds) => verify_bounds
874- . iter ( )
875- . any ( |verify_bound| self . eval_verify_bound ( mir , lower_bound , verify_bound ) ) ,
917+ VerifyBound :: AnyBound ( verify_bounds) => verify_bounds. iter ( ) . any ( |verify_bound| {
918+ self . eval_verify_bound ( tcx , mir , generic_ty , lower_bound , verify_bound )
919+ } ) ,
876920
877- VerifyBound :: AllBounds ( verify_bounds) => verify_bounds
878- . iter ( )
879- . all ( |verify_bound| self . eval_verify_bound ( mir , lower_bound , verify_bound ) ) ,
921+ VerifyBound :: AllBounds ( verify_bounds) => verify_bounds. iter ( ) . all ( |verify_bound| {
922+ self . eval_verify_bound ( tcx , mir , generic_ty , lower_bound , verify_bound )
923+ } ) ,
880924 }
881925 }
882926
927+ fn eval_if_eq (
928+ & self ,
929+ tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
930+ mir : & Mir < ' tcx > ,
931+ generic_ty : Ty < ' tcx > ,
932+ lower_bound : RegionVid ,
933+ test_ty : Ty < ' tcx > ,
934+ verify_bound : & VerifyBound < ' tcx > ,
935+ ) -> bool {
936+ let generic_ty_normalized = self . normalize_to_scc_representatives ( tcx, generic_ty) ;
937+ let test_ty_normalized = self . normalize_to_scc_representatives ( tcx, test_ty) ;
938+ if generic_ty_normalized == test_ty_normalized {
939+ self . eval_verify_bound ( tcx, mir, generic_ty, lower_bound, verify_bound)
940+ } else {
941+ false
942+ }
943+ }
944+
945+ /// This is a conservative normalization procedure. It takes every
946+ /// free region in `value` and replaces it with the
947+ /// "representative" of its SCC (see `scc_representatives` field).
948+ /// We are guaranteed that if two values normalize to the same
949+ /// thing, then they are equal; this is a conservative check in
950+ /// that they could still be equal even if they normalize to
951+ /// different results. (For example, there might be two regions
952+ /// with the same value that are not in the same SCC).
953+ ///
954+ /// NB. This is not an ideal approach and I would like to revisit
955+ /// it. However, it works pretty well in practice. In particular,
956+ /// this is needed to deal with projection outlives bounds like
957+ ///
958+ /// <T as Foo<'0>>::Item: '1
959+ ///
960+ /// In particular, this routine winds up being important when
961+ /// there are bounds like `where <T as Foo<'a>>::Item: 'b` in the
962+ /// environment. In this case, if we can show that `'0 == 'a`,
963+ /// and that `'b: '1`, then we know that the clause is
964+ /// satisfied. In such cases, particularly due to limitations of
965+ /// the trait solver =), we usually wind up with a where-clause like
966+ /// `T: Foo<'a>` in scope, which thus forces `'0 == 'a` to be added as
967+ /// a constraint, and thus ensures that they are in the same SCC.
968+ ///
969+ /// So why can't we do a more correct routine? Well, we could
970+ /// *almost* use the `relate_tys` code, but the way it is
971+ /// currently setup it creates inference variables to deal with
972+ /// higher-ranked things and so forth, and right now the inference
973+ /// context is not permitted to make more inference variables. So
974+ /// we use this kind of hacky solution.
975+ fn normalize_to_scc_representatives < T > ( & self , tcx : TyCtxt < ' _ , ' _ , ' tcx > , value : T ) -> T
976+ where
977+ T : TypeFoldable < ' tcx > ,
978+ {
979+ tcx. fold_regions ( & value, & mut false , |r, _db| {
980+ let vid = self . to_region_vid ( r) ;
981+ let scc = self . constraint_sccs . scc ( vid) ;
982+ let repr = self . scc_representatives [ scc] ;
983+ tcx. mk_region ( ty:: ReVar ( repr) )
984+ } )
985+ }
986+
883987 // Evaluate whether `sup_region: sub_region @ point`.
884988 fn eval_outlives (
885989 & self ,
0 commit comments