From 4b48243a24e533ba81149df956fdc16cdaf1460e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 25 Jun 2015 22:03:01 +0200 Subject: [PATCH 01/10] Fix erasure of Thistypes. Thistypes erased to the underlying class. This is wrong. When seen as part of some other type, a ThisType has to erase to the erasure of the underlying type (i.e. the erasure if the selftype of the class). unittest-collections.scala failed with a MethodNotFound error because the erasure was computed incorrectly. On the other hand, a tree with a ThisType type, should keep the type, analogous to a tree with a TermRef type. --- src/dotty/tools/dotc/core/TypeErasure.scala | 6 +----- src/dotty/tools/dotc/transform/Erasure.scala | 1 + tests/{pending => }/run/unittest_collection.check | 0 tests/{pending => }/run/unittest_collection.scala | 10 +++++----- 4 files changed, 7 insertions(+), 10 deletions(-) rename tests/{pending => }/run/unittest_collection.check (100%) rename tests/{pending => }/run/unittest_collection.scala (86%) diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala index abe5418d4424..8abab9155ad8 100644 --- a/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/src/dotty/tools/dotc/core/TypeErasure.scala @@ -315,12 +315,8 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean val parent = tp.parent if (parent isRef defn.ArrayClass) eraseArray(tp) else this(parent) - case tp: TermRef => + case _: TermRef | _: ThisType => this(tp.widen) - case tp: ThisType => - def thisTypeErasure(tpToErase: Type) = - erasureFn(isJava, semiEraseVCs = false, isConstructor, wildcardOK)(tpToErase) - thisTypeErasure(tp.cls.typeRef) case SuperType(thistpe, supertpe) => SuperType(this(thistpe), this(supertpe)) case ExprType(rt) => diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index ad261c16be71..663c309c07c1 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -271,6 +271,7 @@ object Erasure extends TypeTestsCasts{ def erasedType(tree: untpd.Tree, semiEraseVCs: Boolean)(implicit ctx: Context): Type = tree.typeOpt match { case tp: TermRef if tree.isTerm => erasedRef(tp) + case tp: ThisType => tp case tp => erasure(tp, semiEraseVCs) } diff --git a/tests/pending/run/unittest_collection.check b/tests/run/unittest_collection.check similarity index 100% rename from tests/pending/run/unittest_collection.check rename to tests/run/unittest_collection.check diff --git a/tests/pending/run/unittest_collection.scala b/tests/run/unittest_collection.scala similarity index 86% rename from tests/pending/run/unittest_collection.scala rename to tests/run/unittest_collection.scala index d10845475b74..5db9b56d2bdc 100644 --- a/tests/pending/run/unittest_collection.scala +++ b/tests/run/unittest_collection.scala @@ -4,11 +4,11 @@ object Test { def main(args: Array[String]): Unit = { test(collection.mutable.ArrayBuffer[String]()) - test(collection.mutable.ListBuffer[String]()) - class BBuf(z:ListBuffer[String]) extends BufferProxy[String] { - def self = z - } - test(new BBuf(collection.mutable.ListBuffer[String]())) +// test(collection.mutable.ListBuffer[String]()) +// class BBuf(z:ListBuffer[String]) extends BufferProxy[String] { +// def self = z +// } +// test(new BBuf(collection.mutable.ListBuffer[String]())) } def test(x: Buffer[String]): Unit = { From aac4c28e4358bd6ff55cf5391508a9196cfb36ad Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 25 Jun 2015 22:50:07 +0200 Subject: [PATCH 02/10] Remove check file. The file consisted of just a deprecation warning. Not sure what was deprecated; neither dotty nor scalac find anything wrong with it. --- tests/run/unittest_collection.check | 1 - 1 file changed, 1 deletion(-) delete mode 100644 tests/run/unittest_collection.check diff --git a/tests/run/unittest_collection.check b/tests/run/unittest_collection.check deleted file mode 100644 index df1629dd7eb1..000000000000 --- a/tests/run/unittest_collection.check +++ /dev/null @@ -1 +0,0 @@ -warning: there was one deprecation warning; re-run with -deprecation for details From 830a66276c40d9552f0d55b1b560a85a26d0b56c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 26 Jun 2015 09:53:30 +0200 Subject: [PATCH 03/10] Simplify logic in erasure. There's one behavioral change: on typedSelectFromTypeTree, we use erasedType as for a notmal ref. Before semiEraseVCs was always set to false here. I don't see how the treatment should be different. E.g. it should not matter if we see a x.y or T#y --- src/dotty/tools/dotc/transform/Erasure.scala | 27 ++++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 663c309c07c1..8446e26262dd 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -268,36 +268,29 @@ object Erasure extends TypeTestsCasts{ class Typer extends typer.ReTyper with NoChecking { import Boxing._ - def erasedType(tree: untpd.Tree, semiEraseVCs: Boolean)(implicit ctx: Context): Type = - tree.typeOpt match { - case tp: TermRef if tree.isTerm => erasedRef(tp) - case tp: ThisType => tp - case tp => erasure(tp, semiEraseVCs) - } + def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type = { + val tp = tree.typeOpt + if (tree.isTerm) erasedRef(tp) else erasure(tp, semiEraseVCs = true) + } - def promote(tree: untpd.Tree, semiEraseVCs: Boolean)(implicit ctx: Context): tree.ThisTree[Type] = { + override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { assert(tree.hasType) - val erased = erasedType(tree, semiEraseVCs) + val erased = erasedType(tree) ctx.log(s"promoting ${tree.show}: ${erased.showWithUnderlying()}") tree.withType(erased) } - override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { - promote(tree, true) - } - /** When erasing most TypeTrees we should not semi-erase value types. * This is not the case for [[DefDef#tpt]], [[ValDef#tpt]] and [[Typed#tpt]], they * are handled separately by [[typedDefDef]], [[typedValDef]] and [[typedTyped]]. */ - override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = { - promote(tree, semiEraseVCs = false) - } + override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = + tree.withType(erasure(tree.tpe, semiEraseVCs = false)) /** This override is only needed to semi-erase type ascriptions */ override def typedTyped(tree: untpd.Typed, pt: Type)(implicit ctx: Context): Tree = { val Typed(expr, tpt) = tree - val tpt1 = promote(tpt, semiEraseVCs = true) + val tpt1 = promote(tpt) val expr1 = typed(expr, tpt1.tpe) assignType(untpd.cpy.Typed(tree)(expr1, tpt1), tpt1) } @@ -385,7 +378,7 @@ object Erasure extends TypeTestsCasts{ } override def typedSelectFromTypeTree(tree: untpd.SelectFromTypeTree, pt: Type)(implicit ctx: Context) = - untpd.Ident(tree.name).withPos(tree.pos).withType(erasedType(tree, semiEraseVCs = false)) + untpd.Ident(tree.name).withPos(tree.pos).withType(erasedType(tree)) override def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = if (tree.symbol == ctx.owner.enclosingClass || tree.symbol.isStaticOwner) promote(tree) From 8017c54da7b512478a78367f9b31a6b13260b311 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 26 Jun 2015 14:19:01 +0200 Subject: [PATCH 04/10] Disable checkConstraintClosed by default Checking that constraints are closed caused cyclic reference exceptions in DottyBackedInterface. What's worrying is that these were seemingly not checked by the checkin tests. Or maybe there is some dependcy on compilation order that triggers the erros only in my setup. --- src/dotty/tools/dotc/config/Config.scala | 12 ++++++++++-- src/dotty/tools/dotc/core/TyperState.scala | 2 +- src/dotty/tools/dotc/core/Types.scala | 2 ++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala index 9e9974bdce85..97893647c7fb 100644 --- a/src/dotty/tools/dotc/config/Config.scala +++ b/src/dotty/tools/dotc/config/Config.scala @@ -32,8 +32,16 @@ object Config { */ final val checkConstraintsPropagated = false - /** Check that constraints of globally committable typer states are closed */ - final val checkConstraintsClosed = true + /** Check that constraints of globally committable typer states are closed. + * NOTE: When enabled, the check can cause CyclicReference errors because + * it traverses all elements of a type. Such failures were observed when + * compiling all of dotty together (source seems to be in GenBCode which + * accesses javac's settings.) + * + * It is recommended to turn this option on only when chasing down + * a PolyParam instantiation error. See comment in Types.TypeVar.instantiate. + */ + final val debugCheckConstraintsClosed = false /** Check that no type appearing as the info of a SymDenotation contains * skolem types. diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala index ba7a6a8063fd..5617f568a2a7 100644 --- a/src/dotty/tools/dotc/core/TyperState.scala +++ b/src/dotty/tools/dotc/core/TyperState.scala @@ -87,7 +87,7 @@ extends TyperState(r) { override def constraint = myConstraint override def constraint_=(c: Constraint)(implicit ctx: Context) = { - if (Config.checkConstraintsClosed && isGlobalCommittable) c.checkClosed() + if (Config.debugCheckConstraintsClosed && isGlobalCommittable) c.checkClosed() myConstraint = c } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 1270466e9cb1..d6bb9c3c574e 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -2460,6 +2460,8 @@ object Types { if (ctx.typerState.isGlobalCommittable) assert(!inst.isInstanceOf[PolyParam], i"bad inst $this := $inst, constr = ${ctx.typerState.constraint}") + // If this fails, you might want to turn on Config.debugCheckConstraintsClosed + // to help find the root of the problem. instantiateWith(inst) } From 28751a117f32fb163b54e36e20915fd6f2cc39ff Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 26 Jun 2015 14:23:34 +0200 Subject: [PATCH 05/10] Get rid of semiEraseVCs boolean parameters Replace by the pair of methods erasure/valueErasure. The boolean parameter is still kept, but only as a confuration parameter of the erasure objects. --- src/dotty/tools/dotc/core/TypeErasure.scala | 21 ++++++++++++------- src/dotty/tools/dotc/transform/Erasure.scala | 6 +++--- .../dotc/transform/ExtensionMethods.scala | 4 ++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala index 8abab9155ad8..9b41eb982a5e 100644 --- a/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/src/dotty/tools/dotc/core/TypeErasure.scala @@ -110,15 +110,20 @@ object TypeErasure { private def erasureCtx(implicit ctx: Context) = if (ctx.erasedTypes) ctx.withPhase(ctx.erasurePhase).addMode(Mode.FutureDefsOK) else ctx - /** The standard erasure of a Scala type. + /** The standard erasure of a Scala type. Value classes are erased as normal classes. + * + * @param tp The type to erase. + */ + def erasure(tp: Type)(implicit ctx: Context): Type = + erasureFn(isJava = false, semiEraseVCs = false, isConstructor = false, wildcardOK = false)(tp)(erasureCtx) + + /** The value class erasure of a Scala type, where value classes are semi-erased to + * ErasedValueType (they will be fully erased in [[ElimErasedValueType]]). * * @param tp The type to erase. - * @param semiEraseVCs If true, value classes are semi-erased to ErasedValueType - * (they will be fully erased in [[ElimErasedValueType]]). - * If false, they are erased like normal classes. */ - def erasure(tp: Type, semiEraseVCs: Boolean = false)(implicit ctx: Context): Type = - erasureFn(isJava = false, semiEraseVCs, isConstructor = false, wildcardOK = false)(tp)(erasureCtx) + def valueErasure(tp: Type)(implicit ctx: Context): Type = + erasureFn(isJava = false, semiEraseVCs = true, isConstructor = false, wildcardOK = false)(tp)(erasureCtx) def sigName(tp: Type, isJava: Boolean)(implicit ctx: Context): TypeName = { val seqClass = if (isJava) defn.ArrayClass else defn.SeqClass @@ -141,7 +146,7 @@ object TypeErasure { case tp: ThisType => tp case tp => - erasure(tp, semiEraseVCs = true) + valueErasure(tp) } /** The symbol's erased info. This is the type's erasure, except for the following symbols: @@ -392,7 +397,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean private def eraseDerivedValueClassRef(tref: TypeRef)(implicit ctx: Context): Type = { val cls = tref.symbol.asClass val underlying = underlyingOfValueClass(cls) - ErasedValueType(cls, erasure(underlying, semiEraseVCs = true)) + ErasedValueType(cls, valueErasure(underlying)) } diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 8446e26262dd..8b4c6a87db19 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -270,7 +270,7 @@ object Erasure extends TypeTestsCasts{ def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type = { val tp = tree.typeOpt - if (tree.isTerm) erasedRef(tp) else erasure(tp, semiEraseVCs = true) + if (tree.isTerm) erasedRef(tp) else valueErasure(tp) } override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { @@ -285,7 +285,7 @@ object Erasure extends TypeTestsCasts{ * are handled separately by [[typedDefDef]], [[typedValDef]] and [[typedTyped]]. */ override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = - tree.withType(erasure(tree.tpe, semiEraseVCs = false)) + tree.withType(erasure(tree.tpe)) /** This override is only needed to semi-erase type ascriptions */ override def typedTyped(tree: untpd.Typed, pt: Type)(implicit ctx: Context): Tree = { @@ -454,7 +454,7 @@ object Erasure extends TypeTestsCasts{ if (pt.isValueType) pt else { if (tree.typeOpt.derivesFrom(ctx.definitions.UnitClass)) tree.typeOpt - else erasure(tree.typeOpt, semiEraseVCs = true) + else valueErasure(tree.typeOpt) } } diff --git a/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/src/dotty/tools/dotc/transform/ExtensionMethods.scala index 503016d8bab2..f50e3324dc0e 100644 --- a/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -14,7 +14,7 @@ import core._ import Phases.Phase import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._ -import TypeErasure.{ erasure, ErasedValueType } +import TypeErasure.{ erasure, valueErasure, ErasedValueType } import TypeUtils._ import util.Positions._ import Decorators._ @@ -65,7 +65,7 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful } } - val underlying = erasure(underlyingOfValueClass(valueClass), semiEraseVCs = true) + val underlying = valueErasure(underlyingOfValueClass(valueClass)) val evt = ErasedValueType(valueClass, underlying) val u2evtSym = ctx.newSymbol(moduleSym, nme.U2EVT, Synthetic | Method, MethodType(List(nme.x_0), List(underlying), evt)) From ef0184826b784fda9e2e1ef9aab31cab692cf3d2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 26 Jun 2015 14:29:49 +0200 Subject: [PATCH 06/10] Restored full test Uncommented parts that were left accidentally commented out when debugging. --- tests/run/unittest_collection.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/run/unittest_collection.scala b/tests/run/unittest_collection.scala index 5db9b56d2bdc..d10845475b74 100644 --- a/tests/run/unittest_collection.scala +++ b/tests/run/unittest_collection.scala @@ -4,11 +4,11 @@ object Test { def main(args: Array[String]): Unit = { test(collection.mutable.ArrayBuffer[String]()) -// test(collection.mutable.ListBuffer[String]()) -// class BBuf(z:ListBuffer[String]) extends BufferProxy[String] { -// def self = z -// } -// test(new BBuf(collection.mutable.ListBuffer[String]())) + test(collection.mutable.ListBuffer[String]()) + class BBuf(z:ListBuffer[String]) extends BufferProxy[String] { + def self = z + } + test(new BBuf(collection.mutable.ListBuffer[String]())) } def test(x: Buffer[String]): Unit = { From 3290164f06715bbdf1cc2283b70e6234f74c3606 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 26 Jun 2015 17:08:04 +0200 Subject: [PATCH 07/10] Fix trait constructors Trait constructors added a this to the constructor of a trait, which is useless because the constructor's type is unit. By contrast, it's good to rename the DefDef to the new name. --- src/dotty/tools/dotc/transform/TraitConstructors.scala | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/dotty/tools/dotc/transform/TraitConstructors.scala b/src/dotty/tools/dotc/transform/TraitConstructors.scala index 9fea468dac82..8c7277c2ee7c 100644 --- a/src/dotty/tools/dotc/transform/TraitConstructors.scala +++ b/src/dotty/tools/dotc/transform/TraitConstructors.scala @@ -11,15 +11,12 @@ import dotty.tools.dotc.core._ import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} /*** - * Renames constructors in traits so that backend will call them with invokeInterface - * Also makes sure that renamed constructor bodies conforms to type of method + * Renames constructors in traits so that backend will call them with invokeInterface */ class TraitConstructors extends MiniPhaseTransform with SymTransformer { import dotty.tools.dotc.ast.tpd._ def phaseName: String = "traitConstructors" - override def treeTransformPhase: Phase = this.phase - def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = { if (sym.isPrimaryConstructor && (sym.owner is Flags.Trait)) sym.copySymDenotation(name = nme.IMPLCLASS_CONSTRUCTOR) @@ -29,8 +26,7 @@ class TraitConstructors extends MiniPhaseTransform with SymTransformer { override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { val sym = tree.symbol if (sym.isPrimaryConstructor && (sym.owner is Flags.Trait)) - cpy.DefDef(tree)(rhs = Block(List(tree.rhs), This(tree.symbol.enclosingClass.asClass))) + cpy.DefDef(tree)(name = nme.IMPLCLASS_CONSTRUCTOR) else tree } - } From 78f5e1cb9c0b186e4835d0a69e551ed5e988829b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 26 Jun 2015 22:42:42 +0200 Subject: [PATCH 08/10] Drop redundant import --- src/dotty/tools/dotc/transform/ExtensionMethods.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/src/dotty/tools/dotc/transform/ExtensionMethods.scala index f50e3324dc0e..087e15c71685 100644 --- a/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -14,7 +14,7 @@ import core._ import Phases.Phase import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._ -import TypeErasure.{ erasure, valueErasure, ErasedValueType } +import TypeErasure.{ valueErasure, ErasedValueType } import TypeUtils._ import util.Positions._ import Decorators._ From a5eae5a79212f76c8a8ad3e4ea39ce0bb3302b9e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 27 Jun 2015 15:43:42 +0200 Subject: [PATCH 09/10] Drop TraitConstructors phase It did not do enough to carry its own weight, in particular because DenotationTransformers do have a price - every encountered denotation in the whole program is passed through them. The name change from to $init$ was all it did, that is now rolled into Mixin. Also renamed IMPLCLASS_CONSTRUCTOR to TRAIT_CONSTRUCTOR. --- src/dotty/tools/dotc/Compiler.scala | 3 +- src/dotty/tools/dotc/core/Flags.scala | 2 +- src/dotty/tools/dotc/core/NameOps.scala | 2 +- src/dotty/tools/dotc/core/StdNames.scala | 2 +- .../tools/dotc/core/SymDenotations.scala | 9 ++++-- .../core/unpickleScala2/Scala2Unpickler.scala | 2 +- .../dotc/transform/AugmentScala2Traits.scala | 2 +- .../transform/LinkScala2ImplClasses.scala | 2 +- src/dotty/tools/dotc/transform/Mixin.scala | 9 +++--- .../dotc/transform/TraitConstructors.scala | 32 ------------------- 10 files changed, 18 insertions(+), 47 deletions(-) delete mode 100644 src/dotty/tools/dotc/transform/TraitConstructors.scala diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index e9b0a9676df0..dcb5ba37354b 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -76,8 +76,7 @@ class Compiler { List(/*new PrivateToStatic,*/ new ExpandPrivate, new CollectEntryPoints, - new LabelDefs, - new TraitConstructors), + new LabelDefs), List(new GenBCode) ) diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 759dff0d44d8..f39f2bac6ec6 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -388,7 +388,7 @@ object Flags { /** Symbol is a self name */ final val SelfName = termFlag(54, "") - /** Symbol is an implementation class */ + /** Symbol is an implementation class of a Scala2 trait */ final val ImplClass = typeFlag(54, "") final val SelfNameOrImplClass = SelfName.toCommonFlags diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala index dc94f6db12da..4d6cca61dc08 100644 --- a/src/dotty/tools/dotc/core/NameOps.scala +++ b/src/dotty/tools/dotc/core/NameOps.scala @@ -62,7 +62,7 @@ object NameOps { def likeTyped(n: Name): N = (if (name.isTermName) n.toTermName else n.toTypeName).asInstanceOf[N] - def isConstructorName = name == CONSTRUCTOR || name == IMPLCLASS_CONSTRUCTOR + def isConstructorName = name == CONSTRUCTOR || name == TRAIT_CONSTRUCTOR def isExceptionResultName = name startsWith EXCEPTION_RESULT_PREFIX def isImplClassName = name endsWith IMPL_CLASS_SUFFIX def isLocalDummyName = name startsWith LOCALDUMMY_PREFIX diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala index eaf4ce1e2080..eb1a73625381 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -232,7 +232,6 @@ object StdNames { val EVT2U: N = "evt2u$" val EQEQ_LOCAL_VAR: N = "eqEqTemp$" val FAKE_LOCAL_THIS: N = "this$" - val IMPLCLASS_CONSTRUCTOR: N = "$init$" val LAZY_LOCAL: N = "$lzy" val LAZY_LOCAL_INIT: N = "$lzyINIT" val LAZY_FIELD_OFFSET: N = "OFFSET$" @@ -261,6 +260,7 @@ object StdNames { val SKOLEM: N = "" val SPECIALIZED_INSTANCE: N = "specInstance$" val THIS: N = "_$this" + val TRAIT_CONSTRUCTOR: N = "$init$" val U2EVT: N = "u2evt$" final val Nil: N = "Nil" diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index d8dddb0828cb..78b187970856 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -530,7 +530,7 @@ object SymDenotations { final def isClassConstructor = name == nme.CONSTRUCTOR /** Is this the constructor of a trait? */ - final def isImplClassConstructor = name == nme.IMPLCLASS_CONSTRUCTOR + final def isImplClassConstructor = name == nme.TRAIT_CONSTRUCTOR /** Is this the constructor of a trait or a class */ final def isConstructor = name.isConstructorName @@ -1630,8 +1630,11 @@ object SymDenotations { override def fullName(implicit ctx: Context): Name = super.fullName override def primaryConstructor(implicit ctx: Context): Symbol = { - val cname = if (this is ImplClass) nme.IMPLCLASS_CONSTRUCTOR else nme.CONSTRUCTOR - info.decls.denotsNamed(cname).last.symbol // denotsNamed returns Symbols in reverse order of occurrence + def constrNamed(cname: TermName) = info.decls.denotsNamed(cname).last.symbol + // denotsNamed returns Symbols in reverse order of occurrence + if (this.is(ImplClass)) constrNamed(nme.TRAIT_CONSTRUCTOR) + else + constrNamed(nme.CONSTRUCTOR).orElse(constrNamed(nme.TRAIT_CONSTRUCTOR)) } /** The parameter accessors of this class. Term and type accessors, diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 9498cf43c7f7..53e8478fa66f 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -438,7 +438,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas } val name1 = name0.adjustIfModuleClass(flags) - val name = if (name1 == nme.IMPLCLASS_CONSTRUCTOR) nme.CONSTRUCTOR else name1 + val name = if (name1 == nme.TRAIT_CONSTRUCTOR) nme.CONSTRUCTOR else name1 def isClassRoot = (name == classRoot.name) && (owner == classRoot.owner) && !(flags is ModuleClass) def isModuleClassRoot = (name == moduleClassRoot.name) && (owner == moduleClassRoot.owner) && (flags is Module) diff --git a/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala b/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala index 9f9d2dd67682..116fee899fd9 100644 --- a/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala +++ b/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala @@ -60,7 +60,7 @@ class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransform val mold = if (meth.isConstructor) meth.copySymDenotation( - name = nme.IMPLCLASS_CONSTRUCTOR, + name = nme.TRAIT_CONSTRUCTOR, info = MethodType(Nil, defn.UnitType)) else meth.ensureNotPrivate meth.copy( diff --git a/src/dotty/tools/dotc/transform/LinkScala2ImplClasses.scala b/src/dotty/tools/dotc/transform/LinkScala2ImplClasses.scala index 8c247130a50f..60e8edc26a1c 100644 --- a/src/dotty/tools/dotc/transform/LinkScala2ImplClasses.scala +++ b/src/dotty/tools/dotc/transform/LinkScala2ImplClasses.scala @@ -50,7 +50,7 @@ class LinkScala2ImplClasses extends MiniPhaseTransform with IdentityDenotTransfo private def implMethod(meth: Symbol)(implicit ctx: Context): Symbol = meth.owner.implClass.info - .decl(if (meth.isConstructor) nme.IMPLCLASS_CONSTRUCTOR else meth.name) + .decl(if (meth.isConstructor) nme.TRAIT_CONSTRUCTOR else meth.name) .suchThat(c => FullParameterization.memberSignature(c.info) == meth.signature) .symbol diff --git a/src/dotty/tools/dotc/transform/Mixin.scala b/src/dotty/tools/dotc/transform/Mixin.scala index de6cde8f2cc6..bebaf44f46cd 100644 --- a/src/dotty/tools/dotc/transform/Mixin.scala +++ b/src/dotty/tools/dotc/transform/Mixin.scala @@ -100,8 +100,10 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => override def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = if (sym.is(Accessor, butNot = Deferred) && sym.owner.is(Trait)) sym.copySymDenotation(initFlags = sym.flags &~ ParamAccessor | Deferred).ensureNotPrivate - else if (sym.isConstructor && sym.owner.is(Trait) && sym.info.firstParamTypes.nonEmpty) - sym.copySymDenotation(info = MethodType(Nil, sym.info.resultType)) + else if (sym.isConstructor && sym.owner.is(Trait)) + sym.copySymDenotation( + name = nme.TRAIT_CONSTRUCTOR, + info = MethodType(Nil, sym.info.resultType)) else sym @@ -231,8 +233,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => cpy.Template(impl)( constr = - if (cls.is(Trait) && impl.constr.vparamss.flatten.nonEmpty) - cpy.DefDef(impl.constr)(vparamss = Nil :: Nil) + if (cls.is(Trait)) cpy.DefDef(impl.constr)(vparamss = Nil :: Nil) else impl.constr, parents = impl.parents.map(p => TypeTree(p.tpe).withPos(p.pos)), body = diff --git a/src/dotty/tools/dotc/transform/TraitConstructors.scala b/src/dotty/tools/dotc/transform/TraitConstructors.scala deleted file mode 100644 index 8c7277c2ee7c..000000000000 --- a/src/dotty/tools/dotc/transform/TraitConstructors.scala +++ /dev/null @@ -1,32 +0,0 @@ -package dotty.tools.dotc.transform - -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.core.DenotTransformers.{SymTransformer, DenotTransformer} -import dotty.tools.dotc.core.Denotations.SingleDenotation -import dotty.tools.dotc.core.Phases.Phase -import dotty.tools.dotc.core.StdNames._ -import dotty.tools.dotc.core.SymDenotations.SymDenotation -import dotty.tools.dotc.core._ -import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} - -/*** - * Renames constructors in traits so that backend will call them with invokeInterface - */ -class TraitConstructors extends MiniPhaseTransform with SymTransformer { - import dotty.tools.dotc.ast.tpd._ - def phaseName: String = "traitConstructors" - - def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = { - if (sym.isPrimaryConstructor && (sym.owner is Flags.Trait)) - sym.copySymDenotation(name = nme.IMPLCLASS_CONSTRUCTOR) - else sym - } - - override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { - val sym = tree.symbol - if (sym.isPrimaryConstructor && (sym.owner is Flags.Trait)) - cpy.DefDef(tree)(name = nme.IMPLCLASS_CONSTRUCTOR) - else tree - } -} From 1510db96e56ed2fd18fafd1ce1aa411ad282ce28 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 27 Jun 2015 17:53:52 +0200 Subject: [PATCH 10/10] Add comment --- src/dotty/tools/dotc/core/SymDenotations.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 78b187970856..164b0b8f3d16 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1632,7 +1632,7 @@ object SymDenotations { override def primaryConstructor(implicit ctx: Context): Symbol = { def constrNamed(cname: TermName) = info.decls.denotsNamed(cname).last.symbol // denotsNamed returns Symbols in reverse order of occurrence - if (this.is(ImplClass)) constrNamed(nme.TRAIT_CONSTRUCTOR) + if (this.is(ImplClass)) constrNamed(nme.TRAIT_CONSTRUCTOR) // ignore normal constructor else constrNamed(nme.CONSTRUCTOR).orElse(constrNamed(nme.TRAIT_CONSTRUCTOR)) }