scala/scala — pull request #585 by som-snytt (2012-05-20 03:51:35+00:00)
Title: SI-3761: Overload resolution fails on by-name parameter

Preamble: passes ant test and ant nightly. Build time is not slower. Tie-break by cbn is behind a -Yoption.

Footnote: I tried retaining by-name during type inference, but that breaks a bound (in json.Parser, "null" ^^^ null becomes Parser[Nothing] instead of Parser[Null]. I don't see to the bottom there. Continuing education.

When isAsSpecific checks if method m applies to args of types of
formal params of m1, a by-name parameter was converted to its
underlying result type for the params (of m) but not the args (of m1).
This had the useful effect of making m(A) more specific than m(=>A),
but also made m(=>A) and m(=>A, B*) ambiguous. To handle this edge
case, the isCompatible test for A and =>A is made explicit, and
by-name params are no longer converted.

An option -Yresolve-by-name is provided for the purpose of
favoring m(=>A) over m(A) when applied to (=>A). This only happens
for "pass-by-name", when f(x: =>A) invokes g(x). Because overload
resolution does not normally consider the call site, this optional
behavior is not specified. (An analogous case under discussion,
which is more specified: f(x: A) and f(y: B, C*) where B <: A,
for f(b) chooses the fixed-arity method, even though f(B) is more
specific than f(A); that is, the number of actual arguments is not
an input to overload resolution.)

The mechanism for resolve-by-name is to convert cbn params to the
underlying type, which results in ties between m(A) and m(=>A),
and then pick the method which exactly matches the call site with
respect to by-namedness.

The specified workaround for selecting overloaded f(=>A) is to
put the definition in an interface (where it is not overloaded).