@@ -315,24 +315,53 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
315315 def TypeDef (sym : TypeSymbol )(using Context ): TypeDef =
316316 ta.assignType(untpd.TypeDef (sym.name, TypeTree (sym.info)), sym)
317317
318- def ClassDef (cls : ClassSymbol , constr : DefDef , body : List [Tree ], superArgs : List [Tree ] = Nil )(using Context ): TypeDef = {
318+ /** Create a class definition
319+ * @param cls the class symbol of the created class
320+ * @param constr its primary constructor
321+ * @param body the statements in its template
322+ * @param superArgs the arguments to pass to the superclass constructor
323+ * @param adaptVarargs if true, allow matching a vararg superclass constructor
324+ * with a missing argument in superArgs, and synthesize an
325+ * empty repeated parameter in the supercall in this case
326+ */
327+ def ClassDef (cls : ClassSymbol , constr : DefDef , body : List [Tree ],
328+ superArgs : List [Tree ] = Nil , adaptVarargs : Boolean = false )(using Context ): TypeDef =
319329 val firstParent :: otherParents = cls.info.parents: @ unchecked
330+
331+ def isApplicable (constr : Symbol ): Boolean =
332+ def recur (ctpe : Type ): Boolean = ctpe match
333+ case ctpe : PolyType =>
334+ recur(ctpe.instantiate(firstParent.argTypes))
335+ case ctpe : MethodType =>
336+ var paramInfos = ctpe.paramInfos
337+ if adaptVarargs && paramInfos.length == superArgs.length + 1
338+ && atPhaseNoLater(Phases .elimRepeatedPhase)(constr.info.isVarArgsMethod)
339+ then // accept missing argument for varargs parameter
340+ paramInfos = paramInfos.init
341+ superArgs.corresponds(paramInfos)(_.tpe <:< _)
342+ case _ =>
343+ false
344+ recur(constr.info)
345+
346+ def adaptedSuperArgs (ctpe : Type ): List [Tree ] = ctpe match
347+ case ctpe : PolyType =>
348+ adaptedSuperArgs(ctpe.instantiate(firstParent.argTypes))
349+ case ctpe : MethodType
350+ if ctpe.paramInfos.length == superArgs.length + 1 =>
351+ // last argument must be a vararg, otherwise isApplicable would have failed
352+ superArgs :+
353+ repeated(Nil , TypeTree (ctpe.paramInfos.last.argInfos.head, inferred = true ))
354+ case _ =>
355+ superArgs
356+
320357 val superRef =
321- if (cls.is(Trait )) TypeTree (firstParent)
322- else {
323- def isApplicable (ctpe : Type ): Boolean = ctpe match {
324- case ctpe : PolyType =>
325- isApplicable(ctpe.instantiate(firstParent.argTypes))
326- case ctpe : MethodType =>
327- (superArgs corresponds ctpe.paramInfos)(_.tpe <:< _)
328- case _ =>
329- false
330- }
331- val constr = firstParent.decl(nme.CONSTRUCTOR ).suchThat(constr => isApplicable(constr.info))
332- New (firstParent, constr.symbol.asTerm, superArgs)
333- }
358+ if cls.is(Trait ) then TypeTree (firstParent)
359+ else
360+ val constr = firstParent.decl(nme.CONSTRUCTOR ).suchThat(isApplicable)
361+ New (firstParent, constr.symbol.asTerm, adaptedSuperArgs(constr.info))
362+
334363 ClassDefWithParents (cls, constr, superRef :: otherParents.map(TypeTree (_)), body)
335- }
364+ end ClassDef
336365
337366 def ClassDefWithParents (cls : ClassSymbol , constr : DefDef , parents : List [Tree ], body : List [Tree ])(using Context ): TypeDef = {
338367 val selfType =
@@ -359,13 +388,18 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
359388 * @param parents a non-empty list of class types
360389 * @param termForwarders a non-empty list of forwarding definitions specified by their name and the definition they forward to.
361390 * @param typeMembers a possibly-empty list of type members specified by their name and their right hand side.
391+ * @param adaptVarargs if true, allow matching a vararg superclass constructor
392+ * with a missing argument in superArgs, and synthesize an
393+ * empty repeated parameter in the supercall in this case
362394 *
363395 * The class has the same owner as the first function in `termForwarders`.
364396 * Its position is the union of all symbols in `termForwarders`.
365397 */
366- def AnonClass (parents : List [Type ], termForwarders : List [(TermName , TermSymbol )],
367- typeMembers : List [(TypeName , TypeBounds )] = Nil )(using Context ): Block = {
368- AnonClass (termForwarders.head._2.owner, parents, termForwarders.map(_._2.span).reduceLeft(_ union _)) { cls =>
398+ def AnonClass (parents : List [Type ],
399+ termForwarders : List [(TermName , TermSymbol )],
400+ typeMembers : List [(TypeName , TypeBounds )],
401+ adaptVarargs : Boolean )(using Context ): Block = {
402+ AnonClass (termForwarders.head._2.owner, parents, termForwarders.map(_._2.span).reduceLeft(_ union _), adaptVarargs) { cls =>
369403 def forwarder (name : TermName , fn : TermSymbol ) = {
370404 val fwdMeth = fn.copy(cls, name, Synthetic | Method | Final ).entered.asTerm
371405 for overridden <- fwdMeth.allOverriddenSymbols do
@@ -385,6 +419,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
385419 * with the specified owner and position.
386420 */
387421 def AnonClass (owner : Symbol , parents : List [Type ], coord : Coord )(body : ClassSymbol => List [Tree ])(using Context ): Block =
422+ AnonClass (owner, parents, coord, adaptVarargs = false )(body)
423+
424+ private def AnonClass (owner : Symbol , parents : List [Type ], coord : Coord , adaptVarargs : Boolean )(body : ClassSymbol => List [Tree ])(using Context ): Block =
388425 val parents1 =
389426 if (parents.head.classSymbol.is(Trait )) {
390427 val head = parents.head.parents.head
@@ -393,7 +430,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
393430 else parents
394431 val cls = newNormalizedClassSymbol(owner, tpnme.ANON_CLASS , Synthetic | Final , parents1, coord = coord)
395432 val constr = newConstructor(cls, Synthetic , Nil , Nil ).entered
396- val cdef = ClassDef (cls, DefDef (constr), body(cls))
433+ val cdef = ClassDef (cls, DefDef (constr), body(cls), Nil , adaptVarargs )
397434 Block (cdef :: Nil , New (cls.typeRef, Nil ))
398435
399436 def Import (expr : Tree , selectors : List [untpd.ImportSelector ])(using Context ): Import =
0 commit comments