Skip to content

Commit ef27460

Browse files
committed
Merge pull request #611 from dotty-staging/supercalls-traits-test
Add a test for supercalls in traits.
2 parents c533f81 + 7779b8f commit ef27460

File tree

6 files changed

+70
-8
lines changed

6 files changed

+70
-8
lines changed

src/dotty/tools/dotc/core/TypeErasure.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ object TypeErasure {
164164
else if (sym.isConstructor) outer.addParam(sym.owner.asClass, erase(tp)(erasureCtx))
165165
else erase.eraseInfo(tp, sym)(erasureCtx) match {
166166
case einfo: MethodType if sym.isGetter && einfo.resultType.isRef(defn.UnitClass) =>
167-
defn.BoxedUnitClass.typeRef
167+
MethodType(Nil, Nil, defn.BoxedUnitClass.typeRef)
168168
case einfo =>
169169
einfo
170170
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ import Decorators._
5050

5151
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
5252
val sym = tree.symbol
53-
53+
5454
def newField = ctx.newSymbol(
5555
owner = ctx.owner,
5656
name = sym.name.asTermName.fieldName,
5757
flags = Private | (if (sym is Stable) EmptyFlags else Mutable),
5858
info = sym.info.resultType,
5959
coord = tree.pos).enteredAfter(thisTransform)
60-
61-
lazy val field = sym.field.orElse(newField).asTerm
60+
61+
lazy val field = sym.field.orElse(newField).asTerm
6262
if (sym.is(Accessor, butNot = NoFieldNeeded))
6363
if (sym.isGetter) {
6464
tree.rhs.changeOwnerAfter(sym, field, thisTransform)

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,14 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
152152
def traitInits(mixin: ClassSymbol): List[Tree] =
153153
for (getter <- mixin.info.decls.filter(getr => getr.isGetter && !wasDeferred(getr)).toList)
154154
yield {
155-
// transformFollowing call is needed to make memoize & lazy vals run
156-
transformFollowing(DefDef(implementation(getter.asTerm), superRef(initializer(getter)).appliedToNone))
155+
// transformFollowing call is needed to make memoize & lazy vals run
156+
val rhs = transformFollowing(superRef(initializer(getter)).appliedToNone)
157+
// isCurrent: getter is a member of implementing class
158+
val isCurrent = getter.is(ExpandedName) || ctx.atPhase(thisTransform) { implicit ctx =>
159+
cls.info.member(getter.name).suchThat(_.isGetter).symbol == getter
160+
}
161+
if (isCurrent) transformFollowing(DefDef(implementation(getter.asTerm), rhs))
162+
else rhs
157163
}
158164

159165
def setters(mixin: ClassSymbol): List[Tree] =

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
8383
def methodOverrides(mixin: ClassSymbol): List[Tree] = {
8484
def isOverridden(meth: Symbol) = meth.overridingSymbol(cls).is(Method, butNot = Deferred)
8585
def needsDisambiguation(meth: Symbol): Boolean =
86-
meth.is(Method, butNot = PrivateOrDeferred) &&
86+
meth.is(Method, butNot = PrivateOrAccessorOrDeferred) &&
8787
!isOverridden(meth) &&
8888
!meth.allOverriddenSymbols.forall(_ is Deferred)
8989
for (meth <- mixin.info.decls.toList if needsDisambiguation(meth))
@@ -107,5 +107,5 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
107107
else ddef
108108
}
109109

110-
private val PrivateOrDeferred = Private | Deferred
110+
private val PrivateOrAccessorOrDeferred = Private | Accessor | Deferred
111111
}

tests/run/supercalls-traits.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
trait A {
2+
def foo = 1
3+
}
4+
5+
trait B {
6+
def foo = 2
7+
}
8+
9+
class C extends A with B {
10+
override def foo = super[A].foo + super[B].foo
11+
}
12+
13+
object Test {
14+
def main(args: Array[String]) = assert(new C().foo == 3)
15+
}

tests/run/traits-initialization.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
object store {
2+
var str = ""
3+
}
4+
5+
import store._
6+
7+
trait A {
8+
str += "a"
9+
val i = 2
10+
val s = str += 'A'
11+
str += '1'
12+
}
13+
14+
trait B extends A {
15+
str += 'b'
16+
override val i = 3
17+
override val s = str += 'B'
18+
str += '2'
19+
}
20+
21+
class D(sup: Unit) extends A {
22+
str += 'd'
23+
override val i = 4
24+
override val s = str += 'D'
25+
str += '3'
26+
}
27+
28+
class E(sup: Unit) extends A with B {
29+
str += 'd'
30+
override val i = 5
31+
override val s = str += 'E'
32+
str += '3'
33+
}
34+
35+
36+
object Test extends D({str += "Z"}) with B {
37+
// should only have 2 fields
38+
str += 'E'
39+
def main(args: Array[String]) = assert(str == "ZaA1dD3bB2E4", str)
40+
str += '4'
41+
}

0 commit comments

Comments
 (0)