@@ -3,7 +3,7 @@ package dotc
33package typer
44
55import core ._
6- import ast .{Trees , tpd , untpd }
6+ import ast .{Trees , tpd , untpd , desugar }
77import util .Spans ._
88import util .Stats .record
99import util .{SourcePosition , NoSourcePosition , SourceFile }
@@ -864,7 +864,7 @@ trait Applications extends Compatibility {
864864 case funRef : TermRef =>
865865 val app =
866866 if (proto.allArgTypesAreCurrent())
867- new ApplyToTyped (tree, fun1, funRef, proto.unforcedTypedArgs , pt)
867+ new ApplyToTyped (tree, fun1, funRef, proto.typedArgs() , pt)
868868 else
869869 new ApplyToUntyped (tree, fun1, funRef, proto, pt)(
870870 given fun1 .nullableInArgContext(given argCtx (tree)))
@@ -891,7 +891,7 @@ trait Applications extends Compatibility {
891891 }
892892
893893 fun1.tpe match {
894- case err : ErrorType => cpy.Apply (tree)(fun1, proto.unforcedTypedArgs ).withType(err)
894+ case err : ErrorType => cpy.Apply (tree)(fun1, proto.typedArgs() ).withType(err)
895895 case TryDynamicCallType => typedDynamicApply(tree, pt)
896896 case _ =>
897897 if (originalProto.isDropped) fun1
@@ -1635,14 +1635,46 @@ trait Applications extends Compatibility {
16351635 def narrowByTypes (alts : List [TermRef ], argTypes : List [Type ], resultType : Type ): List [TermRef ] =
16361636 alts filter (isApplicableMethodRef(_, argTypes, resultType))
16371637
1638+ /** Normalization steps before checking arguments:
1639+ *
1640+ * { expr } --> expr
1641+ * (x1, ..., xn) => expr --> ((x1, ..., xn)) => expr
1642+ * if n != 1, no alternative has a corresponding formal parameter that
1643+ * is an n-ary function, and at least one alternative has a corresponding
1644+ * formal parameter that is a unary function.
1645+ */
1646+ def normArg (alts : List [TermRef ], arg : untpd.Tree , idx : Int ): untpd.Tree = arg match
1647+ case Block (Nil , expr) => normArg(alts, expr, idx)
1648+ case untpd.Function (args : List [untpd.ValDef ] @ unchecked, body) =>
1649+
1650+ // If ref refers to a method whose parameter at index `idx` is a function type,
1651+ // the arity of that function, otherise -1.
1652+ def paramCount (ref : TermRef ) =
1653+ val formals = ref.widen.firstParamTypes
1654+ if formals.length > idx then
1655+ formals(idx) match
1656+ case defn.FunctionOf (args, _, _, _) => args.length
1657+ case _ => - 1
1658+ else - 1
1659+
1660+ val numArgs = args.length
1661+ if numArgs != 1
1662+ && ! alts.exists(paramCount(_) == numArgs)
1663+ && alts.exists(paramCount(_) == 1 )
1664+ then
1665+ desugar.makeTupledFunction(args, body, isGenericTuple = true )
1666+ // `isGenericTuple = true` is the safe choice here. It means the i'th tuple
1667+ // element is selected with `(i)` instead of `_i`, which gives the same code
1668+ // in the end, but the compilation time and the ascribed type are more involved.
1669+ // It also means that -Ytest-pickler -Xprint-types fails for sources exercising
1670+ // the idiom since after pickling the target is known, so _i is used directly.
1671+ else arg
1672+ case _ => arg
1673+ end normArg
1674+
16381675 val candidates = pt match {
16391676 case pt @ FunProto (args, resultType) =>
16401677 val numArgs = args.length
1641- val normArgs = args.mapConserve {
1642- case Block (Nil , expr) => expr
1643- case x => x
1644- }
1645-
16461678 def sizeFits (alt : TermRef ): Boolean = alt.widen.stripPoly match {
16471679 case tp : MethodType =>
16481680 val ptypes = tp.paramInfos
@@ -1661,9 +1693,10 @@ trait Applications extends Compatibility {
16611693 alts.filter(sizeFits(_))
16621694
16631695 def narrowByShapes (alts : List [TermRef ]): List [TermRef ] =
1664- if (normArgs exists untpd.isFunctionWithUnknownParamType)
1665- if (hasNamedArg(args)) narrowByTrees(alts, args map treeShape, resultType)
1666- else narrowByTypes(alts, normArgs map typeShape, resultType)
1696+ val normArgs = args.mapWithIndexConserve(normArg(alts, _, _))
1697+ if normArgs.exists(untpd.isFunctionWithUnknownParamType) then
1698+ if hasNamedArg(args) then narrowByTrees(alts, normArgs.map(treeShape), resultType)
1699+ else narrowByTypes(alts, normArgs.map(typeShape), resultType)
16671700 else
16681701 alts
16691702
@@ -1681,16 +1714,14 @@ trait Applications extends Compatibility {
16811714
16821715 val alts1 = narrowBySize(alts)
16831716 // ctx.log(i"narrowed by size: ${alts1.map(_.symbol.showDcl)}%, %")
1684- if ( isDetermined(alts1)) alts1
1685- else {
1717+ if isDetermined(alts1) then alts1
1718+ else
16861719 val alts2 = narrowByShapes(alts1)
16871720 // ctx.log(i"narrowed by shape: ${alts2.map(_.symbol.showDcl)}%, %")
1688- if ( isDetermined(alts2)) alts2
1689- else {
1721+ if isDetermined(alts2) then alts2
1722+ else
16901723 pretypeArgs(alts2, pt)
1691- narrowByTrees(alts2, pt.unforcedTypedArgs, resultType)
1692- }
1693- }
1724+ narrowByTrees(alts2, pt.typedArgs(normArg(alts2, _, _)), resultType)
16941725
16951726 case pt @ PolyProto (targs1, pt1) if targs.isEmpty =>
16961727 val alts1 = alts.filter(pt.isMatchedBy(_))
@@ -1749,7 +1780,7 @@ trait Applications extends Compatibility {
17491780 else pt match {
17501781 case pt @ FunProto (_, resType : FunProto ) =>
17511782 // try to narrow further with snd argument list
1752- val advanced = advanceCandidates(pt.unforcedTypedArgs .tpes)
1783+ val advanced = advanceCandidates(pt.typedArgs() .tpes)
17531784 resolveOverloaded(advanced.map(_._1), resType, Nil ) // resolve with candidates where first params are stripped
17541785 .map(advanced.toMap) // map surviving result(s) back to original candidates
17551786 case _ =>
0 commit comments