@@ -39,7 +39,7 @@ use rustc_hir::def_id::DefId;
3939use rustc_middle:: ty:: error:: TypeError ;
4040use rustc_middle:: ty:: relate:: { self , Relate , RelateResult , TypeRelation } ;
4141use rustc_middle:: ty:: subst:: SubstsRef ;
42- use rustc_middle:: ty:: { self , InferConst , Ty , TyCtxt } ;
42+ use rustc_middle:: ty:: { self , InferConst , Ty , TyCtxt , TypeFoldable } ;
4343use rustc_middle:: ty:: { IntType , UintType } ;
4444use rustc_span:: { Span , DUMMY_SP } ;
4545
@@ -126,7 +126,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
126126 b : & ' tcx ty:: Const < ' tcx > ,
127127 ) -> RelateResult < ' tcx , & ' tcx ty:: Const < ' tcx > >
128128 where
129- R : TypeRelation < ' tcx > ,
129+ R : ConstEquateRelation < ' tcx > ,
130130 {
131131 debug ! ( "{}.consts({:?}, {:?})" , relation. tag( ) , a, b) ;
132132 if a == b {
@@ -164,7 +164,22 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
164164 ( _, ty:: ConstKind :: Infer ( InferConst :: Var ( vid) ) ) => {
165165 return self . unify_const_variable ( !a_is_expected, vid, a) ;
166166 }
167-
167+ ( ty:: ConstKind :: Unevaluated ( ..) , _) if self . tcx . lazy_normalization ( ) => {
168+ // FIXME(#59490): Need to remove the leak check to accomodate
169+ // escaping bound variables here.
170+ if !a. has_escaping_bound_vars ( ) && !b. has_escaping_bound_vars ( ) {
171+ relation. const_equate_obligation ( a, b) ;
172+ }
173+ return Ok ( b) ;
174+ }
175+ ( _, ty:: ConstKind :: Unevaluated ( ..) ) if self . tcx . lazy_normalization ( ) => {
176+ // FIXME(#59490): Need to remove the leak check to accomodate
177+ // escaping bound variables here.
178+ if !a. has_escaping_bound_vars ( ) && !b. has_escaping_bound_vars ( ) {
179+ relation. const_equate_obligation ( a, b) ;
180+ }
181+ return Ok ( a) ;
182+ }
168183 _ => { }
169184 }
170185
@@ -375,6 +390,20 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
375390 debug ! ( "generalize: success {{ {:?}, {:?} }}" , ty, needs_wf) ;
376391 Ok ( Generalization { ty, needs_wf } )
377392 }
393+
394+ pub fn add_const_equate_obligation (
395+ & mut self ,
396+ a_is_expected : bool ,
397+ a : & ' tcx ty:: Const < ' tcx > ,
398+ b : & ' tcx ty:: Const < ' tcx > ,
399+ ) {
400+ let predicate = if a_is_expected {
401+ ty:: Predicate :: ConstEquate ( a, b)
402+ } else {
403+ ty:: Predicate :: ConstEquate ( b, a)
404+ } ;
405+ self . obligations . push ( Obligation :: new ( self . trace . cause . clone ( ) , self . param_env , predicate) ) ;
406+ }
378407}
379408
380409struct Generalizer < ' cx , ' tcx > {
@@ -637,11 +666,19 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
637666 }
638667 }
639668 }
669+ ty:: ConstKind :: Unevaluated ( ..) if self . tcx ( ) . lazy_normalization ( ) => Ok ( c) ,
640670 _ => relate:: super_relate_consts ( self , c, c) ,
641671 }
642672 }
643673}
644674
675+ pub trait ConstEquateRelation < ' tcx > : TypeRelation < ' tcx > {
676+ /// Register an obligation that both constants must be equal to each other.
677+ ///
678+ /// If they aren't equal then the relation doesn't hold.
679+ fn const_equate_obligation ( & mut self , a : & ' tcx ty:: Const < ' tcx > , b : & ' tcx ty:: Const < ' tcx > ) ;
680+ }
681+
645682pub trait RelateResultCompare < ' tcx , T > {
646683 fn compare < F > ( & self , t : T , f : F ) -> RelateResult < ' tcx , T >
647684 where
0 commit comments