@@ -177,98 +177,61 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
177
177
}) ++ initBuf
178
178
}
179
179
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
183
185
*/
184
- def transformConstructor (tree : Tree ): (Tree , List [Tree ]) = tree match {
186
+ def transformConstructor (tree : Tree ): (Tree , List [Tree ], List [ Tree ] ) = tree match {
185
187
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)
188
202
case _ =>
189
203
val Apply (sel @ Select (New (_), nme.CONSTRUCTOR ), args) = tree
190
204
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)
192
206
}
193
207
194
- val superCallsAndArgs = (
208
+ val superCallsAndArgs : Map [ Symbol , ( Tree , List [ Tree ], List [ Tree ])] = (
195
209
for (p <- impl.parents; constr = stripBlock(p).symbol if constr.isConstructor)
196
210
yield constr.owner -> transformConstructor(p)
197
211
).toMap
198
212
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, _, _)) =>
220
216
if (defn.NotRuntimeClasses .contains(baseCls) || baseCls.isAllOf(NoInitsTrait )) Nil
221
217
else call :: Nil
222
218
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
224
221
else
225
222
// println(i"synth super call ${baseCls.primaryConstructor}: ${baseCls.primaryConstructor.info}")
226
223
transformFollowingDeep(superRef(baseCls.primaryConstructor).appliedToNone) :: Nil
227
- }
228
224
229
225
def wasOneOf (sym : Symbol , flags : FlagSet ) =
230
226
ctx.atPhase(thisPhase) { sym.isOneOf(flags) }
231
227
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
-
264
228
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
272
235
assert(
273
236
impl.parents.forall(_.tpe.typeSymbol != mixin),
274
237
i " missing parameters for $mixin from $impl should have been caught in typer " )
@@ -277,7 +240,6 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
277
240
|needs to be implemented directly so that arguments can be passed """ ,
278
241
cls.sourcePos)
279
242
EmptyTree
280
- }
281
243
282
244
for (getter <- mixin.info.decls.toList if getter.isGetter && ! wasOneOf(getter, Deferred )) yield {
283
245
val isScala2x = mixin.is(Scala2x )
@@ -325,13 +287,18 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
325
287
if (cls.is(Trait )) traitDefs(impl.body)
326
288
else if (! cls.isPrimitiveValueClass) {
327
289
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)
333
298
}
334
- superCallOpt(superCls) ::: mixInits ::: impl.body
299
+ superCallOpt(superCls)
300
+ ::: mixInits
301
+ ::: impl.body
335
302
}
336
303
else impl.body)
337
304
}
0 commit comments