@@ -305,24 +305,41 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
305
305
def TypeDef (sym : TypeSymbol )(using Context ): TypeDef =
306
306
ta.assignType(untpd.TypeDef (sym.name, TypeTree (sym.info)), sym)
307
307
308
- def ClassDef (cls : ClassSymbol , constr : DefDef , body : List [Tree ], superArgs : List [Tree ] = Nil )(using Context ): TypeDef = {
308
+ /** Create a class definition
309
+ * @param cls the class symbol of the created class
310
+ * @param constr its primary constructor
311
+ * @param body the statements in its template
312
+ * @param superArgs the arguments to pass to the superclass constructor
313
+ * @param adaptVarargs if true, allow matching a vararg superclass constructor
314
+ * with a missing argument in superArgs, and synthesize an
315
+ * empty repeated parameter in the supercall in this case
316
+ */
317
+ def ClassDef (cls : ClassSymbol , constr : DefDef , body : List [Tree ],
318
+ superArgs : List [Tree ] = Nil , adaptVarargs : Boolean = false )(using Context ): TypeDef =
309
319
val firstParent :: otherParents = cls.info.parents: @ unchecked
320
+
321
+ def adaptedSuperArgs (ctpe : Type ): List [Tree ] = ctpe match
322
+ case ctpe : PolyType =>
323
+ adaptedSuperArgs(ctpe.instantiate(firstParent.argTypes))
324
+ case ctpe : MethodType
325
+ if ctpe.paramInfos.length == superArgs.length + 1 =>
326
+ // last argument must be a vararg, otherwise isApplicable would have failed
327
+ superArgs :+
328
+ repeated(Nil , TypeTree (ctpe.paramInfos.last.argInfos.head, inferred = true ))
329
+ case _ =>
330
+ superArgs
331
+
310
332
val superRef =
311
- if (cls.is(Trait )) TypeTree (firstParent)
312
- else {
313
- def isApplicable (ctpe : Type ): Boolean = ctpe match {
314
- case ctpe : PolyType =>
315
- isApplicable(ctpe.instantiate(firstParent.argTypes))
316
- case ctpe : MethodType =>
317
- (superArgs corresponds ctpe.paramInfos)(_.tpe <:< _)
318
- case _ =>
319
- false
320
- }
321
- val constr = firstParent.decl(nme.CONSTRUCTOR ).suchThat(constr => isApplicable(constr.info))
322
- New (firstParent, constr.symbol.asTerm, superArgs)
323
- }
333
+ if cls.is(Trait ) then TypeTree (firstParent)
334
+ else
335
+ val parentConstr = firstParent.applicableConstructors(superArgs.tpes, adaptVarargs) match
336
+ case Nil => assert(false , i " no applicable parent constructor of $firstParent for supercall arguments $superArgs" )
337
+ case constr :: Nil => constr
338
+ case _ => assert(false , i " multiple applicable parent constructors of $firstParent for supercall arguments $superArgs" )
339
+ New (firstParent, parentConstr.asTerm, adaptedSuperArgs(parentConstr.info))
340
+
324
341
ClassDefWithParents (cls, constr, superRef :: otherParents.map(TypeTree (_)), body)
325
- }
342
+ end ClassDef
326
343
327
344
def ClassDefWithParents (cls : ClassSymbol , constr : DefDef , parents : List [Tree ], body : List [Tree ])(using Context ): TypeDef = {
328
345
val selfType =
@@ -349,13 +366,18 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
349
366
* @param parents a non-empty list of class types
350
367
* @param termForwarders a non-empty list of forwarding definitions specified by their name and the definition they forward to.
351
368
* @param typeMembers a possibly-empty list of type members specified by their name and their right hand side.
369
+ * @param adaptVarargs if true, allow matching a vararg superclass constructor
370
+ * with a missing argument in superArgs, and synthesize an
371
+ * empty repeated parameter in the supercall in this case
352
372
*
353
373
* The class has the same owner as the first function in `termForwarders`.
354
374
* Its position is the union of all symbols in `termForwarders`.
355
375
*/
356
- def AnonClass (parents : List [Type ], termForwarders : List [(TermName , TermSymbol )],
357
- typeMembers : List [(TypeName , TypeBounds )] = Nil )(using Context ): Block = {
358
- AnonClass (termForwarders.head._2.owner, parents, termForwarders.map(_._2.span).reduceLeft(_ union _)) { cls =>
376
+ def AnonClass (parents : List [Type ],
377
+ termForwarders : List [(TermName , TermSymbol )],
378
+ typeMembers : List [(TypeName , TypeBounds )],
379
+ adaptVarargs : Boolean )(using Context ): Block = {
380
+ AnonClass (termForwarders.head._2.owner, parents, termForwarders.map(_._2.span).reduceLeft(_ union _), adaptVarargs) { cls =>
359
381
def forwarder (name : TermName , fn : TermSymbol ) = {
360
382
val fwdMeth = fn.copy(cls, name, Synthetic | Method | Final ).entered.asTerm
361
383
for overridden <- fwdMeth.allOverriddenSymbols do
@@ -375,6 +397,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
375
397
* with the specified owner and position.
376
398
*/
377
399
def AnonClass (owner : Symbol , parents : List [Type ], coord : Coord )(body : ClassSymbol => List [Tree ])(using Context ): Block =
400
+ AnonClass (owner, parents, coord, adaptVarargs = false )(body)
401
+
402
+ private def AnonClass (owner : Symbol , parents : List [Type ], coord : Coord , adaptVarargs : Boolean )(body : ClassSymbol => List [Tree ])(using Context ): Block =
378
403
val parents1 =
379
404
if (parents.head.classSymbol.is(Trait )) {
380
405
val head = parents.head.parents.head
@@ -383,7 +408,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
383
408
else parents
384
409
val cls = newNormalizedClassSymbol(owner, tpnme.ANON_CLASS , Synthetic | Final , parents1, coord = coord)
385
410
val constr = newConstructor(cls, Synthetic , Nil , Nil ).entered
386
- val cdef = ClassDef (cls, DefDef (constr), body(cls))
411
+ val cdef = ClassDef (cls, DefDef (constr), body(cls), Nil , adaptVarargs )
387
412
Block (cdef :: Nil , New (cls.typeRef, Nil ))
388
413
389
414
def Import (expr : Tree , selectors : List [untpd.ImportSelector ])(using Context ): Import =
0 commit comments