@@ -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,6 +1635,43 @@ 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
@@ -1656,42 +1693,10 @@ trait Applications extends Compatibility {
16561693 alts.filter(sizeFits(_))
16571694
16581695 def narrowByShapes (alts : List [TermRef ]): List [TermRef ] =
1659-
1660- /** Normalization steps before shape-checking arguments:
1661- *
1662- * { expr } --> expr
1663- * (x1, ..., xn) => expr --> ((x1, ..., xn)) => expr
1664- * if n > 1, no alternative has a corresponding formal parameter that
1665- * is an n-ary function, and at least one alternative has a corresponding
1666- * formal parameter that is a unary function.
1667- */
1668- def normArg (arg : untpd.Tree , idx : Int ): untpd.Tree = arg match
1669- case Block (Nil , expr) => normArg(expr, idx)
1670- case untpd.Function (args, body) =>
1671-
1672- // If ref refers to a method whose parameter at index `idx` is a function type,
1673- // the arity of that function, otherise 0.
1674- def paramCount (ref : TermRef ) =
1675- val formals = ref.widen.firstParamTypes
1676- if formals.length > idx then
1677- formals(idx) match
1678- case defn.FunctionOf (args, _, _, _) => args.length
1679- case _ => 0
1680- else 0
1681-
1682- val numArgs = args.length
1683- if numArgs > 1
1684- && ! alts.exists(paramCount(_) == numArgs)
1685- && alts.exists(paramCount(_) == 1 )
1686- then untpd.Function (untpd.Tuple (args) :: Nil , body)
1687- else arg
1688- case _ => arg
1689- end normArg
1690-
1691- val normArgs = args.mapWithIndexConserve(normArg)
1692- if (normArgs exists untpd.isFunctionWithUnknownParamType)
1693- if (hasNamedArg(args)) narrowByTrees(alts, args map treeShape, resultType)
1694- 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)
16951700 else
16961701 alts
16971702
@@ -1709,16 +1714,14 @@ trait Applications extends Compatibility {
17091714
17101715 val alts1 = narrowBySize(alts)
17111716 // ctx.log(i"narrowed by size: ${alts1.map(_.symbol.showDcl)}%, %")
1712- if ( isDetermined(alts1)) alts1
1713- else {
1717+ if isDetermined(alts1) then alts1
1718+ else
17141719 val alts2 = narrowByShapes(alts1)
17151720 // ctx.log(i"narrowed by shape: ${alts2.map(_.symbol.showDcl)}%, %")
1716- if ( isDetermined(alts2)) alts2
1717- else {
1721+ if isDetermined(alts2) then alts2
1722+ else
17181723 pretypeArgs(alts2, pt)
1719- narrowByTrees(alts2, pt.unforcedTypedArgs, resultType)
1720- }
1721- }
1724+ narrowByTrees(alts2, pt.typedArgs(normArg(alts2, _, _)), resultType)
17221725
17231726 case pt @ PolyProto (targs1, pt1) if targs.isEmpty =>
17241727 val alts1 = alts.filter(pt.isMatchedBy(_))
@@ -1777,7 +1780,7 @@ trait Applications extends Compatibility {
17771780 else pt match {
17781781 case pt @ FunProto (_, resType : FunProto ) =>
17791782 // try to narrow further with snd argument list
1780- val advanced = advanceCandidates(pt.unforcedTypedArgs .tpes)
1783+ val advanced = advanceCandidates(pt.typedArgs() .tpes)
17811784 resolveOverloaded(advanced.map(_._1), resType, Nil ) // resolve with candidates where first params are stripped
17821785 .map(advanced.toMap) // map surviving result(s) back to original candidates
17831786 case _ =>
0 commit comments