@@ -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,7 +236,7 @@ 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 {
238240 match rhs. kind ( ) {
239241 // Start by checking whether the `rhs` type may unify with
240242 // pretty much everything. Just return `true` in that case.
@@ -273,8 +275,12 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
273275 | ty:: Placeholder ( _) => { }
274276 } ;
275277
278+ if self . cache . contains ( & ( lhs, rhs) ) {
279+ return true ;
280+ }
281+
276282 // For purely rigid types, use structural equivalence.
277- match lhs. kind ( ) {
283+ let may_unify = match lhs. kind ( ) {
278284 ty:: Ref ( _, lhs_ty, lhs_mutbl) => match rhs. kind ( ) {
279285 ty:: Ref ( _, rhs_ty, rhs_mutbl) => {
280286 lhs_mutbl == rhs_mutbl && self . types_may_unify ( lhs_ty, rhs_ty)
@@ -414,10 +420,16 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
414420 }
415421
416422 ty:: Error ( ..) => true ,
423+ } ;
424+
425+ if may_unify {
426+ self . cache . insert ( ( lhs, rhs) ) ;
417427 }
428+
429+ may_unify
418430 }
419431
420- pub fn consts_may_unify ( self , lhs : I :: Const , rhs : I :: Const ) -> bool {
432+ pub fn consts_may_unify ( & mut self , lhs : I :: Const , rhs : I :: Const ) -> bool {
421433 match rhs. kind ( ) {
422434 ty:: ConstKind :: Param ( _) => {
423435 if INSTANTIATE_RHS_WITH_INFER {
@@ -465,7 +477,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
465477 }
466478 }
467479
468- fn var_and_ty_may_unify ( self , var : ty:: InferTy , ty : I :: Ty ) -> bool {
480+ fn var_and_ty_may_unify ( & mut self , var : ty:: InferTy , ty : I :: Ty ) -> bool {
469481 if !ty. is_known_rigid ( ) {
470482 return true ;
471483 }
0 commit comments