@@ -1985,8 +1985,19 @@ object Types {
19851985 * except for replacing type parameters with associated type variables.
19861986 */
19871987 def simplified (using Context ): Type =
1988- // stripping LazyRef is important for the reduction of applied match types
1989- // see the comment in matchCases/recur for more details
1988+ // A recursive match type will have the recursive call
1989+ // wrapped in a LazyRef. For example in i18175, the recursive calls
1990+ // to IsPiped within the definition of IsPiped are all wrapped in LazyRefs.
1991+ // In addition to that, TypeMaps, such as the one that backs TypeOps.simplify,
1992+ // by default will rewrap a LazyRef when applying its function.
1993+ // The result of those two things means that given a big enough input
1994+ // that recursive enough times through one or multiple match types,
1995+ // reducing and simplifying the result of the case bodies,
1996+ // can end up with a large stack of directly-nested lazy refs.
1997+ // And if that nesting level breaches `Config.LogPendingSubTypesThreshold`,
1998+ // then TypeComparer will eventually start returning `false` for `isSubType`.
1999+ // Or, under -Yno-deep-subtypes, start throwing AssertionErrors.
2000+ // So, we eagerly strip that lazy ref here to avoid the stacking.
19902001 val tp = stripLazyRef
19912002 TypeOps .simplify(tp, null )
19922003
0 commit comments