@@ -915,7 +915,9 @@ trait Applications extends Compatibility { self: Typer =>
915
915
}}
916
916
917
917
def narrowMostSpecific (alts : List [TermRef ])(implicit ctx : Context ): List [TermRef ] = track(" narrowMostSpecific" ) {
918
- (alts : @ unchecked) match {
918
+ alts match {
919
+ case Nil => alts
920
+ case _ :: Nil => alts
919
921
case alt :: alts1 =>
920
922
def winner (bestSoFar : TermRef , alts : List [TermRef ]): TermRef = alts match {
921
923
case alt :: alts1 =>
@@ -966,6 +968,51 @@ trait Applications extends Compatibility { self: Typer =>
966
968
def narrowByTypes (alts : List [TermRef ], argTypes : List [Type ], resultType : Type ): List [TermRef ] =
967
969
alts filter (isApplicable(_, argTypes, resultType))
968
970
971
+ /** Is `alt` a method or polytype whose result type after the first value parameter
972
+ * section conforms to the expected type `resultType`? If `resultType`
973
+ * is a `IgnoredProto`, pick the underlying type instead.
974
+ */
975
+ def resultConforms (alt : Type , resultType : Type )(implicit ctx : Context ): Boolean = resultType match {
976
+ case IgnoredProto (ignored) => resultConforms(alt, ignored)
977
+ case _ : ValueType =>
978
+ alt.widen match {
979
+ case tp : PolyType => resultConforms(constrained(tp).resultType, resultType)
980
+ case tp : MethodType => constrainResult(tp.resultType, resultType)
981
+ case _ => true
982
+ }
983
+ case _ => true
984
+ }
985
+
986
+ /** If the `chosen` alternative has a result type incompatible with the expected result
987
+ * type `pt`, run overloading resolution again on all alternatives that do match `pt`.
988
+ * If the latter succeeds with a single alternative, return it, otherwise
989
+ * fallback to `chosen`.
990
+ *
991
+ * Note this order of events is done for speed. One might be tempted to
992
+ * preselect alternatives by result type. But is slower, because it discriminates
993
+ * less. The idea is when searching for a best solution, as is the case in overloading
994
+ * resolution, we should first try criteria which are cheap and which have a high
995
+ * probability of pruning the search. result type comparisons are neither cheap nor
996
+ * do they prune much, on average.
997
+ */
998
+ def adaptByResult (alts : List [TermRef ], chosen : TermRef ) = {
999
+ def nestedCtx = ctx.fresh.setExploreTyperState
1000
+ pt match {
1001
+ case pt : FunProto if ! resultConforms(chosen, pt.resultType)(nestedCtx) =>
1002
+ alts.filter(alt =>
1003
+ (alt ne chosen) && resultConforms(alt, pt.resultType)(nestedCtx)) match {
1004
+ case Nil => chosen
1005
+ case alt2 :: Nil => alt2
1006
+ case alts2 =>
1007
+ resolveOverloaded(alts2, pt) match {
1008
+ case alt2 :: Nil => alt2
1009
+ case _ => chosen
1010
+ }
1011
+ }
1012
+ case _ => chosen
1013
+ }
1014
+ }
1015
+
969
1016
val candidates = pt match {
970
1017
case pt @ FunProto (args, resultType, _) =>
971
1018
val numArgs = args.length
@@ -1027,15 +1074,20 @@ trait Applications extends Compatibility { self: Typer =>
1027
1074
case pt =>
1028
1075
alts filter (normalizedCompatible(_, pt))
1029
1076
}
1030
- if (isDetermined(candidates)) candidates
1031
- else narrowMostSpecific(candidates) match {
1032
- case result @ (alt1 :: alt2 :: _) =>
1033
- // overload.println(i"ambiguous $alt1 $alt2")
1077
+ narrowMostSpecific(candidates) match {
1078
+ case Nil => Nil
1079
+ case alt :: Nil =>
1080
+ adaptByResult(alts, alt) :: Nil
1081
+ // why `alts` and not `candidates`? pos/array-overload.scala gives a test case.
1082
+ // Here, only the Int-apply is a candidate, but it is not compatible with the result
1083
+ // type. Picking the Byte-apply as the only result-compatible solution then forces
1084
+ // the arguments (which are constants) to be adapted to Byte. If we had picked
1085
+ // `candidates` instead, no solution would have been found.
1086
+ case alts =>
1087
+ // overload.println(i"ambiguous $alts%, %")
1034
1088
val deepPt = pt.deepenProto
1035
1089
if (deepPt ne pt) resolveOverloaded(alts, deepPt, targs)
1036
- else result
1037
- case result =>
1038
- result
1090
+ else alts
1039
1091
}
1040
1092
}
1041
1093
0 commit comments