@@ -11,6 +11,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas
11
11
#[ cfg( feature = "nightly" ) ]
12
12
use rustc_macros:: { HashStable_NoContext , TyDecodable , TyEncodable } ;
13
13
14
+ use crate :: data_structures:: DelayedSet ;
14
15
use crate :: inherent:: * ;
15
16
use crate :: visit:: TypeVisitableExt as _;
16
17
use crate :: { self as ty, Interner } ;
@@ -181,41 +182,42 @@ impl<DefId> SimplifiedType<DefId> {
181
182
/// We also use this function during coherence. For coherence the
182
183
/// impls only have to overlap for some value, so we treat parameters
183
184
/// on both sides like inference variables.
184
- #[ derive( Debug , Clone , Copy ) ]
185
+ #[ derive( Debug ) ]
185
186
pub struct DeepRejectCtxt <
186
187
I : Interner ,
187
188
const INSTANTIATE_LHS_WITH_INFER : bool ,
188
189
const INSTANTIATE_RHS_WITH_INFER : bool ,
189
190
> {
190
191
_interner : PhantomData < I > ,
192
+ cache : DelayedSet < ( I :: Ty , I :: Ty ) > ,
191
193
}
192
194
193
195
impl < I : Interner > DeepRejectCtxt < I , false , false > {
194
196
/// Treat parameters in both the lhs and the rhs as rigid.
195
197
pub fn relate_rigid_rigid ( _interner : I ) -> DeepRejectCtxt < I , false , false > {
196
- DeepRejectCtxt { _interner : PhantomData }
198
+ DeepRejectCtxt { _interner : PhantomData , cache : Default :: default ( ) }
197
199
}
198
200
}
199
201
200
202
impl < I : Interner > DeepRejectCtxt < I , true , true > {
201
203
/// Treat parameters in both the lhs and the rhs as infer vars.
202
204
pub fn relate_infer_infer ( _interner : I ) -> DeepRejectCtxt < I , true , true > {
203
- DeepRejectCtxt { _interner : PhantomData }
205
+ DeepRejectCtxt { _interner : PhantomData , cache : Default :: default ( ) }
204
206
}
205
207
}
206
208
207
209
impl < I : Interner > DeepRejectCtxt < I , false , true > {
208
210
/// Treat parameters in the lhs as rigid, and in rhs as infer vars.
209
211
pub fn relate_rigid_infer ( _interner : I ) -> DeepRejectCtxt < I , false , true > {
210
- DeepRejectCtxt { _interner : PhantomData }
212
+ DeepRejectCtxt { _interner : PhantomData , cache : Default :: default ( ) }
211
213
}
212
214
}
213
215
214
216
impl < I : Interner , const INSTANTIATE_LHS_WITH_INFER : bool , const INSTANTIATE_RHS_WITH_INFER : bool >
215
217
DeepRejectCtxt < I , INSTANTIATE_LHS_WITH_INFER , INSTANTIATE_RHS_WITH_INFER >
216
218
{
217
219
pub fn args_may_unify (
218
- self ,
220
+ & mut self ,
219
221
obligation_args : I :: GenericArgs ,
220
222
impl_args : I :: GenericArgs ,
221
223
) -> bool {
@@ -234,17 +236,32 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
234
236
} )
235
237
}
236
238
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
+
238
244
match rhs. kind ( ) {
239
245
// Start by checking whether the `rhs` type may unify with
240
246
// pretty much everything. Just return `true` in that case.
241
247
ty:: Param ( _) => {
242
248
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) ) ;
243
260
return true ;
261
+ } else {
262
+ return false ;
244
263
}
245
264
}
246
- ty:: Error ( _) | ty:: Alias ( ..) | ty:: Bound ( ..) => return true ,
247
- ty:: Infer ( var) => return self . var_and_ty_may_unify ( var, lhs) ,
248
265
249
266
// These types only unify with inference variables or their own
250
267
// variant.
@@ -274,7 +291,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
274
291
} ;
275
292
276
293
// For purely rigid types, use structural equivalence.
277
- match lhs. kind ( ) {
294
+ let may_unify = match lhs. kind ( ) {
278
295
ty:: Ref ( _, lhs_ty, lhs_mutbl) => match rhs. kind ( ) {
279
296
ty:: Ref ( _, rhs_ty, rhs_mutbl) => {
280
297
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_
414
431
}
415
432
416
433
ty:: Error ( ..) => true ,
434
+ } ;
435
+
436
+ if may_unify {
437
+ self . cache . insert ( ( lhs, rhs) ) ;
417
438
}
439
+
440
+ may_unify
418
441
}
419
442
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 {
421
444
match rhs. kind ( ) {
422
445
ty:: ConstKind :: Param ( _) => {
423
446
if INSTANTIATE_RHS_WITH_INFER {
@@ -465,7 +488,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
465
488
}
466
489
}
467
490
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 {
469
492
if !ty. is_known_rigid ( ) {
470
493
return true ;
471
494
}
0 commit comments