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