@@ -1047,31 +1047,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
1047
1047
* to form the method type.
1048
1048
* todo: use techniques like for implicits to pick candidates quickly?
1049
1049
*/
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" ) {
1075
1051
1076
1052
/** Is `alt` a method or polytype whose result type after the first value parameter
1077
1053
* section conforms to the expected type `resultType`? If `resultType`
@@ -1100,23 +1076,63 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
1100
1076
* probability of pruning the search. result type comparisons are neither cheap nor
1101
1077
* do they prune much, on average.
1102
1078
*/
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
1119
1094
}
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))
1120
1136
1121
1137
val candidates = pt match {
1122
1138
case pt @ FunProto (args, resultType, _) =>
@@ -1176,33 +1192,27 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
1176
1192
}
1177
1193
}
1178
1194
1179
- case pt @ PolyProto (targs, pt1) =>
1195
+ case pt @ PolyProto (targs1, pt1) =>
1196
+ assert(targs.isEmpty)
1180
1197
val alts1 = alts filter pt.isMatchedBy
1181
- resolveOverloaded(alts1, pt1, targs )
1198
+ resolveOverloaded(alts1, pt1, targs1 )
1182
1199
1183
1200
case defn.FunctionOf (args, resultType) =>
1184
1201
narrowByTypes(alts, args, resultType)
1185
1202
1186
1203
case pt =>
1187
1204
alts filter (normalizedCompatible(_, pt))
1188
1205
}
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
+ }
1206
1216
}
1207
1217
}
1208
1218
@@ -1305,11 +1315,3 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
1305
1315
harmonizeWith(tpes)(identity, (tp, pt) => pt)
1306
1316
}
1307
1317
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