Skip to content

Commit

Permalink
Move comment for stripLazyRef usage
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed Jul 17, 2023
1 parent d087c43 commit d42301e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 15 deletions.
13 changes: 0 additions & 13 deletions compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3248,19 +3248,6 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
MatchTypeTrace.noInstance(scrut, cas, fails)
NoType
case MatchResult.Reduced(tp) =>
// A recursive match type will have the recursive call
// wrapped in a LazyRef. For example in i18175, the recursive calls
// to IsPiped within the definition of IsPiped are all wrapped in LazyRefs.
// In addition to that, TypeMaps, such as the one that backs TypeOps.simplify,
// by default will rewrap a LazyRef when applying its function.
// The result of those two things means that given a big enough input
// that recursive enough times through one or multiple match types,
// reducing and simplifying the result of the case bodies,
// can end up with a large stack of directly-nested lazy refs.
// And if that nesting level breaches `Config.LogPendingSubTypesThreshold`,
// then TypeComparer will eventually start returning `false` for `isSubType`.
// Or, under -Yno-deep-subtypes, start throwing AssertionErrors.
// So, we eagerly strip that lazy ref here to avoid the stacking.
tp.simplified
case Nil =>
val casesText = MatchTypeTrace.noMatchesText(scrut, cases)
Expand Down
15 changes: 13 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1985,8 +1985,19 @@ object Types {
* except for replacing type parameters with associated type variables.
*/
def simplified(using Context): Type =
// stripping LazyRef is important for the reduction of applied match types
// see the comment in matchCases/recur for more details
// A recursive match type will have the recursive call
// wrapped in a LazyRef. For example in i18175, the recursive calls
// to IsPiped within the definition of IsPiped are all wrapped in LazyRefs.
// In addition to that, TypeMaps, such as the one that backs TypeOps.simplify,
// by default will rewrap a LazyRef when applying its function.
// The result of those two things means that given a big enough input
// that recursive enough times through one or multiple match types,
// reducing and simplifying the result of the case bodies,
// can end up with a large stack of directly-nested lazy refs.
// And if that nesting level breaches `Config.LogPendingSubTypesThreshold`,
// then TypeComparer will eventually start returning `false` for `isSubType`.
// Or, under -Yno-deep-subtypes, start throwing AssertionErrors.
// So, we eagerly strip that lazy ref here to avoid the stacking.
val tp = stripLazyRef
TypeOps.simplify(tp, null)

Expand Down

0 comments on commit d42301e

Please sign in to comment.