From c6425f0e103194e50576c591ebab87b19c4b83c3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 27 May 2015 19:14:30 +0200 Subject: Fix bug in typer erasure's transformInfo ()Unit translates to ()BoxedUnit not BoxedUnit. --- src/dotty/tools/dotc/core/TypeErasure.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala index 65bc5e57f..fac795ef8 100644 --- a/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/src/dotty/tools/dotc/core/TypeErasure.scala @@ -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 } -- cgit v1.2.3 From d81fc0395d525f4dd0ec7d1707b3f0249b014edb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 27 May 2015 19:20:32 +0200 Subject: Mixin: generate a getter in implementing class only if current A class might implement several fields in inherited traits with the same and type. In that case only one getter should be produced, but all initializing expressions have to be executed. --- src/dotty/tools/dotc/transform/Memoize.scala | 6 +++--- src/dotty/tools/dotc/transform/Mixin.scala | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/dotty/tools/dotc/transform/Memoize.scala b/src/dotty/tools/dotc/transform/Memoize.scala index d96a52868..cbde1ef8a 100644 --- a/src/dotty/tools/dotc/transform/Memoize.scala +++ b/src/dotty/tools/dotc/transform/Memoize.scala @@ -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) diff --git a/src/dotty/tools/dotc/transform/Mixin.scala b/src/dotty/tools/dotc/transform/Mixin.scala index 8470be2ef..d5c5746f3 100644 --- a/src/dotty/tools/dotc/transform/Mixin.scala +++ b/src/dotty/tools/dotc/transform/Mixin.scala @@ -153,7 +153,12 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => 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)) + val rhs = transformFollowing(superRef(initializer(getter)).appliedToNone) + val isCurrent = 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] = -- cgit v1.2.3 From 05679f3afccc2a3085bc089bccbdc03096fb90a0 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 27 May 2015 19:21:23 +0200 Subject: Extended test case. Also added non-unit fields and a class that directly implements two traits with the same fields. --- src/dotty/tools/dotc/transform/ResolveSuper.scala | 4 ++-- tests/run/traits-initialization.scala | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/dotty/tools/dotc/transform/ResolveSuper.scala b/src/dotty/tools/dotc/transform/ResolveSuper.scala index 9c0e34256..0f1c448d9 100644 --- a/src/dotty/tools/dotc/transform/ResolveSuper.scala +++ b/src/dotty/tools/dotc/transform/ResolveSuper.scala @@ -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)) @@ -107,5 +107,5 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th else ddef } - private val PrivateOrDeferred = Private | Deferred + private val PrivateOrAccessorOrDeferred = Private | Accessor | Deferred } diff --git a/tests/run/traits-initialization.scala b/tests/run/traits-initialization.scala index 2eee3d633..fdddc8f44 100644 --- a/tests/run/traits-initialization.scala +++ b/tests/run/traits-initialization.scala @@ -6,22 +6,32 @@ 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 -- cgit v1.2.3 From 7779b8fefa745e8b034bc33f46d21bd8599ac4a0 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 28 May 2015 10:18:13 +0200 Subject: Refine definition of isCurrent Fixes problem with run/t261.scala. --- src/dotty/tools/dotc/transform/Mixin.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/dotty/tools/dotc/transform/Mixin.scala b/src/dotty/tools/dotc/transform/Mixin.scala index d5c5746f3..d2e7943f8 100644 --- a/src/dotty/tools/dotc/transform/Mixin.scala +++ b/src/dotty/tools/dotc/transform/Mixin.scala @@ -152,9 +152,10 @@ 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 call is needed to make memoize & lazy vals run val rhs = transformFollowing(superRef(initializer(getter)).appliedToNone) - val isCurrent = ctx.atPhase(thisTransform) { implicit ctx => + // 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)) -- cgit v1.2.3