@@ -24,6 +24,7 @@ import Inferencing.*
2424import reporting .*
2525import Nullables .* , NullOpsDecorator .*
2626import config .{Feature , MigrationVersion , SourceVersion }
27+ import util .Property
2728
2829import collection .mutable
2930import config .Printers .{overload , typr , unapp }
@@ -42,6 +43,17 @@ import dotty.tools.dotc.inlines.Inlines
4243object Applications {
4344 import tpd .*
4445
46+ /** Attachment key for SeqLiterals containing spreads. Eliminated at PostTyper */
47+ val HasSpreads = new Property .StickyKey [Unit ]
48+
49+ /** An extractor for spreads in sequence literals */
50+ object spread :
51+ def apply (arg : Tree , elemtpt : Tree )(using Context ) =
52+ ref(defn.spreadMethod).appliedToTypeTree(elemtpt).appliedTo(arg)
53+ def unapply (arg : Apply )(using Context ): Option [Tree ] = arg match
54+ case Apply (fn, x :: Nil ) if fn.symbol == defn.spreadMethod => Some (x)
55+ case _ => None
56+
4557 def extractorMember (tp : Type , name : Name )(using Context ): SingleDenotation =
4658 tp.member(name).suchThat(sym => sym.info.isParameterless && sym.info.widenExpr.isValueType)
4759
@@ -797,14 +809,19 @@ trait Applications extends Compatibility {
797809 addTyped(arg)
798810 case _ =>
799811 val elemFormal = formal.widenExpr.argTypesLo.head
800- val typedArgs =
801- harmonic(harmonizeArgs, elemFormal) {
802- args.map { arg =>
812+ if Feature .enabled(Feature .multiSpreads)
813+ && ! ctx.isAfterTyper && args.exists(isVarArg)
814+ then
815+ args.foreach: arg =>
816+ if isVarArg(arg)
817+ then addArg(typedArg(arg, formal), formal)
818+ else addArg(typedArg(arg, elemFormal), elemFormal)
819+ else
820+ val typedArgs = harmonic(harmonizeArgs, elemFormal):
821+ args.map: arg =>
803822 checkNoVarArg(arg)
804823 typedArg(arg, elemFormal)
805- }
806- }
807- typedArgs.foreach(addArg(_, elemFormal))
824+ typedArgs.foreach(addArg(_, elemFormal))
808825 makeVarArg(args.length, elemFormal)
809826 }
810827 else args match {
@@ -944,12 +961,18 @@ trait Applications extends Compatibility {
944961 typedArgBuf += typedArg
945962 ok = ok & ! typedArg.tpe.isError
946963
947- def makeVarArg (n : Int , elemFormal : Type ): Unit = {
948- val args = typedArgBuf.takeRight(n).toList
964+ def makeVarArg (n : Int , elemFormal : Type ): Unit =
965+ var args = typedArgBuf.takeRight(n).toList
949966 typedArgBuf.dropRightInPlace(n)
950- val elemtpt = TypeTree (elemFormal.normalizedTupleType, inferred = true )
951- typedArgBuf += seqToRepeated(SeqLiteral (args, elemtpt))
952- }
967+ val elemTpe = elemFormal.normalizedTupleType
968+ val elemtpt = TypeTree (elemTpe, inferred = true )
969+ def wrapSpread (arg : Tree ): Tree = arg match
970+ case Typed (argExpr, tpt) if tpt.tpe.isRepeatedParam => spread(argExpr, elemtpt)
971+ case _ => arg
972+ val args1 = args.mapConserve(wrapSpread)
973+ val seqLit = SeqLiteral (args1, elemtpt)
974+ if args1 ne args then seqLit.putAttachment(HasSpreads , ())
975+ typedArgBuf += seqToRepeated(seqLit)
953976
954977 def harmonizeArgs (args : List [TypedArg ]): List [Tree ] =
955978 // harmonize args only if resType depends on parameter types
0 commit comments