Skip to content

Commit f4520d4

Browse files
committed
Simplify implementation
1 parent 9b6cd3d commit f4520d4

File tree

1 file changed

+44
-77
lines changed

1 file changed

+44
-77
lines changed

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

Lines changed: 44 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -177,98 +177,61 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
177177
}) ++ initBuf
178178
}
179179

180-
/** Map constructor call to a pair of a supercall and a list of arguments
181-
* to be used as initializers of trait parameters if the target of the call
182-
* is a trait.
180+
/** Map constructor call to a triple of a supercall, and if the target
181+
* is a trait
182+
* - a list of val defs used in arguments (these can arise
183+
* due to reorderings with named and/or default parameters).
184+
* - a list of arguments to be used as initializers of trait parameters
183185
*/
184-
def transformConstructor(tree: Tree): (Tree, List[Tree]) = tree match {
186+
def transformConstructor(tree: Tree): (Tree, List[Tree], List[Tree]) = tree match {
185187
case Block(stats, expr) =>
186-
val (scall, inits) = transformConstructor(expr)
187-
(cpy.Block(tree)(stats, scall), inits)
188+
val (scall, inits, args) = transformConstructor(expr)
189+
if args.isEmpty then
190+
(cpy.Block(tree)(stats, scall), inits, args)
191+
else // it's a trait constructor with parameters, lift all prefix statements to class context
192+
// so that they precede argument definitions.
193+
stats.foreach {
194+
case stat: ValDef =>
195+
stat.symbol.copySymDenotation(
196+
owner = cls,
197+
initFlags = stat.symbol.flags | PrivateLocal
198+
).installAfter(thisPhase)
199+
stat.symbol.enteredAfter(thisPhase)
200+
}
201+
(scall, stats ::: inits, args)
188202
case _ =>
189203
val Apply(sel @ Select(New(_), nme.CONSTRUCTOR), args) = tree
190204
val (callArgs, initArgs) = if (tree.symbol.owner.is(Trait)) (Nil, args) else (args, Nil)
191-
(superRef(tree.symbol, tree.span).appliedToArgs(callArgs), initArgs)
205+
(superRef(tree.symbol, tree.span).appliedToArgs(callArgs), Nil, initArgs)
192206
}
193207

194-
val superCallsAndArgs = (
208+
val superCallsAndArgs: Map[Symbol, (Tree, List[Tree], List[Tree])] = (
195209
for (p <- impl.parents; constr = stripBlock(p).symbol if constr.isConstructor)
196210
yield constr.owner -> transformConstructor(p)
197211
).toMap
198212

199-
/** Definitions in a parent trait constructor call (these can arise
200-
* due to reorderings with named and/or default parameters).
201-
*/
202-
def prefix(tree: Tree): List[Tree] =
203-
if stripBlock(tree).symbol.owner.is(Trait) then
204-
tree match
205-
case Block(stats, expr) => stats ::: prefix(expr)
206-
case _ => Nil
207-
else Nil
208-
209-
/** the proper trait parent constructor call, without any preceding val defs */
210-
def properCall(tree: Tree): Tree =
211-
val call = stripBlock(tree)
212-
if call.symbol.owner.is(Trait) then call else tree
213-
214-
val prefixes = superCallsAndArgs.transform((_, v) => prefix(v._1))
215-
val superCalls = superCallsAndArgs.transform((_, v) => properCall(v._1))
216-
val initArgs = superCallsAndArgs.transform((_, v) => v._2)
217-
218-
def superCallOpt(baseCls: Symbol): List[Tree] = superCalls.get(baseCls) match {
219-
case Some(call) =>
213+
def superCallOpt(baseCls: Symbol): List[Tree] =
214+
superCallsAndArgs.get(baseCls) match
215+
case Some((call, _, _)) =>
220216
if (defn.NotRuntimeClasses.contains(baseCls) || baseCls.isAllOf(NoInitsTrait)) Nil
221217
else call :: Nil
222218
case None =>
223-
if (baseCls.isAllOf(NoInitsTrait) || defn.NoInitClasses.contains(baseCls) || defn.isFunctionClass(baseCls)) Nil
219+
if baseCls.isAllOf(NoInitsTrait) || defn.NoInitClasses.contains(baseCls) || defn.isFunctionClass(baseCls) then
220+
Nil
224221
else
225222
//println(i"synth super call ${baseCls.primaryConstructor}: ${baseCls.primaryConstructor.info}")
226223
transformFollowingDeep(superRef(baseCls.primaryConstructor).appliedToNone) :: Nil
227-
}
228224

229225
def wasOneOf(sym: Symbol, flags: FlagSet) =
230226
ctx.atPhase(thisPhase) { sym.isOneOf(flags) }
231227

232-
/** The prefix definitions of a mixin parent constructor, lifted
233-
* to the enclosing class.
234-
*/
235-
def traitConstrPrefix(mixin: ClassSymbol): List[Tree] =
236-
prefixes.get(mixin) match
237-
case Some(stats) =>
238-
stats.map {
239-
case stat: ValDef =>
240-
stat.symbol.copySymDenotation(
241-
owner = cls,
242-
initFlags = stat.symbol.flags | PrivateLocal
243-
).installAfter(thisPhase)
244-
stat.symbol.enteredAfter(thisPhase)
245-
stat
246-
}
247-
case _ =>
248-
Nil
249-
250-
/** Adapt tree so that references to valdefs that are lifted to the
251-
* class now use `this` as a prefix
252-
*/
253-
def adaptToPrefix(stat: Tree, prefixSyms: List[Symbol]) =
254-
if prefixSyms.isEmpty then stat
255-
else
256-
val m = new TreeMap:
257-
override def transform(tree: Tree)(using Context) = tree match
258-
case tree: Ident if prefixSyms.contains(tree.symbol) =>
259-
This(cls).select(tree.symbol).withSpan(tree.span)
260-
case _ =>
261-
super.transform(tree)
262-
m.transform(stat)
263-
264228
def traitInits(mixin: ClassSymbol): List[Tree] = {
265-
var argNum = 0
266-
def nextArgument() = initArgs.get(mixin) match {
267-
case Some(arguments) =>
268-
val result = arguments(argNum)
269-
argNum += 1
270-
result
271-
case None =>
229+
val argsIt = superCallsAndArgs.get(mixin) match
230+
case Some((_, _, args)) => args.iterator
231+
case _ => Iterator.empty
232+
def nextArgument() =
233+
if argsIt.hasNext then argsIt.next
234+
else
272235
assert(
273236
impl.parents.forall(_.tpe.typeSymbol != mixin),
274237
i"missing parameters for $mixin from $impl should have been caught in typer")
@@ -277,7 +240,6 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
277240
|needs to be implemented directly so that arguments can be passed""",
278241
cls.sourcePos)
279242
EmptyTree
280-
}
281243

282244
for (getter <- mixin.info.decls.toList if getter.isGetter && !wasOneOf(getter, Deferred)) yield {
283245
val isScala2x = mixin.is(Scala2x)
@@ -325,13 +287,18 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
325287
if (cls.is(Trait)) traitDefs(impl.body)
326288
else if (!cls.isPrimitiveValueClass) {
327289
val mixInits = mixins.flatMap { mixin =>
328-
val prefix = traitConstrPrefix(mixin)
329-
val prefixSyms = prefix.map(_.symbol)
330-
val initsAndCall = (flatten(traitInits(mixin)) ::: superCallOpt(mixin))
331-
.map(adaptToPrefix(_, prefixSyms))
332-
prefix ::: initsAndCall ::: setters(mixin) ::: mixinForwarders(mixin)
290+
val prefix = superCallsAndArgs.get(mixin) match
291+
case Some((_, inits, _)) => inits
292+
case _ => Nil
293+
prefix
294+
::: flatten(traitInits(mixin))
295+
::: superCallOpt(mixin)
296+
::: setters(mixin)
297+
::: mixinForwarders(mixin)
333298
}
334-
superCallOpt(superCls) ::: mixInits ::: impl.body
299+
superCallOpt(superCls)
300+
::: mixInits
301+
::: impl.body
335302
}
336303
else impl.body)
337304
}

0 commit comments

Comments
 (0)