Skip to content

Commit 94e5d76

Browse files
committed
Merge pull request scala#595 from som-snytt/ticket/3761-overload-byname-only
SI-3761: Overload resolution fails on by-name parameter
2 parents 0f198a6 + 8de2caa commit 94e5d76

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

src/compiler/scala/tools/nsc/typechecker/Infer.scala

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,21 @@ trait Infer {
305305
}
306306

307307

308-
def isCompatible(tp: Type, pt: Type): Boolean = {
308+
/** "Compatible" means conforming after conversions.
309+
* "Raising to a thunk" is not implicit; therefore, for purposes of applicability and
310+
* specificity, an arg type `A` is considered compatible with cbn formal parameter type `=>A`.
311+
* For this behavior, the type `pt` must have cbn params preserved; for instance, `formalTypes(removeByName = false)`.
312+
*
313+
* `isAsSpecific` no longer prefers A by testing applicability to A for both m(A) and m(=>A)
314+
* since that induces a tie between m(=>A) and m(=>A,B*) [SI-3761]
315+
*/
316+
private def isCompatible(tp: Type, pt: Type): Boolean = {
317+
def isCompatibleByName(tp: Type, pt: Type): Boolean = pt match {
318+
case TypeRef(_, ByNameParamClass, List(res)) if !isByNameParamType(tp) => isCompatible(tp, res)
319+
case _ => false
320+
}
309321
val tp1 = normalize(tp)
310-
(tp1 weak_<:< pt) || isCoercible(tp1, pt)
322+
(tp1 weak_<:< pt) || isCoercible(tp1, pt) || isCompatibleByName(tp, pt)
311323
}
312324
def isCompatibleArgs(tps: List[Type], pts: List[Type]) =
313325
(tps corresponds pts)(isCompatible)
@@ -662,7 +674,7 @@ trait Infer {
662674
case ExistentialType(tparams, qtpe) =>
663675
isApplicable(undetparams, qtpe, argtpes0, pt)
664676
case MethodType(params, _) =>
665-
val formals = formalTypes(params map { _.tpe }, argtpes0.length)
677+
val formals = formalTypes(params map { _.tpe }, argtpes0.length, removeByName = false)
666678

667679
def tryTupleApply: Boolean = {
668680
// if 1 formal, 1 argtpe (a tuple), otherwise unmodified argtpes0
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
hello!
2+
hello working world
3+
goodnight!
4+
goodnight moon, nobody, noises everywhere
5+
0
6+
1
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
class OverTheTop {
3+
def info0(m: String) = m + "!"
4+
def info0(m: String, args: Any*) = m +" "+ args.mkString(" ")
5+
6+
// as reported
7+
def info1(m: =>String) = m + "!"
8+
def info1(m: =>String, args: Any*) = m +" "+ args.mkString(", ")
9+
10+
// @lrytz
11+
def m[A](x: => Int) = 0; def m[A](x: => Int, xs: Int*) = 1
12+
}
13+
object Test {
14+
def main(args: Array[String]) {
15+
val top = new OverTheTop
16+
println(top.info0("hello"))
17+
println(top.info0("hello","working","world"))
18+
println(top.info1("goodnight"))
19+
println(top.info1("goodnight", "moon", "nobody", "noises everywhere"))
20+
println(top.m(17))
21+
println(top.m(17,19))
22+
}
23+
}

0 commit comments

Comments
 (0)