@@ -305,24 +305,53 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
305305 def TypeDef (sym : TypeSymbol )(using Context ): TypeDef =
306306 ta.assignType(untpd.TypeDef (sym.name, TypeTree (sym.info)), sym)
307307
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 =
309319 val firstParent :: otherParents = cls.info.parents: @ unchecked
320+
321+ def isApplicable (constr : Symbol ): Boolean =
322+ def recur (ctpe : Type ): Boolean = ctpe match
323+ case ctpe : PolyType =>
324+ recur(ctpe.instantiate(firstParent.argTypes))
325+ case ctpe : MethodType =>
326+ var paramInfos = ctpe.paramInfos
327+ if adaptVarargs && paramInfos.length == superArgs.length + 1
328+ && atPhaseNoLater(Phases .elimRepeatedPhase)(constr.info.isVarArgsMethod)
329+ then // accept missing argument for varargs parameter
330+ paramInfos = paramInfos.init
331+ superArgs.corresponds(paramInfos)(_.tpe <:< _)
332+ case _ =>
333+ false
334+ recur(constr.info)
335+
336+ def adaptedSuperArgs (ctpe : Type ): List [Tree ] = ctpe match
337+ case ctpe : PolyType =>
338+ adaptedSuperArgs(ctpe.instantiate(firstParent.argTypes))
339+ case ctpe : MethodType
340+ if ctpe.paramInfos.length == superArgs.length + 1 =>
341+ // last argument must be a vararg, otherwise isApplicable would have failed
342+ superArgs :+
343+ repeated(Nil , TypeTree (ctpe.paramInfos.last.argInfos.head, inferred = true ))
344+ case _ =>
345+ superArgs
346+
310347 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- }
348+ if cls.is(Trait ) then TypeTree (firstParent)
349+ else
350+ val constr = firstParent.decl(nme.CONSTRUCTOR ).suchThat(isApplicable)
351+ New (firstParent, constr.symbol.asTerm, adaptedSuperArgs(constr.info))
352+
324353 ClassDefWithParents (cls, constr, superRef :: otherParents.map(TypeTree (_)), body)
325- }
354+ end ClassDef
326355
327356 def ClassDefWithParents (cls : ClassSymbol , constr : DefDef , parents : List [Tree ], body : List [Tree ])(using Context ): TypeDef = {
328357 val selfType =
@@ -349,13 +378,18 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
349378 * @param parents a non-empty list of class types
350379 * @param termForwarders a non-empty list of forwarding definitions specified by their name and the definition they forward to.
351380 * @param typeMembers a possibly-empty list of type members specified by their name and their right hand side.
381+ * @param adaptVarargs if true, allow matching a vararg superclass constructor
382+ * with a missing argument in superArgs, and synthesize an
383+ * empty repeated parameter in the supercall in this case
352384 *
353385 * The class has the same owner as the first function in `termForwarders`.
354386 * Its position is the union of all symbols in `termForwarders`.
355387 */
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 =>
388+ def AnonClass (parents : List [Type ],
389+ termForwarders : List [(TermName , TermSymbol )],
390+ typeMembers : List [(TypeName , TypeBounds )],
391+ adaptVarargs : Boolean )(using Context ): Block = {
392+ AnonClass (termForwarders.head._2.owner, parents, termForwarders.map(_._2.span).reduceLeft(_ union _), adaptVarargs) { cls =>
359393 def forwarder (name : TermName , fn : TermSymbol ) = {
360394 val fwdMeth = fn.copy(cls, name, Synthetic | Method | Final ).entered.asTerm
361395 for overridden <- fwdMeth.allOverriddenSymbols do
@@ -375,6 +409,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
375409 * with the specified owner and position.
376410 */
377411 def AnonClass (owner : Symbol , parents : List [Type ], coord : Coord )(body : ClassSymbol => List [Tree ])(using Context ): Block =
412+ AnonClass (owner, parents, coord, adaptVarargs = false )(body)
413+
414+ private def AnonClass (owner : Symbol , parents : List [Type ], coord : Coord , adaptVarargs : Boolean )(body : ClassSymbol => List [Tree ])(using Context ): Block =
378415 val parents1 =
379416 if (parents.head.classSymbol.is(Trait )) {
380417 val head = parents.head.parents.head
@@ -383,7 +420,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
383420 else parents
384421 val cls = newNormalizedClassSymbol(owner, tpnme.ANON_CLASS , Synthetic | Final , parents1, coord = coord)
385422 val constr = newConstructor(cls, Synthetic , Nil , Nil ).entered
386- val cdef = ClassDef (cls, DefDef (constr), body(cls))
423+ val cdef = ClassDef (cls, DefDef (constr), body(cls), Nil , adaptVarargs )
387424 Block (cdef :: Nil , New (cls.typeRef, Nil ))
388425
389426 def Import (expr : Tree , selectors : List [untpd.ImportSelector ])(using Context ): Import =
0 commit comments