1
- package dotty .tools .dotc
1
+ package dotty .tools
2
+ package dotc
2
3
package transform
3
4
4
5
import core ._
@@ -176,49 +177,60 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
176
177
}) ++ initBuf
177
178
}
178
179
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
182
185
*/
183
- def transformConstructor (tree : Tree ): (Tree , List [Tree ]) = tree match {
186
+ def transformConstructor (tree : Tree ): (Tree , List [Tree ], List [ Tree ] ) = tree match {
184
187
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)
187
202
case _ =>
188
203
val Apply (sel @ Select (New (_), nme.CONSTRUCTOR ), args) = tree
189
204
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)
191
206
}
192
207
193
- val superCallsAndArgs = (
208
+ val superCallsAndArgs : Map [ Symbol , ( Tree , List [ Tree ], List [ Tree ])] = (
194
209
for (p <- impl.parents; constr = stripBlock(p).symbol if constr.isConstructor)
195
210
yield constr.owner -> transformConstructor(p)
196
211
).toMap
197
- val superCalls = superCallsAndArgs.transform((_, v) => v._1)
198
- val initArgs = superCallsAndArgs.transform((_, v) => v._2)
199
212
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, _, _) ) =>
202
215
if (defn.NotRuntimeClasses .contains(baseCls) || baseCls.isAllOf(NoInitsTrait )) Nil
203
216
else call :: Nil
204
217
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
206
220
else
207
221
// println(i"synth super call ${baseCls.primaryConstructor}: ${baseCls.primaryConstructor.info}")
208
222
transformFollowingDeep(superRef(baseCls.primaryConstructor).appliedToNone) :: Nil
209
- }
210
223
211
224
def wasOneOf (sym : Symbol , flags : FlagSet ) =
212
225
ctx.atPhase(thisPhase) { sym.isOneOf(flags) }
213
226
214
227
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
222
234
assert(
223
235
impl.parents.forall(_.tpe.typeSymbol != mixin),
224
236
i " missing parameters for $mixin from $impl should have been caught in typer " )
@@ -227,7 +239,6 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
227
239
|needs to be implemented directly so that arguments can be passed """ ,
228
240
cls.sourcePos)
229
241
EmptyTree
230
- }
231
242
232
243
for (getter <- mixin.info.decls.toList if getter.isGetter && ! wasOneOf(getter, Deferred )) yield {
233
244
val isScala2x = mixin.is(Scala2x )
@@ -275,9 +286,18 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
275
286
if (cls.is(Trait )) traitDefs(impl.body)
276
287
else if (! cls.isPrimitiveValueClass) {
277
288
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)
279
297
}
280
- superCallOpt(superCls) ::: mixInits ::: impl.body
298
+ superCallOpt(superCls)
299
+ ::: mixInits
300
+ ::: impl.body
281
301
}
282
302
else impl.body)
283
303
}
0 commit comments