Skip to content

Commit b2da316

Browse files
committed
wip
1 parent 06f311c commit b2da316

File tree

1 file changed

+34
-35
lines changed

1 file changed

+34
-35
lines changed

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

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Decorators._
1313
import DenotTransformers._
1414
import StdNames._
1515
import NameKinds._
16+
import NameOps._
1617
import ast.Trees._
1718
import collection.mutable
1819

@@ -145,32 +146,38 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
145146
}
146147
}.asTerm
147148

149+
private def wasOneOf(sym: Symbol, flags: FlagSet)(implicit ctx: Context): Boolean =
150+
ctx.atPhase(thisPhase) { sym.isOneOf(flags) }
151+
152+
private def needsTraitSetter(sym: Symbol)(implicit ctx: Context): Boolean =
153+
sym.isGetter && !wasOneOf(sym, DeferredOrLazy | ParamAccessor) && !sym.setter.exists
154+
&& !sym.info.resultType.isInstanceOf[ConstantType]
155+
156+
private def traitSetter(getter: TermSymbol)(implicit ctx: Context): Symbol =
157+
getter.copy(
158+
name = getter.ensureNotPrivate.name
159+
.expandedName(getter.owner, TraitSetterName)
160+
.asTermName.setterName,
161+
flags = Method | Accessor | Deferred,
162+
info = MethodType(getter.info.resultType :: Nil, defn.UnitType))
163+
148164
override def transformTemplate(impl: Template)(implicit ctx: Context): Template = {
149165
val cls = impl.symbol.owner.asClass
150166
val ops = new MixinOps(cls, thisPhase)
151167
import ops._
152168

153169
def traitDefs(stats: List[Tree]): List[Tree] = {
154-
val initBuf = new mutable.ListBuffer[Tree]
155-
stats.flatMap({
156-
case stat: DefDef if stat.symbol.isGetter && !stat.rhs.isEmpty && !stat.symbol.is(Lazy) =>
157-
// make initializer that has all effects of previous getter,
158-
// replace getter rhs with empty tree.
159-
val vsym = stat.symbol
160-
val isym = initializer(vsym)
161-
val rhs = Block(
162-
initBuf.toList.map(_.changeOwnerAfter(impl.symbol, isym, thisPhase)),
163-
stat.rhs.changeOwnerAfter(vsym, isym, thisPhase).wildcardToDefault)
164-
initBuf.clear()
165-
cpy.DefDef(stat)(rhs = EmptyTree) :: DefDef(isym, rhs) :: Nil
170+
stats.flatMap {
171+
case stat: DefDef if needsTraitSetter(stat.symbol) =>
172+
// add a trait setter for this getter
173+
val vsym = stat.symbol.asTerm
174+
val ssym = traitSetter(vsym).asTerm.enteredAfter(thisPhase)
175+
stat :: DefDef(ssym, EmptyTree) :: Nil
166176
case stat: DefDef if stat.symbol.isSetter =>
167177
cpy.DefDef(stat)(rhs = EmptyTree) :: Nil
168-
case stat: DefTree =>
169-
stat :: Nil
170178
case stat =>
171-
initBuf += stat
172-
Nil
173-
}) ++ initBuf
179+
stat :: Nil
180+
}
174181
}
175182

176183
/** Map constructor call to a pair of a supercall and a list of arguments
@@ -205,9 +212,6 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
205212
transformFollowingDeep(superRef(baseCls.primaryConstructor).appliedToNone) :: Nil
206213
}
207214

208-
def wasOneOf(sym: Symbol, flags: FlagSet) =
209-
ctx.atPhase(thisPhase) { sym.isOneOf(flags) }
210-
211215
def traitInits(mixin: ClassSymbol): List[Tree] = {
212216
var argNum = 0
213217
def nextArgument() = initArgs.get(mixin) match {
@@ -227,33 +231,28 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
227231
}
228232

229233
for (getter <- mixin.info.decls.toList if getter.isGetter && !wasOneOf(getter, Deferred)) yield {
230-
val isScala2x = mixin.is(Scala2x)
231-
def default = Underscore(getter.info.resultType)
232-
def initial = transformFollowing(superRef(initializer(getter)).appliedToNone)
233-
234234
if (isCurrent(getter) || getter.name.is(ExpandedName)) {
235235
val rhs =
236236
if (wasOneOf(getter, ParamAccessor))
237237
nextArgument()
238-
else if (isScala2x)
239-
if (getter.is(Lazy, butNot = Module))
240-
initial
241-
else if (getter.is(Module))
242-
New(getter.info.resultType, List(This(cls)))
243-
else
244-
Underscore(getter.info.resultType)
238+
else if (getter.is(Lazy, butNot = Module))
239+
transformFollowing(superRef(getter).appliedToNone)
240+
else if (getter.is(Module))
241+
New(getter.info.resultType, List(This(cls)))
245242
else
246-
initial
243+
Underscore(getter.info.resultType)
247244
// transformFollowing call is needed to make memoize & lazy vals run
248245
transformFollowing(DefDef(mkForwarderSym(getter.asTerm), rhs))
249246
}
250-
else if (isScala2x || wasOneOf(getter, ParamAccessor | Lazy)) EmptyTree
251-
else initial
247+
else EmptyTree
252248
}
253249
}
254250

255251
def setters(mixin: ClassSymbol): List[Tree] =
256-
for (setter <- mixin.info.decls.filter(setr => setr.isSetter && !wasOneOf(setr, Deferred)))
252+
val mixinSetters = mixin.info.decls.filter { sym =>
253+
sym.isSetter && (!wasOneOf(sym, Deferred) || sym.name.is(TraitSetterName))
254+
}
255+
for (setter <- mixinSetters)
257256
yield transformFollowing(DefDef(mkForwarderSym(setter.asTerm), unitLiteral.withSpan(cls.span)))
258257

259258
def mixinForwarders(mixin: ClassSymbol): List[Tree] =

0 commit comments

Comments
 (0)