@@ -38,8 +38,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
38
38
use rustc_middle:: ty:: relate:: { self , Relate , RelateResult , TypeRelation } ;
39
39
use rustc_middle:: ty:: subst:: SubstsRef ;
40
40
use rustc_middle:: ty:: {
41
- self , FallibleTypeFolder , InferConst , Ty , TyCtxt , TypeFoldable , TypeSuperFoldable ,
42
- TypeVisitable ,
41
+ self , AliasKind , FallibleTypeFolder , InferConst , ToPredicate , Ty , TyCtxt , TypeFoldable ,
42
+ TypeSuperFoldable , TypeVisitable ,
43
43
} ;
44
44
use rustc_middle:: ty:: { IntType , UintType } ;
45
45
use rustc_span:: { Span , DUMMY_SP } ;
@@ -74,7 +74,7 @@ impl<'tcx> InferCtxt<'tcx> {
74
74
b : Ty < ' tcx > ,
75
75
) -> RelateResult < ' tcx , Ty < ' tcx > >
76
76
where
77
- R : TypeRelation < ' tcx > ,
77
+ R : ObligationEmittingRelation < ' tcx > ,
78
78
{
79
79
let a_is_expected = relation. a_is_expected ( ) ;
80
80
@@ -122,6 +122,15 @@ impl<'tcx> InferCtxt<'tcx> {
122
122
Err ( TypeError :: Sorts ( ty:: relate:: expected_found ( relation, a, b) ) )
123
123
}
124
124
125
+ ( ty:: Alias ( AliasKind :: Projection , _) , _) if self . tcx . trait_solver_next ( ) => {
126
+ relation. register_type_equate_obligation ( a. into ( ) , b. into ( ) ) ;
127
+ Ok ( b)
128
+ }
129
+ ( _, ty:: Alias ( AliasKind :: Projection , _) ) if self . tcx . trait_solver_next ( ) => {
130
+ relation. register_type_equate_obligation ( b. into ( ) , a. into ( ) ) ;
131
+ Ok ( a)
132
+ }
133
+
125
134
_ => ty:: relate:: super_relate_tys ( relation, a, b) ,
126
135
}
127
136
}
@@ -133,7 +142,7 @@ impl<'tcx> InferCtxt<'tcx> {
133
142
b : ty:: Const < ' tcx > ,
134
143
) -> RelateResult < ' tcx , ty:: Const < ' tcx > >
135
144
where
136
- R : ConstEquateRelation < ' tcx > ,
145
+ R : ObligationEmittingRelation < ' tcx > ,
137
146
{
138
147
debug ! ( "{}.consts({:?}, {:?})" , relation. tag( ) , a, b) ;
139
148
if a == b {
@@ -169,15 +178,15 @@ impl<'tcx> InferCtxt<'tcx> {
169
178
// FIXME(#59490): Need to remove the leak check to accommodate
170
179
// escaping bound variables here.
171
180
if !a. has_escaping_bound_vars ( ) && !b. has_escaping_bound_vars ( ) {
172
- relation. const_equate_obligation ( a, b) ;
181
+ relation. register_const_equate_obligation ( a, b) ;
173
182
}
174
183
return Ok ( b) ;
175
184
}
176
185
( _, ty:: ConstKind :: Unevaluated ( ..) ) if self . tcx . lazy_normalization ( ) => {
177
186
// FIXME(#59490): Need to remove the leak check to accommodate
178
187
// escaping bound variables here.
179
188
if !a. has_escaping_bound_vars ( ) && !b. has_escaping_bound_vars ( ) {
180
- relation. const_equate_obligation ( a, b) ;
189
+ relation. register_const_equate_obligation ( a, b) ;
181
190
}
182
191
return Ok ( a) ;
183
192
}
@@ -435,32 +444,21 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
435
444
Ok ( Generalization { ty, needs_wf } )
436
445
}
437
446
438
- pub fn add_const_equate_obligation (
447
+ pub fn register_obligations ( & mut self , obligations : PredicateObligations < ' tcx > ) {
448
+ self . obligations . extend ( obligations. into_iter ( ) ) ;
449
+ }
450
+
451
+ pub fn register_predicates (
439
452
& mut self ,
440
- a_is_expected : bool ,
441
- a : ty:: Const < ' tcx > ,
442
- b : ty:: Const < ' tcx > ,
453
+ obligations : impl IntoIterator < Item = impl ToPredicate < ' tcx > > ,
443
454
) {
444
- let predicate = if a_is_expected {
445
- ty:: PredicateKind :: ConstEquate ( a, b)
446
- } else {
447
- ty:: PredicateKind :: ConstEquate ( b, a)
448
- } ;
449
- self . obligations . push ( Obligation :: new (
450
- self . tcx ( ) ,
451
- self . trace . cause . clone ( ) ,
452
- self . param_env ,
453
- ty:: Binder :: dummy ( predicate) ,
454
- ) ) ;
455
+ self . obligations . extend ( obligations. into_iter ( ) . map ( |to_pred| {
456
+ Obligation :: new ( self . infcx . tcx , self . trace . cause . clone ( ) , self . param_env , to_pred)
457
+ } ) )
455
458
}
456
459
457
460
pub fn mark_ambiguous ( & mut self ) {
458
- self . obligations . push ( Obligation :: new (
459
- self . tcx ( ) ,
460
- self . trace . cause . clone ( ) ,
461
- self . param_env ,
462
- ty:: Binder :: dummy ( ty:: PredicateKind :: Ambiguous ) ,
463
- ) ) ;
461
+ self . register_predicates ( [ ty:: Binder :: dummy ( ty:: PredicateKind :: Ambiguous ) ] ) ;
464
462
}
465
463
}
466
464
@@ -779,11 +777,42 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
779
777
}
780
778
}
781
779
782
- pub trait ConstEquateRelation < ' tcx > : TypeRelation < ' tcx > {
780
+ pub trait ObligationEmittingRelation < ' tcx > : TypeRelation < ' tcx > {
781
+ /// Register obligations that must hold in order for this relation to hold
782
+ fn register_obligations ( & mut self , obligations : PredicateObligations < ' tcx > ) ;
783
+
784
+ /// Register predicates that must hold in order for this relation to hold. Uses
785
+ /// a default obligation cause, [`ObligationEmittingRelation::register_obligations`] should
786
+ /// be used if control over the obligaton causes is required.
787
+ fn register_predicates (
788
+ & mut self ,
789
+ obligations : impl IntoIterator < Item = impl ToPredicate < ' tcx > > ,
790
+ ) ;
791
+
783
792
/// Register an obligation that both constants must be equal to each other.
784
793
///
785
794
/// If they aren't equal then the relation doesn't hold.
786
- fn const_equate_obligation ( & mut self , a : ty:: Const < ' tcx > , b : ty:: Const < ' tcx > ) ;
795
+ fn register_const_equate_obligation ( & mut self , a : ty:: Const < ' tcx > , b : ty:: Const < ' tcx > ) {
796
+ let ( a, b) = if self . a_is_expected ( ) { ( a, b) } else { ( b, a) } ;
797
+
798
+ self . register_predicates ( [ ty:: Binder :: dummy ( if self . tcx ( ) . trait_solver_next ( ) {
799
+ ty:: PredicateKind :: AliasEq ( a. into ( ) , b. into ( ) )
800
+ } else {
801
+ ty:: PredicateKind :: ConstEquate ( a, b)
802
+ } ) ] ) ;
803
+ }
804
+
805
+ /// Register an obligation that both types must be equal to each other.
806
+ ///
807
+ /// If they aren't equal then the relation doesn't hold.
808
+ fn register_type_equate_obligation ( & mut self , a : Ty < ' tcx > , b : Ty < ' tcx > ) {
809
+ let ( a, b) = if self . a_is_expected ( ) { ( a, b) } else { ( b, a) } ;
810
+
811
+ self . register_predicates ( [ ty:: Binder :: dummy ( ty:: PredicateKind :: AliasEq (
812
+ a. into ( ) ,
813
+ b. into ( ) ,
814
+ ) ) ] ) ;
815
+ }
787
816
}
788
817
789
818
fn int_unification_error < ' tcx > (
0 commit comments