1- package dotty .tools .dotc
1+ package dotty .tools
2+ package dotc
23package transform
34
45import core ._
@@ -176,49 +177,60 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
176177 }) ++ initBuf
177178 }
178179
179- /** Map constructor call to a pair of a supercall and a list of arguments
180- * to be used as initializers of trait parameters if the target of the call
181- * 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
182185 */
183- def transformConstructor (tree : Tree ): (Tree , List [Tree ]) = tree match {
186+ def transformConstructor (tree : Tree ): (Tree , List [Tree ], List [ Tree ] ) = tree match {
184187 case Block (stats, expr) =>
185- val (scall, inits) = transformConstructor(expr)
186- (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)
187202 case _ =>
188203 val Apply (sel @ Select (New (_), nme.CONSTRUCTOR ), args) = tree
189204 val (callArgs, initArgs) = if (tree.symbol.owner.is(Trait )) (Nil , args) else (args, Nil )
190- (superRef(tree.symbol, tree.span).appliedToArgs(callArgs), initArgs)
205+ (superRef(tree.symbol, tree.span).appliedToArgs(callArgs), Nil , initArgs)
191206 }
192207
193- val superCallsAndArgs = (
208+ val superCallsAndArgs : Map [ Symbol , ( Tree , List [ Tree ], List [ Tree ])] = (
194209 for (p <- impl.parents; constr = stripBlock(p).symbol if constr.isConstructor)
195210 yield constr.owner -> transformConstructor(p)
196211 ).toMap
197- val superCalls = superCallsAndArgs.transform((_, v) => v._1)
198- val initArgs = superCallsAndArgs.transform((_, v) => v._2)
199212
200- def superCallOpt (baseCls : Symbol ): List [Tree ] = superCalls .get(baseCls) match {
201- case Some (call) =>
213+ def superCallOpt (baseCls : Symbol ): List [Tree ] = superCallsAndArgs .get(baseCls) match
214+ case Some (( call, _, _) ) =>
202215 if (defn.NotRuntimeClasses .contains(baseCls) || baseCls.isAllOf(NoInitsTrait )) Nil
203216 else call :: Nil
204217 case None =>
205- if (baseCls.isAllOf(NoInitsTrait ) || defn.NoInitClasses .contains(baseCls) || defn.isFunctionClass(baseCls)) Nil
218+ if baseCls.isAllOf(NoInitsTrait ) || defn.NoInitClasses .contains(baseCls) || defn.isFunctionClass(baseCls) then
219+ Nil
206220 else
207221 // println(i"synth super call ${baseCls.primaryConstructor}: ${baseCls.primaryConstructor.info}")
208222 transformFollowingDeep(superRef(baseCls.primaryConstructor).appliedToNone) :: Nil
209- }
210223
211224 def wasOneOf (sym : Symbol , flags : FlagSet ) =
212225 ctx.atPhase(thisPhase) { sym.isOneOf(flags) }
213226
214227 def traitInits (mixin : ClassSymbol ): List [Tree ] = {
215- var argNum = 0
216- def nextArgument () = initArgs.get(mixin) match {
217- case Some (arguments) =>
218- val result = arguments(argNum)
219- argNum += 1
220- result
221- case None =>
228+ val argsIt = superCallsAndArgs.get(mixin) match
229+ case Some ((_, _, args)) => args.iterator
230+ case _ => Iterator .empty
231+ def nextArgument () =
232+ if argsIt.hasNext then argsIt.next
233+ else
222234 assert(
223235 impl.parents.forall(_.tpe.typeSymbol != mixin),
224236 i " missing parameters for $mixin from $impl should have been caught in typer " )
@@ -227,7 +239,6 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
227239 |needs to be implemented directly so that arguments can be passed """ ,
228240 cls.sourcePos)
229241 EmptyTree
230- }
231242
232243 for (getter <- mixin.info.decls.toList if getter.isGetter && ! wasOneOf(getter, Deferred )) yield {
233244 val isScala2x = mixin.is(Scala2x )
@@ -275,9 +286,18 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
275286 if (cls.is(Trait )) traitDefs(impl.body)
276287 else if (! cls.isPrimitiveValueClass) {
277288 val mixInits = mixins.flatMap { mixin =>
278- flatten(traitInits(mixin)) ::: superCallOpt(mixin) ::: setters(mixin) ::: mixinForwarders(mixin)
289+ val prefix = superCallsAndArgs.get(mixin) match
290+ case Some ((_, inits, _)) => inits
291+ case _ => Nil
292+ prefix
293+ ::: flatten(traitInits(mixin))
294+ ::: superCallOpt(mixin)
295+ ::: setters(mixin)
296+ ::: mixinForwarders(mixin)
279297 }
280- superCallOpt(superCls) ::: mixInits ::: impl.body
298+ superCallOpt(superCls)
299+ ::: mixInits
300+ ::: impl.body
281301 }
282302 else impl.body)
283303 }
0 commit comments