Skip to content

Commit ed1de3a

Browse files
committed
Merge pull request #428 from dotty-staging/trait-constructors
New phase: trait constructors
2 parents c22d468 + 77997f3 commit ed1de3a

File tree

6 files changed

+67
-21
lines changed

6 files changed

+67
-21
lines changed

src/dotty/tools/backend/jvm/CollectEntryPoints.scala

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,22 @@ class CollectEntryPoints extends MiniPhaseTransform {
4848
}
4949

5050
object CollectEntryPoints{
51+
def isJavaMainMethod(sym: Symbol)(implicit ctx: Context) = {
52+
val d = ctx.definitions
53+
val StringType = d.StringType
54+
55+
(sym.name == nme.main) && (sym.info match {
56+
case r@MethodType(_, List(d.ArrayType(t))) =>
57+
(t.widenDealias =:= StringType) && (
58+
r.resultType.widenDealias =:= d.UnitType)
59+
case _ => false
60+
})
61+
}
62+
5163
def isJavaEntyPoint(sym: Symbol)(implicit ctx: Context): Boolean = {
5264
import Types.MethodType
5365
val d = ctx.definitions
5466
val StringType = d.StringType
55-
def isJavaMainMethod(sym: Symbol) = (sym.name == nme.main) && (toDenot(sym).info match {
56-
case r@ MethodType(_, List(d.ArrayType(StringType))) => r.resultType eq d.UnitType
57-
case _ => false
58-
})
5967
// The given class has a main method.
6068
def hasJavaMainMethod(sym: Symbol): Boolean =
6169
(toDenot(sym).info member nme.main).alternatives exists(x => isJavaMainMethod(x.symbol))

src/dotty/tools/backend/jvm/DottyBackendInterface.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{
452452
def isVarargsMethod: Boolean = sym is Flags.JavaVarargs
453453
def isDeprecated: Boolean = false
454454
def isMutable: Boolean = sym is Flags.Mutable
455-
def hasAbstractFlag: Boolean = (sym is Flags.Abstract) || (sym is Flags.JavaInterface)
455+
def hasAbstractFlag: Boolean =
456+
(sym is Flags.Abstract) || (sym is Flags.JavaInterface) || (sym is Flags.Trait)
456457
def hasModuleFlag: Boolean = sym is Flags.Module
457458
def isSynchronized: Boolean = sym is Flags.Synchronized
458459
def isNonBottomSubClass(other: Symbol): Boolean = sym.derivesFrom(other)

src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class Compiler {
6767
List(new LambdaLift,
6868
new Flatten,
6969
new RestoreScopes),
70-
List(/*new PrivateToStatic,*/ new CollectEntryPoints, new LabelDefs, new ElimWildcardIdents),
70+
List(/*new PrivateToStatic,*/ new CollectEntryPoints, new LabelDefs, new ElimWildcardIdents, new TraitConstructors),
7171
List(new GenBCode)
7272
)
7373

src/dotty/tools/dotc/transform/InterceptedMethods.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@ class InterceptedMethods extends MiniPhaseTransform { thisTransform =>
6464
// this should be removed if we have guarantee that ## will get Apply node
6565
override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): Tree = {
6666
if (tree.symbol.isTerm && poundPoundMethods.contains(tree.symbol.asTerm)) {
67-
val rewrite = PoundPoundValue(tree.qualifier)
67+
val rewrite = poundPoundValue(tree.qualifier)
6868
ctx.log(s"$phaseName rewrote $tree to $rewrite")
6969
rewrite
7070
}
7171
else tree
7272
}
7373

74-
private def PoundPoundValue(tree: Tree)(implicit ctx: Context) = {
74+
private def poundPoundValue(tree: Tree)(implicit ctx: Context) = {
7575
val s = tree.tpe.widen.typeSymbol
7676
if (s == defn.NullClass) Literal(Constant(0))
7777
else {
@@ -108,7 +108,7 @@ class InterceptedMethods extends MiniPhaseTransform { thisTransform =>
108108
val rewrite: Tree = tree.fun match {
109109
case Select(qual, name) =>
110110
if (poundPoundMethods contains tree.fun.symbol.asTerm) {
111-
PoundPoundValue(qual)
111+
poundPoundValue(qual)
112112
} else if (Any_comparisons contains tree.fun.symbol.asTerm) {
113113
if (tree.fun.symbol eq defn.Any_==) {
114114
qual.select(defn.Any_equals).appliedToArgs(tree.args)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package dotty.tools.dotc.transform
2+
3+
import dotty.tools.dotc.ast.tpd
4+
import dotty.tools.dotc.core.Contexts.Context
5+
import dotty.tools.dotc.core.DenotTransformers.{SymTransformer, DenotTransformer}
6+
import dotty.tools.dotc.core.Denotations.SingleDenotation
7+
import dotty.tools.dotc.core.Phases.Phase
8+
import dotty.tools.dotc.core.StdNames._
9+
import dotty.tools.dotc.core.SymDenotations.SymDenotation
10+
import dotty.tools.dotc.core._
11+
import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo}
12+
13+
/***
14+
* Renames constructors in traits so that backend will call them with invokeInterface
15+
* Also makes sure that renamed constructor bodies conforms to type of method
16+
*/
17+
class TraitConstructors extends MiniPhaseTransform with SymTransformer {
18+
import dotty.tools.dotc.ast.tpd._
19+
def phaseName: String = "traitConstructors"
20+
21+
22+
override def treeTransformPhase: Phase = this.phase
23+
24+
def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = {
25+
if(sym.isPrimaryConstructor && (sym.owner is Flags.Trait))
26+
sym.copySymDenotation(name = nme.INITIALIZER_PREFIX ++ sym.owner.fullName)
27+
else sym
28+
}
29+
30+
override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
31+
val sym = tree.symbol
32+
if (sym.isPrimaryConstructor && (sym.owner is Flags.Trait))
33+
cpy.DefDef(tree)(rhs = Block(List(tree.rhs), This(tree.symbol.enclosingClass.asClass)))
34+
else tree
35+
}
36+
37+
}

tests/pos/approximateUnion.scala

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ object approximateUnion {
1010
trait B extends C[B] with D
1111

1212
val coin = true
13-
val x = if (coin) new A else new B
14-
val y = Some(if (coin) new A else new B)
13+
val x = if (coin) new A{} else new B{}
14+
val y = Some(if (coin) new A{} else new B{} )
1515

1616
val xtest: C[A | B] & D = x
1717
val ytest: Some[C[A | B] & D] = y
@@ -22,8 +22,8 @@ object approximateUnion {
2222
trait B extends C[X[B]] with D with E
2323

2424
val coin = true
25-
val x = if (coin) new A else new B
26-
val y = Some(if (coin) new A else new B)
25+
val x = if (coin) new A{} else new B{}
26+
val y = Some(if (coin) new A{} else new B{})
2727

2828
val xtest: C[X[A & B]] & D = x
2929
val ytest: Some[C[X[A & B]] & D] = y
@@ -42,8 +42,8 @@ object approximateUnion2 {
4242
trait B extends C[B] with D
4343

4444
val coin = true
45-
val x = if (coin) new A else new B
46-
val y = Some(if (coin) new A else new B)
45+
val x = if (coin) new A{} else new B{}
46+
val y = Some(if (coin) new A{} else new B{})
4747

4848
val xtest: C[_ >: A & B <: A | B] & D = x
4949
val ytest: Some[C[_ >: A & B <: A | B] & D] = y
@@ -54,8 +54,8 @@ object approximateUnion2 {
5454
trait B extends C[X[B]] with D with E
5555

5656
val coin = true
57-
val x = if (coin) new A else new B
58-
val y = Some(if (coin) new A else new B)
57+
val x = if (coin) new A{} else new B{}
58+
val y = Some(if (coin) new A{} else new B{})
5959

6060
val xtest: C[_ >: X[A | B] <: X[A & B]] & D = x
6161
val ytest: Some[C[_ >: X[A | B] <: X[A & B]]] = y
@@ -74,8 +74,8 @@ object approximateUnion3 {
7474
trait B extends C[B] with D
7575

7676
val coin = true
77-
val x = if (coin) new A else new B
78-
val y = Some(if (coin) new A else new B)
77+
val x = if (coin) new A{} else new B{}
78+
val y = Some(if (coin) new A{} else new B{})
7979

8080
val xtest: C[A & B] & D = x
8181
val ytest: Some[C[A & B] & D] = y
@@ -86,8 +86,8 @@ object approximateUnion3 {
8686
trait B extends C[X[B]] with D with E
8787

8888
val coin = true
89-
val x = if (coin) new A else new B
90-
val y = Some(if (coin) new A else new B)
89+
val x = if (coin) new A{} else new B{}
90+
val y = Some(if (coin) new A{} else new B{})
9191

9292
val xtest: C[X[A | B]] & D = x
9393
val ytest2: Some[C[X[A | B]] & D] = y

0 commit comments

Comments
 (0)