From 7b1fc312fbaeafbeb1eadc080be1aa2e905963e2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 22 Jul 2016 22:20:53 +0200 Subject: [PATCH 1/2] Fix #1263: Suppress super initializer call for val parameters of traits. Val-parameters of traits don't have an initializer, as other vals do. So we cannot call the initializer in an initialization sequence of a subclass. Fixes #1263. --- src/dotty/tools/dotc/transform/Mixin.scala | 14 +++++++------- tests/run/i1263.scala | 10 ++++++++++ 2 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 tests/run/i1263.scala diff --git a/src/dotty/tools/dotc/transform/Mixin.scala b/src/dotty/tools/dotc/transform/Mixin.scala index b0d1e5c5f75e..8cdc82f7ab66 100644 --- a/src/dotty/tools/dotc/transform/Mixin.scala +++ b/src/dotty/tools/dotc/transform/Mixin.scala @@ -182,8 +182,8 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => } } - def wasDeferred(sym: Symbol) = - ctx.atPhase(thisTransform) { implicit ctx => sym is Deferred } + def was(sym: Symbol, flags: FlagSet) = + ctx.atPhase(thisTransform) { implicit ctx => sym is flags } def traitInits(mixin: ClassSymbol): List[Tree] = { var argNum = 0 @@ -202,7 +202,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => EmptyTree } - for (getter <- mixin.info.decls.filter(getr => getr.isGetter && !wasDeferred(getr)).toList) yield { + for (getter <- mixin.info.decls.toList if getter.isGetter && !was(getter, Deferred)) yield { val isScala2x = mixin.is(Scala2x) def default = Underscore(getter.info.resultType) def initial = transformFollowing(superRef(initializer(getter)).appliedToNone) @@ -220,23 +220,23 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => if (isCurrent(getter) || getter.is(ExpandedName)) { val rhs = - if (ctx.atPhase(thisTransform)(implicit ctx => getter.is(ParamAccessor))) nextArgument() + if (was(getter, ParamAccessor)) nextArgument() else if (isScala2x) if (getter.is(Lazy, butNot = Module)) lazyGetterCall else if (getter.is(Module)) New(getter.info.resultType, List(This(cls))) else Underscore(getter.info.resultType) - else transformFollowing(superRef(initializer(getter)).appliedToNone) + else initial // transformFollowing call is needed to make memoize & lazy vals run transformFollowing(DefDef(implementation(getter.asTerm), rhs)) } - else if (isScala2x) EmptyTree + else if (isScala2x || was(getter, ParamAccessor)) EmptyTree else initial } } def setters(mixin: ClassSymbol): List[Tree] = - for (setter <- mixin.info.decls.filter(setr => setr.isSetter && !wasDeferred(setr)).toList) + for (setter <- mixin.info.decls.filter(setr => setr.isSetter && !was(setr, Deferred)).toList) yield transformFollowing(DefDef(implementation(setter.asTerm), unitLiteral.withPos(cls.pos))) cpy.Template(impl)( diff --git a/tests/run/i1263.scala b/tests/run/i1263.scala new file mode 100644 index 000000000000..4ae2557115cb --- /dev/null +++ b/tests/run/i1263.scala @@ -0,0 +1,10 @@ +object Test { + trait Foo(val s: String) + + val foo1 = new Foo("bar") {} + val foo2 = new Foo { override val s = "bar" } + def main(args: Array[String]): Unit = { + assert(foo1.s == "bar") + assert(foo2.s == "bar") + } +} From 66b04551306a20d1a8b1efd4914193e49209cf76 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 25 Jul 2016 12:51:35 +0200 Subject: [PATCH 2/2] Extend test case to test variations of modifiers on trait parameters. --- tests/run/i1263.scala | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/run/i1263.scala b/tests/run/i1263.scala index 4ae2557115cb..630e5758e046 100644 --- a/tests/run/i1263.scala +++ b/tests/run/i1263.scala @@ -8,3 +8,27 @@ object Test { assert(foo2.s == "bar") } } +object Test1 { + trait Foo(private val s0: String) { + def s = s0 + } + + val foo1 = new Foo("bar") {} + def main(args: Array[String]): Unit = { + assert(foo1.s == "bar") + } +} +object Test2 { + trait Foo(protected val s: String) + + val foo1 = new Foo("bar") {} + val foo2 = new Foo { override val s = "bar" } +} +object Test3 { + trait Foo(final val s: String) + + val foo1 = new Foo("bar") {} + def main(args: Array[String]): Unit = { + assert(foo1.s == "bar") + } +}