From ee29f47806858766b4010fb254df99cd0bb14d4d Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 25 Mar 2015 13:07:38 +0100 Subject: [PATCH 1/5] Make CollectEntryPoints stable against type aliases. --- .../tools/backend/jvm/CollectEntryPoints.scala | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/dotty/tools/backend/jvm/CollectEntryPoints.scala b/src/dotty/tools/backend/jvm/CollectEntryPoints.scala index 802100bf25ad..734890daa2e1 100644 --- a/src/dotty/tools/backend/jvm/CollectEntryPoints.scala +++ b/src/dotty/tools/backend/jvm/CollectEntryPoints.scala @@ -48,14 +48,22 @@ class CollectEntryPoints extends MiniPhaseTransform { } object CollectEntryPoints{ + def isJavaMainMethod(sym: Symbol)(implicit ctx: Context) = { + val d = ctx.definitions + val StringType = d.StringType + + (sym.name == nme.main) && (sym.info match { + case r@MethodType(_, List(d.ArrayType(t))) => + (t.widenDealias =:= StringType) && ( + r.resultType.widenDealias =:= d.UnitType) + case _ => false + }) + } + def isJavaEntyPoint(sym: Symbol)(implicit ctx: Context): Boolean = { import Types.MethodType val d = ctx.definitions val StringType = d.StringType - def isJavaMainMethod(sym: Symbol) = (sym.name == nme.main) && (toDenot(sym).info match { - case r@ MethodType(_, List(d.ArrayType(StringType))) => r.resultType eq d.UnitType - case _ => false - }) // The given class has a main method. def hasJavaMainMethod(sym: Symbol): Boolean = (toDenot(sym).info member nme.main).alternatives exists(x => isJavaMainMethod(x.symbol)) From e3191b73ddc50083b66bb143e7dbcf728cf230ad Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 25 Mar 2015 13:07:59 +0100 Subject: [PATCH 2/5] Style fixes in InterceptedMethods --- src/dotty/tools/dotc/transform/InterceptedMethods.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dotty/tools/dotc/transform/InterceptedMethods.scala b/src/dotty/tools/dotc/transform/InterceptedMethods.scala index b39405ba3cc5..87a5c1a4ca23 100644 --- a/src/dotty/tools/dotc/transform/InterceptedMethods.scala +++ b/src/dotty/tools/dotc/transform/InterceptedMethods.scala @@ -64,14 +64,14 @@ class InterceptedMethods extends MiniPhaseTransform { thisTransform => // this should be removed if we have guarantee that ## will get Apply node override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): Tree = { if (tree.symbol.isTerm && poundPoundMethods.contains(tree.symbol.asTerm)) { - val rewrite = PoundPoundValue(tree.qualifier) + val rewrite = poundPoundValue(tree.qualifier) ctx.log(s"$phaseName rewrote $tree to $rewrite") rewrite } else tree } - private def PoundPoundValue(tree: Tree)(implicit ctx: Context) = { + private def poundPoundValue(tree: Tree)(implicit ctx: Context) = { val s = tree.tpe.widen.typeSymbol if (s == defn.NullClass) Literal(Constant(0)) else { @@ -108,7 +108,7 @@ class InterceptedMethods extends MiniPhaseTransform { thisTransform => val rewrite: Tree = tree.fun match { case Select(qual, name) => if (poundPoundMethods contains tree.fun.symbol.asTerm) { - PoundPoundValue(qual) + poundPoundValue(qual) } else if (Any_comparisons contains tree.fun.symbol.asTerm) { if (tree.fun.symbol eq defn.Any_==) { qual.select(defn.Any_equals).appliedToArgs(tree.args) From 01fae5d041201e2d8e03dff8c5b9f68c96dad1f5 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 25 Mar 2015 13:08:23 +0100 Subject: [PATCH 3/5] Emit abstract flag for non-abstract traits --- src/dotty/tools/backend/jvm/DottyBackendInterface.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 5fcb7f57be97..357018857cce 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -452,7 +452,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ def isVarargsMethod: Boolean = sym is Flags.JavaVarargs def isDeprecated: Boolean = false def isMutable: Boolean = sym is Flags.Mutable - def hasAbstractFlag: Boolean = (sym is Flags.Abstract) || (sym is Flags.JavaInterface) + def hasAbstractFlag: Boolean = + (sym is Flags.Abstract) || (sym is Flags.JavaInterface) || (sym is Flags.Trait) def hasModuleFlag: Boolean = sym is Flags.Module def isSynchronized: Boolean = sym is Flags.Synchronized def isNonBottomSubClass(other: Symbol): Boolean = sym.derivesFrom(other) From e6fc268ae010bb664a0b7efa0a32922fb410e415 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 25 Mar 2015 13:10:24 +0100 Subject: [PATCH 4/5] New phase trait constructors. Renames constructors in traits so that backend will call them with invokeInterface, instead of invokeSpecial Also makes sure that renamed constructor bodies conforms to type of method --- src/dotty/tools/dotc/Compiler.scala | 2 +- .../dotc/transform/TraitConstructors.scala | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create 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 e051e16c8d49..0db8a42c984e 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -67,7 +67,7 @@ class Compiler { List(new LambdaLift, new Flatten, new RestoreScopes), - List(/*new PrivateToStatic,*/ new CollectEntryPoints, new LabelDefs, new ElimWildcardIdents), + List(/*new PrivateToStatic,*/ new CollectEntryPoints, new LabelDefs, new ElimWildcardIdents, new TraitConstructors), List(new GenBCode) ) diff --git a/src/dotty/tools/dotc/transform/TraitConstructors.scala b/src/dotty/tools/dotc/transform/TraitConstructors.scala new file mode 100644 index 000000000000..8c92f1f7bf05 --- /dev/null +++ b/src/dotty/tools/dotc/transform/TraitConstructors.scala @@ -0,0 +1,37 @@ +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 + * Also makes sure that renamed constructor bodies conforms to type of method + */ +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.INITIALIZER_PREFIX ++ sym.owner.fullName) + 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)(rhs = Block(List(tree.rhs), This(tree.symbol.enclosingClass.asClass))) + else tree + } + +} From 77997f30b28b3588967052647ad3d5164a585f40 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 25 Mar 2015 13:39:53 +0100 Subject: [PATCH 5/5] Fix failing tets: test instantiated abstract traits. --- tests/pos/approximateUnion.scala | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/pos/approximateUnion.scala b/tests/pos/approximateUnion.scala index c3fe0e1625f5..d23c3ca0ee04 100644 --- a/tests/pos/approximateUnion.scala +++ b/tests/pos/approximateUnion.scala @@ -10,8 +10,8 @@ object approximateUnion { trait B extends C[B] with D val coin = true - val x = if (coin) new A else new B - val y = Some(if (coin) new A else new B) + val x = if (coin) new A{} else new B{} + val y = Some(if (coin) new A{} else new B{} ) val xtest: C[A | B] & D = x val ytest: Some[C[A | B] & D] = y @@ -22,8 +22,8 @@ object approximateUnion { trait B extends C[X[B]] with D with E val coin = true - val x = if (coin) new A else new B - val y = Some(if (coin) new A else new B) + val x = if (coin) new A{} else new B{} + val y = Some(if (coin) new A{} else new B{}) val xtest: C[X[A & B]] & D = x val ytest: Some[C[X[A & B]] & D] = y @@ -42,8 +42,8 @@ object approximateUnion2 { trait B extends C[B] with D val coin = true - val x = if (coin) new A else new B - val y = Some(if (coin) new A else new B) + val x = if (coin) new A{} else new B{} + val y = Some(if (coin) new A{} else new B{}) val xtest: C[_ >: A & B <: A | B] & D = x val ytest: Some[C[_ >: A & B <: A | B] & D] = y @@ -54,8 +54,8 @@ object approximateUnion2 { trait B extends C[X[B]] with D with E val coin = true - val x = if (coin) new A else new B - val y = Some(if (coin) new A else new B) + val x = if (coin) new A{} else new B{} + val y = Some(if (coin) new A{} else new B{}) val xtest: C[_ >: X[A | B] <: X[A & B]] & D = x val ytest: Some[C[_ >: X[A | B] <: X[A & B]]] = y @@ -74,8 +74,8 @@ object approximateUnion3 { trait B extends C[B] with D val coin = true - val x = if (coin) new A else new B - val y = Some(if (coin) new A else new B) + val x = if (coin) new A{} else new B{} + val y = Some(if (coin) new A{} else new B{}) val xtest: C[A & B] & D = x val ytest: Some[C[A & B] & D] = y @@ -86,8 +86,8 @@ object approximateUnion3 { trait B extends C[X[B]] with D with E val coin = true - val x = if (coin) new A else new B - val y = Some(if (coin) new A else new B) + val x = if (coin) new A{} else new B{} + val y = Some(if (coin) new A{} else new B{}) val xtest: C[X[A | B]] & D = x val ytest2: Some[C[X[A | B]] & D] = y