@@ -181,41 +181,46 @@ impl<DefId> SimplifiedType<DefId> {
181
181
/// We also use this function during coherence. For coherence the
182
182
/// impls only have to overlap for some value, so we treat parameters
183
183
/// on both sides like inference variables.
184
- #[ derive( Debug , Clone , Copy ) ]
184
+ #[ derive( Debug , Clone ) ]
185
185
pub struct DeepRejectCtxt <
186
186
I : Interner ,
187
187
const INSTANTIATE_LHS_WITH_INFER : bool ,
188
188
const INSTANTIATE_RHS_WITH_INFER : bool ,
189
189
> {
190
190
_interner : PhantomData < I > ,
191
+ /// We bail if the walked types are too big to avoid hangs.
192
+ ///
193
+ /// We could alternatively use a cache to deduplicate types but this
194
+ /// feels like unnecessary effort.
195
+ num_non_trivial_types : usize ,
191
196
}
192
197
193
198
impl < I : Interner > DeepRejectCtxt < I , false , false > {
194
199
/// Treat parameters in both the lhs and the rhs as rigid.
195
200
pub fn relate_rigid_rigid ( _interner : I ) -> DeepRejectCtxt < I , false , false > {
196
- DeepRejectCtxt { _interner : PhantomData }
201
+ DeepRejectCtxt { _interner : PhantomData , num_non_trivial_types : 0 }
197
202
}
198
203
}
199
204
200
205
impl < I : Interner > DeepRejectCtxt < I , true , true > {
201
206
/// Treat parameters in both the lhs and the rhs as infer vars.
202
207
pub fn relate_infer_infer ( _interner : I ) -> DeepRejectCtxt < I , true , true > {
203
- DeepRejectCtxt { _interner : PhantomData }
208
+ DeepRejectCtxt { _interner : PhantomData , num_non_trivial_types : 0 }
204
209
}
205
210
}
206
211
207
212
impl < I : Interner > DeepRejectCtxt < I , false , true > {
208
213
/// Treat parameters in the lhs as rigid, and in rhs as infer vars.
209
214
pub fn relate_rigid_infer ( _interner : I ) -> DeepRejectCtxt < I , false , true > {
210
- DeepRejectCtxt { _interner : PhantomData }
215
+ DeepRejectCtxt { _interner : PhantomData , num_non_trivial_types : 0 }
211
216
}
212
217
}
213
218
214
219
impl < I : Interner , const INSTANTIATE_LHS_WITH_INFER : bool , const INSTANTIATE_RHS_WITH_INFER : bool >
215
220
DeepRejectCtxt < I , INSTANTIATE_LHS_WITH_INFER , INSTANTIATE_RHS_WITH_INFER >
216
221
{
217
222
pub fn args_may_unify (
218
- self ,
223
+ & mut self ,
219
224
obligation_args : I :: GenericArgs ,
220
225
impl_args : I :: GenericArgs ,
221
226
) -> bool {
@@ -234,7 +239,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
234
239
} )
235
240
}
236
241
237
- pub fn types_may_unify ( self , lhs : I :: Ty , rhs : I :: Ty ) -> bool {
242
+ pub fn types_may_unify ( & mut self , lhs : I :: Ty , rhs : I :: Ty ) -> bool {
238
243
match rhs. kind ( ) {
239
244
// Start by checking whether the `rhs` type may unify with
240
245
// pretty much everything. Just return `true` in that case.
@@ -273,6 +278,12 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
273
278
| ty:: Placeholder ( _) => { }
274
279
} ;
275
280
281
+ self . num_non_trivial_types += 1 ;
282
+ // Arbitrary cutoff.
283
+ if self . num_non_trivial_types >= 1024 {
284
+ return true ;
285
+ }
286
+
276
287
// For purely rigid types, use structural equivalence.
277
288
match lhs. kind ( ) {
278
289
ty:: Ref ( _, lhs_ty, lhs_mutbl) => match rhs. kind ( ) {
@@ -417,7 +428,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
417
428
}
418
429
}
419
430
420
- pub fn consts_may_unify ( self , lhs : I :: Const , rhs : I :: Const ) -> bool {
431
+ pub fn consts_may_unify ( & mut self , lhs : I :: Const , rhs : I :: Const ) -> bool {
421
432
match rhs. kind ( ) {
422
433
ty:: ConstKind :: Param ( _) => {
423
434
if INSTANTIATE_RHS_WITH_INFER {
@@ -465,7 +476,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
465
476
}
466
477
}
467
478
468
- fn var_and_ty_may_unify ( self , var : ty:: InferTy , ty : I :: Ty ) -> bool {
479
+ fn var_and_ty_may_unify ( & mut self , var : ty:: InferTy , ty : I :: Ty ) -> bool {
469
480
if !ty. is_known_rigid ( ) {
470
481
return true ;
471
482
}
0 commit comments