Skip to content

Add a test for supercalls in traits. #611

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 28, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/core/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ object TypeErasure {
else if (sym.isConstructor) outer.addParam(sym.owner.asClass, erase(tp)(erasureCtx))
else erase.eraseInfo(tp, sym)(erasureCtx) match {
case einfo: MethodType if sym.isGetter && einfo.resultType.isRef(defn.UnitClass) =>
defn.BoxedUnitClass.typeRef
MethodType(Nil, Nil, defn.BoxedUnitClass.typeRef)
case einfo =>
einfo
}
Expand Down
6 changes: 3 additions & 3 deletions src/dotty/tools/dotc/transform/Memoize.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ import Decorators._

override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
val sym = tree.symbol

def newField = ctx.newSymbol(
owner = ctx.owner,
name = sym.name.asTermName.fieldName,
flags = Private | (if (sym is Stable) EmptyFlags else Mutable),
info = sym.info.resultType,
coord = tree.pos).enteredAfter(thisTransform)
lazy val field = sym.field.orElse(newField).asTerm

lazy val field = sym.field.orElse(newField).asTerm
if (sym.is(Accessor, butNot = NoFieldNeeded))
if (sym.isGetter) {
tree.rhs.changeOwnerAfter(sym, field, thisTransform)
Expand Down
10 changes: 8 additions & 2 deletions src/dotty/tools/dotc/transform/Mixin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,14 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
def traitInits(mixin: ClassSymbol): List[Tree] =
for (getter <- mixin.info.decls.filter(getr => getr.isGetter && !wasDeferred(getr)).toList)
yield {
// transformFollowing call is needed to make memoize & lazy vals run
transformFollowing(DefDef(implementation(getter.asTerm), superRef(initializer(getter)).appliedToNone))
// transformFollowing call is needed to make memoize & lazy vals run
val rhs = transformFollowing(superRef(initializer(getter)).appliedToNone)
// isCurrent: getter is a member of implementing class
val isCurrent = getter.is(ExpandedName) || ctx.atPhase(thisTransform) { implicit ctx =>
cls.info.member(getter.name).suchThat(_.isGetter).symbol == getter
}
if (isCurrent) transformFollowing(DefDef(implementation(getter.asTerm), rhs))
else rhs
}

def setters(mixin: ClassSymbol): List[Tree] =
Expand Down
4 changes: 2 additions & 2 deletions src/dotty/tools/dotc/transform/ResolveSuper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
def methodOverrides(mixin: ClassSymbol): List[Tree] = {
def isOverridden(meth: Symbol) = meth.overridingSymbol(cls).is(Method, butNot = Deferred)
def needsDisambiguation(meth: Symbol): Boolean =
meth.is(Method, butNot = PrivateOrDeferred) &&
meth.is(Method, butNot = PrivateOrAccessorOrDeferred) &&
!isOverridden(meth) &&
!meth.allOverriddenSymbols.forall(_ is Deferred)
for (meth <- mixin.info.decls.toList if needsDisambiguation(meth))
Expand All @@ -107,5 +107,5 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
else ddef
}

private val PrivateOrDeferred = Private | Deferred
private val PrivateOrAccessorOrDeferred = Private | Accessor | Deferred
}
15 changes: 15 additions & 0 deletions tests/run/supercalls-traits.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
trait A {
def foo = 1
}

trait B {
def foo = 2
}

class C extends A with B {
override def foo = super[A].foo + super[B].foo
}

object Test {
def main(args: Array[String]) = assert(new C().foo == 3)
}
41 changes: 41 additions & 0 deletions tests/run/traits-initialization.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
object store {
var str = ""
}

import store._

trait A {
str += "a"
val i = 2
val s = str += 'A'
str += '1'
}

trait B extends A {
str += 'b'
override val i = 3
override val s = str += 'B'
str += '2'
}

class D(sup: Unit) extends A {
str += 'd'
override val i = 4
override val s = str += 'D'
str += '3'
}

class E(sup: Unit) extends A with B {
str += 'd'
override val i = 5
override val s = str += 'E'
str += '3'
}


object Test extends D({str += "Z"}) with B {
// should only have 2 fields
str += 'E'
def main(args: Array[String]) = assert(str == "ZaA1dD3bB2E4", str)
str += '4'
}