@@ -214,27 +214,47 @@ impl<I: Interner> DeepRejectCtxt<I, false, true> {
214214impl < I : Interner , const INSTANTIATE_LHS_WITH_INFER : bool , const INSTANTIATE_RHS_WITH_INFER : bool >
215215 DeepRejectCtxt < I , INSTANTIATE_LHS_WITH_INFER , INSTANTIATE_RHS_WITH_INFER >
216216{
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+
217221 pub fn args_may_unify (
218222 self ,
219223 obligation_args : I :: GenericArgs ,
220224 impl_args : I :: GenericArgs ,
221225 ) -> 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.
222242 iter:: zip ( obligation_args. iter ( ) , impl_args. iter ( ) ) . all ( |( obl, imp) | {
223243 match ( obl. kind ( ) , imp. kind ( ) ) {
224244 // We don't fast reject based on regions.
225245 ( ty:: GenericArgKind :: Lifetime ( _) , ty:: GenericArgKind :: Lifetime ( _) ) => true ,
226246 ( ty:: GenericArgKind :: Type ( obl) , ty:: GenericArgKind :: Type ( imp) ) => {
227- self . types_may_unify ( obl, imp)
247+ self . types_may_unify_inner ( obl, imp, depth )
228248 }
229249 ( ty:: GenericArgKind :: Const ( obl) , ty:: GenericArgKind :: Const ( imp) ) => {
230- self . consts_may_unify ( obl, imp)
250+ self . consts_may_unify_inner ( obl, imp)
231251 }
232252 _ => panic ! ( "kind mismatch: {obl:?} {imp:?}" ) ,
233253 }
234254 } )
235255 }
236256
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 {
238258 match rhs. kind ( ) {
239259 // Start by checking whether the `rhs` type may unify with
240260 // 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_
273293 | ty:: Placeholder ( _) => { }
274294 } ;
275295
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+
276309 // For purely rigid types, use structural equivalence.
277310 match lhs. kind ( ) {
278311 ty:: Ref ( _, lhs_ty, lhs_mutbl) => match rhs. kind ( ) {
279312 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 )
281314 }
282315 _ => false ,
283316 } ,
284317
285318 ty:: Adt ( lhs_def, lhs_args) => match rhs. kind ( ) {
286319 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 )
288321 }
289322 _ => false ,
290323 } ,
@@ -326,27 +359,28 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
326359 ty:: Tuple ( rhs) => {
327360 lhs. len ( ) == rhs. len ( )
328361 && 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 ) )
330363 }
331364 _ => false ,
332365 } ,
333366
334367 ty:: Array ( lhs_ty, lhs_len) => match rhs. kind ( ) {
335368 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)
337371 }
338372 _ => false ,
339373 } ,
340374
341375 ty:: RawPtr ( lhs_ty, lhs_mutbl) => match rhs. kind ( ) {
342376 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 )
344378 }
345379 _ => false ,
346380 } ,
347381
348382 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 ) )
350384 }
351385
352386 ty:: Dynamic ( lhs_preds, ..) => {
@@ -366,7 +400,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
366400 lhs_hdr == rhs_hdr
367401 && lhs_sig_tys. len ( ) == rhs_sig_tys. len ( )
368402 && 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 ) )
370404 }
371405 _ => false ,
372406 } ,
@@ -375,49 +409,51 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
375409
376410 ty:: FnDef ( lhs_def_id, lhs_args) => match rhs. kind ( ) {
377411 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 )
379413 }
380414 _ => false ,
381415 } ,
382416
383417 ty:: Closure ( lhs_def_id, lhs_args) => match rhs. kind ( ) {
384418 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 )
386420 }
387421 _ => false ,
388422 } ,
389423
390424 ty:: CoroutineClosure ( lhs_def_id, lhs_args) => match rhs. kind ( ) {
391425 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 )
393427 }
394428 _ => false ,
395429 } ,
396430
397431 ty:: Coroutine ( lhs_def_id, lhs_args) => match rhs. kind ( ) {
398432 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 )
400434 }
401435 _ => false ,
402436 } ,
403437
404438 ty:: CoroutineWitness ( lhs_def_id, lhs_args) => match rhs. kind ( ) {
405439 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 )
407441 }
408442 _ => false ,
409443 } ,
410444
411445 ty:: Pat ( lhs_ty, _) => {
412446 // 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 ) )
414448 }
415449
416450 ty:: Error ( ..) => true ,
417451 }
418452 }
419453
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 {
421457 match rhs. kind ( ) {
422458 ty:: ConstKind :: Param ( _) => {
423459 if INSTANTIATE_RHS_WITH_INFER {
0 commit comments