@@ -1039,31 +1039,7 @@ trait Applications extends Compatibility { self: Typer =>
1039
1039
* to form the method type.
1040
1040
* todo: use techniques like for implicits to pick candidates quickly?
1041
1041
*/
1042
- def resolveOverloaded (alts : List [TermRef ], pt : Type , targs : List [Type ] = Nil )(implicit ctx : Context ): List [TermRef ] = track(" resolveOverloaded" ) {
1043
-
1044
- def isDetermined (alts : List [TermRef ]) = alts.isEmpty || alts.tail.isEmpty
1045
-
1046
- /** The shape of given tree as a type; cannot handle named arguments. */
1047
- def typeShape (tree : untpd.Tree ): Type = tree match {
1048
- case untpd.Function (args, body) =>
1049
- defn.FunctionOf (args map Function .const(defn.AnyType ), typeShape(body))
1050
- case _ =>
1051
- defn.NothingType
1052
- }
1053
-
1054
- /** The shape of given tree as a type; is more expensive than
1055
- * typeShape but can can handle named arguments.
1056
- */
1057
- def treeShape (tree : untpd.Tree ): Tree = tree match {
1058
- case NamedArg (name, arg) =>
1059
- val argShape = treeShape(arg)
1060
- cpy.NamedArg (tree)(name, argShape).withType(argShape.tpe)
1061
- case _ =>
1062
- dummyTreeOfType(typeShape(tree))
1063
- }
1064
-
1065
- def narrowByTypes (alts : List [TermRef ], argTypes : List [Type ], resultType : Type ): List [TermRef ] =
1066
- alts filter (isApplicable(_, argTypes, resultType))
1042
+ def resolveOverloaded (alts : List [TermRef ], pt : Type )(implicit ctx : Context ): List [TermRef ] = track(" resolveOverloaded" ) {
1067
1043
1068
1044
/** Is `alt` a method or polytype whose result type after the first value parameter
1069
1045
* section conforms to the expected type `resultType`? If `resultType`
@@ -1092,23 +1068,63 @@ trait Applications extends Compatibility { self: Typer =>
1092
1068
* probability of pruning the search. result type comparisons are neither cheap nor
1093
1069
* do they prune much, on average.
1094
1070
*/
1095
- def adaptByResult (alts : List [TermRef ], chosen : TermRef ) = {
1096
- def nestedCtx = ctx.fresh.setExploreTyperState
1097
- pt match {
1098
- case pt : FunProto if ! resultConforms(chosen, pt.resultType)(nestedCtx) =>
1099
- alts.filter(alt =>
1100
- (alt ne chosen) && resultConforms(alt, pt.resultType)(nestedCtx)) match {
1101
- case Nil => chosen
1102
- case alt2 :: Nil => alt2
1103
- case alts2 =>
1104
- resolveOverloaded(alts2, pt) match {
1105
- case alt2 :: Nil => alt2
1106
- case _ => chosen
1107
- }
1108
- }
1109
- case _ => chosen
1110
- }
1071
+ def adaptByResult (chosen : TermRef ) = {
1072
+ def nestedCtx = ctx.fresh.setExploreTyperState
1073
+ pt match {
1074
+ case pt : FunProto if ! resultConforms(chosen, pt.resultType)(nestedCtx) =>
1075
+ alts.filter(alt =>
1076
+ (alt ne chosen) && resultConforms(alt, pt.resultType)(nestedCtx)) match {
1077
+ case Nil => chosen
1078
+ case alt2 :: Nil => alt2
1079
+ case alts2 =>
1080
+ resolveOverloaded(alts2, pt) match {
1081
+ case alt2 :: Nil => alt2
1082
+ case _ => chosen
1083
+ }
1084
+ }
1085
+ case _ => chosen
1111
1086
}
1087
+ }
1088
+
1089
+ var found = resolveOverloaded(alts, pt, Nil )(ctx.retractMode(Mode .ImplicitsEnabled ))
1090
+ if (found.isEmpty && ctx.mode.is(Mode .ImplicitsEnabled ))
1091
+ found = resolveOverloaded(alts, pt, Nil )
1092
+ found match {
1093
+ case alt :: Nil => adaptByResult(alt) :: Nil
1094
+ case _ => found
1095
+ }
1096
+ }
1097
+
1098
+ /** This private version of `resolveOverloaded` does the bulk of the work of
1099
+ * overloading resolution, but does not do result adaptation. It might be
1100
+ * called twice from the public `resolveOverloaded` method, once with
1101
+ * implicits enabled, and once without.
1102
+ */
1103
+ private def resolveOverloaded (alts : List [TermRef ], pt : Type , targs : List [Type ])(implicit ctx : Context ): List [TermRef ] = track(" resolveOverloaded" ) {
1104
+
1105
+ def isDetermined (alts : List [TermRef ]) = alts.isEmpty || alts.tail.isEmpty
1106
+
1107
+ /** The shape of given tree as a type; cannot handle named arguments. */
1108
+ def typeShape (tree : untpd.Tree ): Type = tree match {
1109
+ case untpd.Function (args, body) =>
1110
+ defn.FunctionOf (args map Function .const(defn.AnyType ), typeShape(body))
1111
+ case _ =>
1112
+ defn.NothingType
1113
+ }
1114
+
1115
+ /** The shape of given tree as a type; is more expensive than
1116
+ * typeShape but can can handle named arguments.
1117
+ */
1118
+ def treeShape (tree : untpd.Tree ): Tree = tree match {
1119
+ case NamedArg (name, arg) =>
1120
+ val argShape = treeShape(arg)
1121
+ cpy.NamedArg (tree)(name, argShape).withType(argShape.tpe)
1122
+ case _ =>
1123
+ dummyTreeOfType(typeShape(tree))
1124
+ }
1125
+
1126
+ def narrowByTypes (alts : List [TermRef ], argTypes : List [Type ], resultType : Type ): List [TermRef ] =
1127
+ alts filter (isApplicable(_, argTypes, resultType))
1112
1128
1113
1129
val candidates = pt match {
1114
1130
case pt @ FunProto (args, resultType, _) =>
@@ -1168,33 +1184,27 @@ trait Applications extends Compatibility { self: Typer =>
1168
1184
}
1169
1185
}
1170
1186
1171
- case pt @ PolyProto (targs, pt1) =>
1187
+ case pt @ PolyProto (targs1, pt1) =>
1188
+ assert(targs.isEmpty)
1172
1189
val alts1 = alts filter pt.isMatchedBy
1173
- resolveOverloaded(alts1, pt1, targs )
1190
+ resolveOverloaded(alts1, pt1, targs1 )
1174
1191
1175
1192
case defn.FunctionOf (args, resultType) =>
1176
1193
narrowByTypes(alts, args, resultType)
1177
1194
1178
1195
case pt =>
1179
1196
alts filter (normalizedCompatible(_, pt))
1180
1197
}
1181
- narrowMostSpecific(candidates) match {
1182
- case Nil => Nil
1183
- case alt :: Nil =>
1184
- adaptByResult(alts, alt) :: Nil
1185
- // why `alts` and not `candidates`? pos/array-overload.scala gives a test case.
1186
- // Here, only the Int-apply is a candidate, but it is not compatible with the result
1187
- // type. Picking the Byte-apply as the only result-compatible solution then forces
1188
- // the arguments (which are constants) to be adapted to Byte. If we had picked
1189
- // `candidates` instead, no solution would have been found.
1190
- case alts =>
1191
- val noDefaults = alts.filter(! _.symbol.hasDefaultParams)
1192
- if (noDefaults.length == 1 ) noDefaults // return unique alternative without default parameters if it exists
1193
- else {
1194
- val deepPt = pt.deepenProto
1195
- if (deepPt ne pt) resolveOverloaded(alts, deepPt, targs)
1196
- else alts
1197
- }
1198
+ val found = narrowMostSpecific(candidates)
1199
+ if (found.length <= 1 ) found
1200
+ else {
1201
+ val noDefaults = alts.filter(! _.symbol.hasDefaultParams)
1202
+ if (noDefaults.length == 1 ) noDefaults // return unique alternative without default parameters if it exists
1203
+ else {
1204
+ val deepPt = pt.deepenProto
1205
+ if (deepPt ne pt) resolveOverloaded(alts, deepPt, targs)
1206
+ else alts
1207
+ }
1198
1208
}
1199
1209
}
1200
1210
@@ -1297,11 +1307,3 @@ trait Applications extends Compatibility { self: Typer =>
1297
1307
harmonizeWith(tpes)(identity, (tp, pt) => pt)
1298
1308
}
1299
1309
1300
- /*
1301
- def typedApply(app: untpd.Apply, fun: Tree, methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context): Tree = track("typedApply") {
1302
- new ApplyToTyped(app, fun, methRef, args, resultType).result
1303
- }
1304
-
1305
- def typedApply(fun: Tree, methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context): Tree =
1306
- typedApply(untpd.Apply(untpd.TypedSplice(fun), args), fun, methRef, args, resultType)
1307
- */
0 commit comments