@@ -214,27 +214,47 @@ impl<I: Interner> DeepRejectCtxt<I, false, true> {
214
214
impl < I : Interner , const INSTANTIATE_LHS_WITH_INFER : bool , const INSTANTIATE_RHS_WITH_INFER : bool >
215
215
DeepRejectCtxt < I , INSTANTIATE_LHS_WITH_INFER , INSTANTIATE_RHS_WITH_INFER >
216
216
{
217
+ // Quite arbitrary. Large enough to only affect a very tiny amount of impls/crates
218
+ // and small enough to prevent hangs.
219
+ const STARTING_DEPTH : usize = 8 ;
220
+
217
221
pub fn args_may_unify (
218
222
self ,
219
223
obligation_args : I :: GenericArgs ,
220
224
impl_args : I :: GenericArgs ,
221
225
) -> bool {
226
+ self . args_may_unify_inner ( obligation_args, impl_args, Self :: STARTING_DEPTH )
227
+ }
228
+
229
+ pub fn types_may_unify ( self , lhs : I :: Ty , rhs : I :: Ty ) -> bool {
230
+ self . types_may_unify_inner ( lhs, rhs, Self :: STARTING_DEPTH )
231
+ }
232
+
233
+ fn args_may_unify_inner (
234
+ self ,
235
+ obligation_args : I :: GenericArgs ,
236
+ impl_args : I :: GenericArgs ,
237
+ depth : usize ,
238
+ ) -> bool {
239
+ // No need to decrement the depth here as this function is only
240
+ // recursively reachable via `types_may_unify_inner` which already
241
+ // increments the depth for us.
222
242
iter:: zip ( obligation_args. iter ( ) , impl_args. iter ( ) ) . all ( |( obl, imp) | {
223
243
match ( obl. kind ( ) , imp. kind ( ) ) {
224
244
// We don't fast reject based on regions.
225
245
( ty:: GenericArgKind :: Lifetime ( _) , ty:: GenericArgKind :: Lifetime ( _) ) => true ,
226
246
( ty:: GenericArgKind :: Type ( obl) , ty:: GenericArgKind :: Type ( imp) ) => {
227
- self . types_may_unify ( obl, imp)
247
+ self . types_may_unify_inner ( obl, imp, depth )
228
248
}
229
249
( ty:: GenericArgKind :: Const ( obl) , ty:: GenericArgKind :: Const ( imp) ) => {
230
- self . consts_may_unify ( obl, imp)
250
+ self . consts_may_unify_inner ( obl, imp)
231
251
}
232
252
_ => panic ! ( "kind mismatch: {obl:?} {imp:?}" ) ,
233
253
}
234
254
} )
235
255
}
236
256
237
- pub fn types_may_unify ( self , lhs : I :: Ty , rhs : I :: Ty ) -> bool {
257
+ fn types_may_unify_inner ( self , lhs : I :: Ty , rhs : I :: Ty , depth : usize ) -> bool {
238
258
match rhs. kind ( ) {
239
259
// Start by checking whether the `rhs` type may unify with
240
260
// pretty much everything. Just return `true` in that case.
@@ -273,18 +293,31 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
273
293
| ty:: Placeholder ( _) => { }
274
294
} ;
275
295
296
+ // The type system needs to support exponentially large types
297
+ // as long as they are self-similar. While most other folders
298
+ // use caching to handle them, this folder exists purely as a
299
+ // perf optimization and is incredibly hot. In pretty much all
300
+ // uses checking the cache is slower than simply recursing, so
301
+ // we instead just add an arbitrary depth cutoff.
302
+ //
303
+ // We only decrement the depth here as the match on `rhs`
304
+ // does not recurse.
305
+ let Some ( depth) = depth. checked_sub ( 1 ) else {
306
+ return true ;
307
+ } ;
308
+
276
309
// For purely rigid types, use structural equivalence.
277
310
match lhs. kind ( ) {
278
311
ty:: Ref ( _, lhs_ty, lhs_mutbl) => match rhs. kind ( ) {
279
312
ty:: Ref ( _, rhs_ty, rhs_mutbl) => {
280
- lhs_mutbl == rhs_mutbl && self . types_may_unify ( lhs_ty, rhs_ty)
313
+ lhs_mutbl == rhs_mutbl && self . types_may_unify_inner ( lhs_ty, rhs_ty, depth )
281
314
}
282
315
_ => false ,
283
316
} ,
284
317
285
318
ty:: Adt ( lhs_def, lhs_args) => match rhs. kind ( ) {
286
319
ty:: Adt ( rhs_def, rhs_args) => {
287
- lhs_def == rhs_def && self . args_may_unify ( lhs_args, rhs_args)
320
+ lhs_def == rhs_def && self . args_may_unify_inner ( lhs_args, rhs_args, depth )
288
321
}
289
322
_ => false ,
290
323
} ,
@@ -326,27 +359,28 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
326
359
ty:: Tuple ( rhs) => {
327
360
lhs. len ( ) == rhs. len ( )
328
361
&& iter:: zip ( lhs. iter ( ) , rhs. iter ( ) )
329
- . all ( |( lhs, rhs) | self . types_may_unify ( lhs, rhs) )
362
+ . all ( |( lhs, rhs) | self . types_may_unify_inner ( lhs, rhs, depth ) )
330
363
}
331
364
_ => false ,
332
365
} ,
333
366
334
367
ty:: Array ( lhs_ty, lhs_len) => match rhs. kind ( ) {
335
368
ty:: Array ( rhs_ty, rhs_len) => {
336
- self . types_may_unify ( lhs_ty, rhs_ty) && self . consts_may_unify ( lhs_len, rhs_len)
369
+ self . types_may_unify_inner ( lhs_ty, rhs_ty, depth)
370
+ && self . consts_may_unify_inner ( lhs_len, rhs_len)
337
371
}
338
372
_ => false ,
339
373
} ,
340
374
341
375
ty:: RawPtr ( lhs_ty, lhs_mutbl) => match rhs. kind ( ) {
342
376
ty:: RawPtr ( rhs_ty, rhs_mutbl) => {
343
- lhs_mutbl == rhs_mutbl && self . types_may_unify ( lhs_ty, rhs_ty)
377
+ lhs_mutbl == rhs_mutbl && self . types_may_unify_inner ( lhs_ty, rhs_ty, depth )
344
378
}
345
379
_ => false ,
346
380
} ,
347
381
348
382
ty:: Slice ( lhs_ty) => {
349
- matches ! ( rhs. kind( ) , ty:: Slice ( rhs_ty) if self . types_may_unify ( lhs_ty, rhs_ty) )
383
+ matches ! ( rhs. kind( ) , ty:: Slice ( rhs_ty) if self . types_may_unify_inner ( lhs_ty, rhs_ty, depth ) )
350
384
}
351
385
352
386
ty:: Dynamic ( lhs_preds, ..) => {
@@ -366,7 +400,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
366
400
lhs_hdr == rhs_hdr
367
401
&& lhs_sig_tys. len ( ) == rhs_sig_tys. len ( )
368
402
&& iter:: zip ( lhs_sig_tys. iter ( ) , rhs_sig_tys. iter ( ) )
369
- . all ( |( lhs, rhs) | self . types_may_unify ( lhs, rhs) )
403
+ . all ( |( lhs, rhs) | self . types_may_unify_inner ( lhs, rhs, depth ) )
370
404
}
371
405
_ => false ,
372
406
} ,
@@ -375,49 +409,51 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
375
409
376
410
ty:: FnDef ( lhs_def_id, lhs_args) => match rhs. kind ( ) {
377
411
ty:: FnDef ( rhs_def_id, rhs_args) => {
378
- lhs_def_id == rhs_def_id && self . args_may_unify ( lhs_args, rhs_args)
412
+ lhs_def_id == rhs_def_id && self . args_may_unify_inner ( lhs_args, rhs_args, depth )
379
413
}
380
414
_ => false ,
381
415
} ,
382
416
383
417
ty:: Closure ( lhs_def_id, lhs_args) => match rhs. kind ( ) {
384
418
ty:: Closure ( rhs_def_id, rhs_args) => {
385
- lhs_def_id == rhs_def_id && self . args_may_unify ( lhs_args, rhs_args)
419
+ lhs_def_id == rhs_def_id && self . args_may_unify_inner ( lhs_args, rhs_args, depth )
386
420
}
387
421
_ => false ,
388
422
} ,
389
423
390
424
ty:: CoroutineClosure ( lhs_def_id, lhs_args) => match rhs. kind ( ) {
391
425
ty:: CoroutineClosure ( rhs_def_id, rhs_args) => {
392
- lhs_def_id == rhs_def_id && self . args_may_unify ( lhs_args, rhs_args)
426
+ lhs_def_id == rhs_def_id && self . args_may_unify_inner ( lhs_args, rhs_args, depth )
393
427
}
394
428
_ => false ,
395
429
} ,
396
430
397
431
ty:: Coroutine ( lhs_def_id, lhs_args) => match rhs. kind ( ) {
398
432
ty:: Coroutine ( rhs_def_id, rhs_args) => {
399
- lhs_def_id == rhs_def_id && self . args_may_unify ( lhs_args, rhs_args)
433
+ lhs_def_id == rhs_def_id && self . args_may_unify_inner ( lhs_args, rhs_args, depth )
400
434
}
401
435
_ => false ,
402
436
} ,
403
437
404
438
ty:: CoroutineWitness ( lhs_def_id, lhs_args) => match rhs. kind ( ) {
405
439
ty:: CoroutineWitness ( rhs_def_id, rhs_args) => {
406
- lhs_def_id == rhs_def_id && self . args_may_unify ( lhs_args, rhs_args)
440
+ lhs_def_id == rhs_def_id && self . args_may_unify_inner ( lhs_args, rhs_args, depth )
407
441
}
408
442
_ => false ,
409
443
} ,
410
444
411
445
ty:: Pat ( lhs_ty, _) => {
412
446
// FIXME(pattern_types): take pattern into account
413
- matches ! ( rhs. kind( ) , ty:: Pat ( rhs_ty, _) if self . types_may_unify ( lhs_ty, rhs_ty) )
447
+ matches ! ( rhs. kind( ) , ty:: Pat ( rhs_ty, _) if self . types_may_unify_inner ( lhs_ty, rhs_ty, depth ) )
414
448
}
415
449
416
450
ty:: Error ( ..) => true ,
417
451
}
418
452
}
419
453
420
- pub fn consts_may_unify ( self , lhs : I :: Const , rhs : I :: Const ) -> bool {
454
+ // Unlike `types_may_unify_inner`, this does not take a depth as
455
+ // we never recurse from this function.
456
+ fn consts_may_unify_inner ( self , lhs : I :: Const , rhs : I :: Const ) -> bool {
421
457
match rhs. kind ( ) {
422
458
ty:: ConstKind :: Param ( _) => {
423
459
if INSTANTIATE_RHS_WITH_INFER {
0 commit comments