@@ -1047,31 +1047,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
10471047 * to form the method type.
10481048 * todo: use techniques like for implicits to pick candidates quickly?
10491049 */
1050- def resolveOverloaded (alts : List [TermRef ], pt : Type , targs : List [Type ] = Nil )(implicit ctx : Context ): List [TermRef ] = track(" resolveOverloaded" ) {
1051-
1052- def isDetermined (alts : List [TermRef ]) = alts.isEmpty || alts.tail.isEmpty
1053-
1054- /** The shape of given tree as a type; cannot handle named arguments. */
1055- def typeShape (tree : untpd.Tree ): Type = tree match {
1056- case untpd.Function (args, body) =>
1057- defn.FunctionOf (args map Function .const(defn.AnyType ), typeShape(body))
1058- case _ =>
1059- defn.NothingType
1060- }
1061-
1062- /** The shape of given tree as a type; is more expensive than
1063- * typeShape but can can handle named arguments.
1064- */
1065- def treeShape (tree : untpd.Tree ): Tree = tree match {
1066- case NamedArg (name, arg) =>
1067- val argShape = treeShape(arg)
1068- cpy.NamedArg (tree)(name, argShape).withType(argShape.tpe)
1069- case _ =>
1070- dummyTreeOfType(typeShape(tree))
1071- }
1072-
1073- def narrowByTypes (alts : List [TermRef ], argTypes : List [Type ], resultType : Type ): List [TermRef ] =
1074- alts filter (isApplicable(_, argTypes, resultType))
1050+ def resolveOverloaded (alts : List [TermRef ], pt : Type )(implicit ctx : Context ): List [TermRef ] = track(" resolveOverloaded" ) {
10751051
10761052 /** Is `alt` a method or polytype whose result type after the first value parameter
10771053 * section conforms to the expected type `resultType`? If `resultType`
@@ -1100,23 +1076,63 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
11001076 * probability of pruning the search. result type comparisons are neither cheap nor
11011077 * do they prune much, on average.
11021078 */
1103- def adaptByResult (alts : List [TermRef ], chosen : TermRef ) = {
1104- def nestedCtx = ctx.fresh.setExploreTyperState
1105- pt match {
1106- case pt : FunProto if ! resultConforms(chosen, pt.resultType)(nestedCtx) =>
1107- alts.filter(alt =>
1108- (alt ne chosen) && resultConforms(alt, pt.resultType)(nestedCtx)) match {
1109- case Nil => chosen
1110- case alt2 :: Nil => alt2
1111- case alts2 =>
1112- resolveOverloaded(alts2, pt) match {
1113- case alt2 :: Nil => alt2
1114- case _ => chosen
1115- }
1116- }
1117- case _ => chosen
1118- }
1079+ def adaptByResult (chosen : TermRef ) = {
1080+ def nestedCtx = ctx.fresh.setExploreTyperState
1081+ pt match {
1082+ case pt : FunProto if ! resultConforms(chosen, pt.resultType)(nestedCtx) =>
1083+ alts.filter(alt =>
1084+ (alt ne chosen) && resultConforms(alt, pt.resultType)(nestedCtx)) match {
1085+ case Nil => chosen
1086+ case alt2 :: Nil => alt2
1087+ case alts2 =>
1088+ resolveOverloaded(alts2, pt) match {
1089+ case alt2 :: Nil => alt2
1090+ case _ => chosen
1091+ }
1092+ }
1093+ case _ => chosen
11191094 }
1095+ }
1096+
1097+ var found = resolveOverloaded(alts, pt, Nil )(ctx.retractMode(Mode .ImplicitsEnabled ))
1098+ if (found.isEmpty && ctx.mode.is(Mode .ImplicitsEnabled ))
1099+ found = resolveOverloaded(alts, pt, Nil )
1100+ found match {
1101+ case alt :: Nil => adaptByResult(alt) :: Nil
1102+ case _ => found
1103+ }
1104+ }
1105+
1106+ /** This private version of `resolveOverloaded` does the bulk of the work of
1107+ * overloading resolution, but does not do result adaptation. It might be
1108+ * called twice from the public `resolveOverloaded` method, once with
1109+ * implicits enabled, and once without.
1110+ */
1111+ private def resolveOverloaded (alts : List [TermRef ], pt : Type , targs : List [Type ])(implicit ctx : Context ): List [TermRef ] = track(" resolveOverloaded" ) {
1112+
1113+ def isDetermined (alts : List [TermRef ]) = alts.isEmpty || alts.tail.isEmpty
1114+
1115+ /** The shape of given tree as a type; cannot handle named arguments. */
1116+ def typeShape (tree : untpd.Tree ): Type = tree match {
1117+ case untpd.Function (args, body) =>
1118+ defn.FunctionOf (args map Function .const(defn.AnyType ), typeShape(body))
1119+ case _ =>
1120+ defn.NothingType
1121+ }
1122+
1123+ /** The shape of given tree as a type; is more expensive than
1124+ * typeShape but can can handle named arguments.
1125+ */
1126+ def treeShape (tree : untpd.Tree ): Tree = tree match {
1127+ case NamedArg (name, arg) =>
1128+ val argShape = treeShape(arg)
1129+ cpy.NamedArg (tree)(name, argShape).withType(argShape.tpe)
1130+ case _ =>
1131+ dummyTreeOfType(typeShape(tree))
1132+ }
1133+
1134+ def narrowByTypes (alts : List [TermRef ], argTypes : List [Type ], resultType : Type ): List [TermRef ] =
1135+ alts filter (isApplicable(_, argTypes, resultType))
11201136
11211137 val candidates = pt match {
11221138 case pt @ FunProto (args, resultType, _) =>
@@ -1176,33 +1192,27 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
11761192 }
11771193 }
11781194
1179- case pt @ PolyProto (targs, pt1) =>
1195+ case pt @ PolyProto (targs1, pt1) =>
1196+ assert(targs.isEmpty)
11801197 val alts1 = alts filter pt.isMatchedBy
1181- resolveOverloaded(alts1, pt1, targs )
1198+ resolveOverloaded(alts1, pt1, targs1 )
11821199
11831200 case defn.FunctionOf (args, resultType) =>
11841201 narrowByTypes(alts, args, resultType)
11851202
11861203 case pt =>
11871204 alts filter (normalizedCompatible(_, pt))
11881205 }
1189- narrowMostSpecific(candidates) match {
1190- case Nil => Nil
1191- case alt :: Nil =>
1192- adaptByResult(alts, alt) :: Nil
1193- // why `alts` and not `candidates`? pos/array-overload.scala gives a test case.
1194- // Here, only the Int-apply is a candidate, but it is not compatible with the result
1195- // type. Picking the Byte-apply as the only result-compatible solution then forces
1196- // the arguments (which are constants) to be adapted to Byte. If we had picked
1197- // `candidates` instead, no solution would have been found.
1198- case alts =>
1199- val noDefaults = alts.filter(! _.symbol.hasDefaultParams)
1200- if (noDefaults.length == 1 ) noDefaults // return unique alternative without default parameters if it exists
1201- else {
1202- val deepPt = pt.deepenProto
1203- if (deepPt ne pt) resolveOverloaded(alts, deepPt, targs)
1204- else alts
1205- }
1206+ val found = narrowMostSpecific(candidates)
1207+ if (found.length <= 1 ) found
1208+ else {
1209+ val noDefaults = alts.filter(! _.symbol.hasDefaultParams)
1210+ if (noDefaults.length == 1 ) noDefaults // return unique alternative without default parameters if it exists
1211+ else {
1212+ val deepPt = pt.deepenProto
1213+ if (deepPt ne pt) resolveOverloaded(alts, deepPt, targs)
1214+ else alts
1215+ }
12061216 }
12071217 }
12081218
@@ -1305,11 +1315,3 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
13051315 harmonizeWith(tpes)(identity, (tp, pt) => pt)
13061316}
13071317
1308- /*
1309- def typedApply(app: untpd.Apply, fun: Tree, methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context): Tree = track("typedApply") {
1310- new ApplyToTyped(app, fun, methRef, args, resultType).result
1311- }
1312-
1313- def typedApply(fun: Tree, methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context): Tree =
1314- typedApply(untpd.Apply(untpd.TypedSplice(fun), args), fun, methRef, args, resultType)
1315- */
0 commit comments