From f315852dec6471f71592690d5fc84e512f7c5d9e Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Wed, 18 Mar 2015 01:27:10 +0100 Subject: [PATCH] BUG: The use of isDerivedValueClass in ExtensionMethods causes cyclic references In #411 I implemented value classes and started getting errors in the backend. This commit reproduces similar errors in master with a single change: In master Symbol#isDerivedValueClass always return false because value classes are non-functional, after this commit it still always return false but it calls this.derivesFrom(defn.AnyValClass) first, this is enough to trigger the problem. Here's what's happening with dotc_reporter for example, the first error is: dotty.tools.dotc.core.Types$CyclicReference: cyclic reference involving class FlatHashTable - During Erasure, isDerivedValueClass is called on the class FlatHashTable - derivesFrom forces the computation of the base classes of FlatHashTable - HashUtils is a parent of FlatHashTable, its denotation is forced - HashUtils is then transformed by ExplicitOuter which calls isStatic on it - isStatic calls owner.isStaticOwner, this forces the denotation of the owner of HashUtils, which is the module class FlatHashTable$ - FlatHashTable$ is then transformed by ExtensionMethods which calls linkedClass on it to get the companion class FlatHashTable - isDerivedValueClass is called on the class FlatHashTable - *BOOM* --- src/dotty/tools/dotc/core/Symbols.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index f6e4119ea6fd..955d7ad82864 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -418,9 +418,11 @@ object Symbols { def filter(p: Symbol => Boolean): Symbol = if (p(this)) this else NoSymbol /** Is this symbol a user-defined value class? */ - final def isDerivedValueClass(implicit ctx: Context): Boolean = + final def isDerivedValueClass(implicit ctx: Context): Boolean = { + this.derivesFrom(defn.AnyValClass) // Simulate ValueClasses.isDerivedValueClass false // will migrate to ValueClasses.isDerivedValueClass; // unsupported value class code will continue to use this stub while it exists + } /** The current name of this symbol */ final def name(implicit ctx: Context): ThisName = denot.name.asInstanceOf[ThisName]