@@ -11,6 +11,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas
1111#[ cfg( feature = "nightly" ) ]
1212use rustc_macros:: { HashStable_NoContext , TyDecodable , TyEncodable } ;
1313
14+ use crate :: data_structures:: DelayedSet ;
1415use crate :: inherent:: * ;
1516use crate :: visit:: TypeVisitableExt as _;
1617use crate :: { self as ty, Interner } ;
@@ -181,41 +182,42 @@ impl<DefId> SimplifiedType<DefId> {
181182/// We also use this function during coherence. For coherence the
182183/// impls only have to overlap for some value, so we treat parameters
183184/// on both sides like inference variables.
184- #[ derive( Debug , Clone , Copy ) ]
185+ #[ derive( Debug ) ]
185186pub struct DeepRejectCtxt <
186187 I : Interner ,
187188 const INSTANTIATE_LHS_WITH_INFER : bool ,
188189 const INSTANTIATE_RHS_WITH_INFER : bool ,
189190> {
190191 _interner : PhantomData < I > ,
192+ cache : DelayedSet < ( I :: Ty , I :: Ty ) > ,
191193}
192194
193195impl < I : Interner > DeepRejectCtxt < I , false , false > {
194196 /// Treat parameters in both the lhs and the rhs as rigid.
195197 pub fn relate_rigid_rigid ( _interner : I ) -> DeepRejectCtxt < I , false , false > {
196- DeepRejectCtxt { _interner : PhantomData }
198+ DeepRejectCtxt { _interner : PhantomData , cache : Default :: default ( ) }
197199 }
198200}
199201
200202impl < I : Interner > DeepRejectCtxt < I , true , true > {
201203 /// Treat parameters in both the lhs and the rhs as infer vars.
202204 pub fn relate_infer_infer ( _interner : I ) -> DeepRejectCtxt < I , true , true > {
203- DeepRejectCtxt { _interner : PhantomData }
205+ DeepRejectCtxt { _interner : PhantomData , cache : Default :: default ( ) }
204206 }
205207}
206208
207209impl < I : Interner > DeepRejectCtxt < I , false , true > {
208210 /// Treat parameters in the lhs as rigid, and in rhs as infer vars.
209211 pub fn relate_rigid_infer ( _interner : I ) -> DeepRejectCtxt < I , false , true > {
210- DeepRejectCtxt { _interner : PhantomData }
212+ DeepRejectCtxt { _interner : PhantomData , cache : Default :: default ( ) }
211213 }
212214}
213215
214216impl < I : Interner , const INSTANTIATE_LHS_WITH_INFER : bool , const INSTANTIATE_RHS_WITH_INFER : bool >
215217 DeepRejectCtxt < I , INSTANTIATE_LHS_WITH_INFER , INSTANTIATE_RHS_WITH_INFER >
216218{
217219 pub fn args_may_unify (
218- self ,
220+ & mut self ,
219221 obligation_args : I :: GenericArgs ,
220222 impl_args : I :: GenericArgs ,
221223 ) -> bool {
@@ -234,17 +236,32 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
234236 } )
235237 }
236238
237- pub fn types_may_unify ( self , lhs : I :: Ty , rhs : I :: Ty ) -> bool {
239+ pub fn types_may_unify ( & mut self , lhs : I :: Ty , rhs : I :: Ty ) -> bool {
240+ if self . cache . contains ( & ( lhs, rhs) ) {
241+ return true ;
242+ }
243+
238244 match rhs. kind ( ) {
239245 // Start by checking whether the `rhs` type may unify with
240246 // pretty much everything. Just return `true` in that case.
241247 ty:: Param ( _) => {
242248 if INSTANTIATE_RHS_WITH_INFER {
249+ self . cache . insert ( ( lhs, rhs) ) ;
250+ return true ;
251+ }
252+ }
253+ ty:: Error ( _) | ty:: Alias ( ..) | ty:: Bound ( ..) => {
254+ self . cache . insert ( ( lhs, rhs) ) ;
255+ return true ;
256+ }
257+ ty:: Infer ( var) => {
258+ if self . var_and_ty_may_unify ( var, lhs) {
259+ self . cache . insert ( ( lhs, rhs) ) ;
243260 return true ;
261+ } else {
262+ return false ;
244263 }
245264 }
246- ty:: Error ( _) | ty:: Alias ( ..) | ty:: Bound ( ..) => return true ,
247- ty:: Infer ( var) => return self . var_and_ty_may_unify ( var, lhs) ,
248265
249266 // These types only unify with inference variables or their own
250267 // variant.
@@ -274,7 +291,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
274291 } ;
275292
276293 // For purely rigid types, use structural equivalence.
277- match lhs. kind ( ) {
294+ let may_unify = match lhs. kind ( ) {
278295 ty:: Ref ( _, lhs_ty, lhs_mutbl) => match rhs. kind ( ) {
279296 ty:: Ref ( _, rhs_ty, rhs_mutbl) => {
280297 lhs_mutbl == rhs_mutbl && self . types_may_unify ( lhs_ty, rhs_ty)
@@ -414,10 +431,16 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
414431 }
415432
416433 ty:: Error ( ..) => true ,
434+ } ;
435+
436+ if may_unify {
437+ self . cache . insert ( ( lhs, rhs) ) ;
417438 }
439+
440+ may_unify
418441 }
419442
420- pub fn consts_may_unify ( self , lhs : I :: Const , rhs : I :: Const ) -> bool {
443+ pub fn consts_may_unify ( & mut self , lhs : I :: Const , rhs : I :: Const ) -> bool {
421444 match rhs. kind ( ) {
422445 ty:: ConstKind :: Param ( _) => {
423446 if INSTANTIATE_RHS_WITH_INFER {
@@ -465,7 +488,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
465488 }
466489 }
467490
468- fn var_and_ty_may_unify ( self , var : ty:: InferTy , ty : I :: Ty ) -> bool {
491+ fn var_and_ty_may_unify ( & mut self , var : ty:: InferTy , ty : I :: Ty ) -> bool {
469492 if !ty. is_known_rigid ( ) {
470493 return true ;
471494 }
0 commit comments