diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala index 89b9a714b268..ffc4d65632cf 100644 --- a/compiler/src/dotty/tools/dotc/config/Config.scala +++ b/compiler/src/dotty/tools/dotc/config/Config.scala @@ -108,6 +108,11 @@ object Config { */ final val checkMethodTypes = false + /** If this flag is set, it is checked that TypeRefs don't refer directly + * to themselves. + */ + final val checkTypeRefCycles = false + /** The recursion depth for showing a summarized string */ final val summarizeDepth = 2 diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 8c6474ae0e55..7d97f5e0b06e 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1526,7 +1526,18 @@ object Types { } /** Hook for adding debug check code when denotations are assigned */ - final def checkDenot()(implicit ctx: Context) = {} + final def checkDenot()(implicit ctx: Context) = + if (Config.checkTypeRefCycles) + lastDenotation match { + case d: SingleDenotation => + d.infoOrCompleter match { + case TypeBounds(lo, hi) => + assert(lo ne this, this) + assert(hi ne this, this) + case _ => + } + case _ => + } /** A second fallback to recompute the denotation if necessary */ private def computeDenot(implicit ctx: Context): Denotation = { @@ -1562,9 +1573,9 @@ object Types { // Don't use setDenot here; double binding checks can give spurious failures after erasure lastDenotation = d - checkDenot() lastSymbol = d.symbol checkedPeriod = ctx.period + checkDenot() } d }