aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/transform/Mixin.scala10
-rw-r--r--tests/run/traitParams.scala6
2 files changed, 12 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/transform/Mixin.scala b/src/dotty/tools/dotc/transform/Mixin.scala
index ce3eb6cda..7319d10cd 100644
--- a/src/dotty/tools/dotc/transform/Mixin.scala
+++ b/src/dotty/tools/dotc/transform/Mixin.scala
@@ -20,7 +20,7 @@ import collection.mutable
/** This phase performs the following transformations:
*
- * 1. (done in `traitDefs` and `transformSym`) Map every concrete trait getter
+ * 1. (done in `traitDefs` and `transformSym`) Map every concrete trait getter
*
* <mods> def x(): T = expr
*
@@ -83,6 +83,8 @@ import collection.mutable
* 4. (done in `transformTemplate` and `transformSym`) Drop all parameters from trait
* constructors.
*
+ * 5. (done in `transformSym`) Drop ParamAccessor flag from all parameter accessors in traits.
+ *
* Conceptually, this is the second half of the previous mixin phase. It needs to run
* after erasure because it copies references to possibly private inner classes and objects
* into enclosing classes where they are not visible. This can only be done if all references
@@ -97,7 +99,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
override def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation =
if (sym.is(Accessor, butNot = Deferred) && sym.owner.is(Trait))
- sym.copySymDenotation(initFlags = sym.flags | Deferred).ensureNotPrivate
+ sym.copySymDenotation(initFlags = sym.flags &~ ParamAccessor | Deferred).ensureNotPrivate
else if (sym.isConstructor && sym.owner.is(Trait) && sym.info.firstParamTypes.nonEmpty)
sym.copySymDenotation(info = MethodType(Nil, sym.info.resultType))
else
@@ -124,7 +126,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
def traitDefs(stats: List[Tree]): List[Tree] = {
val initBuf = new mutable.ListBuffer[Tree]
stats.flatMap({
- case stat: DefDef if stat.symbol.isGetter && !stat.rhs.isEmpty && !stat.symbol.is(Flags.Lazy) =>
+ case stat: DefDef if stat.symbol.isGetter && !stat.rhs.isEmpty && !stat.symbol.is(Flags.Lazy) =>
// make initializer that has all effects of previous getter,
// replace getter rhs with empty tree.
val vsym = stat.symbol
@@ -197,7 +199,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
def initial = transformFollowing(superRef(initializer(getter)).appliedToNone)
if (isCurrent(getter) || getter.is(ExpandedName)) {
val rhs =
- if (getter.is(ParamAccessor)) nextArgument()
+ if (ctx.atPhase(thisTransform)(implicit ctx => getter.is(ParamAccessor))) nextArgument()
else if (isScala2x) Underscore(getter.info.resultType)
else transformFollowing(superRef(initializer(getter)).appliedToNone)
// transformFollowing call is needed to make memoize & lazy vals run
diff --git a/tests/run/traitParams.scala b/tests/run/traitParams.scala
index c1b77cf37..82c176461 100644
--- a/tests/run/traitParams.scala
+++ b/tests/run/traitParams.scala
@@ -10,6 +10,12 @@ trait U extends T {
State.s += 1
override def f = super.f + y
}
+trait U2(a: Any) extends T {
+ def d = a // okay
+ val v = a // okay
+ a // used to crash
+}
+
import State._
class C(x: Int) extends U with T(x, x * x + s)
class C2(x: Int) extends T(x, x * x + s) with U