From 674333a6a8c5930bcd7d554833552be967bdb6fc Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 14 Jun 2017 10:36:09 +0200 Subject: [PATCH 1/5] Detect direct cycles of typerefs referring to themselves Have a Config option that allows to flag as assertion errors typerefs that refer directly to themselves in a bound or alias. I am going to use this to track down isRef stackoverflows; I believe it is also useful to keep around in case similar errors appear later. --- compiler/src/dotty/tools/dotc/config/Config.scala | 5 +++++ compiler/src/dotty/tools/dotc/core/Types.scala | 11 +++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala index 89b9a714b268..9a6c84f11e66 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 = true + /** 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..f3b8d0edb892 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1526,7 +1526,14 @@ 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.info match { + case TypeBounds(lo, hi) => + assert(lo.stripTypeVar.stripAnnots ne this) + assert(hi.stripTypeVar.stripAnnots ne this) + case _ => + } /** A second fallback to recompute the denotation if necessary */ private def computeDenot(implicit ctx: Context): Denotation = { @@ -1562,9 +1569,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 } From 2fdc581113768774c69c57a1acc68036b360fc19 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 14 Jun 2017 10:59:28 +0200 Subject: [PATCH 2/5] Acoid CyclicReference errors due to check --- compiler/src/dotty/tools/dotc/core/Types.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index f3b8d0edb892..72812523fffd 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1530,8 +1530,8 @@ object Types { if (Config.checkTypeRefCycles) lastDenotation.info match { case TypeBounds(lo, hi) => - assert(lo.stripTypeVar.stripAnnots ne this) - assert(hi.stripTypeVar.stripAnnots ne this) + assert(lo ne this) + assert(hi ne this) case _ => } From f2a74c95ffdcad737560f34fc65e2d8ed9eaff42 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 14 Jun 2017 13:25:10 +0200 Subject: [PATCH 3/5] Fix checking code Caused cyclic reference exceptions before --- compiler/src/dotty/tools/dotc/core/Types.scala | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 72812523fffd..31e86ee20a2a 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1528,10 +1528,14 @@ object Types { /** Hook for adding debug check code when denotations are assigned */ final def checkDenot()(implicit ctx: Context) = if (Config.checkTypeRefCycles) - lastDenotation.info match { - case TypeBounds(lo, hi) => - assert(lo ne this) - assert(hi ne this) + lastDenotation match { + case d: SingleDenotation => + d.infoOrCompleter match { + case TypeBounds(lo, hi) => + assert(lo ne this) + assert(hi ne this) + case _ => + } case _ => } From 13cd5056494075f6215634c3266cf3e072ce583e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 14 Jun 2017 13:53:42 +0200 Subject: [PATCH 4/5] Give more info on failure --- compiler/src/dotty/tools/dotc/core/Types.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 31e86ee20a2a..7d97f5e0b06e 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1532,8 +1532,8 @@ object Types { case d: SingleDenotation => d.infoOrCompleter match { case TypeBounds(lo, hi) => - assert(lo ne this) - assert(hi ne this) + assert(lo ne this, this) + assert(hi ne this, this) case _ => } case _ => From d69fb6c4ffc0df0ea400bdac36e304f7c802b7a1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 15 Jul 2017 11:53:03 +0200 Subject: [PATCH 5/5] Make checkCycles option false by default --- compiler/src/dotty/tools/dotc/config/Config.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala index 9a6c84f11e66..ffc4d65632cf 100644 --- a/compiler/src/dotty/tools/dotc/config/Config.scala +++ b/compiler/src/dotty/tools/dotc/config/Config.scala @@ -111,7 +111,7 @@ object Config { /** If this flag is set, it is checked that TypeRefs don't refer directly * to themselves. */ - final val checkTypeRefCycles = true + final val checkTypeRefCycles = false /** The recursion depth for showing a summarized string */ final val summarizeDepth = 2