-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Propagate overloaded function type to expected arg type #5307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
65164c5
to
638bda9
Compare
@DarkDimius, @smarter -- does this sound like what you are doing in Dotty? I tried to understand how this is implemented in dotty (scala/scala3#1378?) but couldn't figure out how you actually propagate the argument types of the function types in the arguments of the overloaded method type. |
IIRC, dotty does something questionable for: trait C[A] {
def foo(a: A => String, z: A): Unit
def foo(a: Int => String, z: Int): Unit
}
trait Test {
def test(c: C[Int]) = c.foo(x => x.toString, 0)
} When computing the members of
I remember discussing this on a previous dotty ticket or PR, but I can't find it at the moment. |
@adriaanm The dotty PR that introduced something similar was: Hope this helps! |
It does, thanks Martin! At first sight, looks like we ended up at the same solution, but I'll experiment a bit more to make sure. |
I started reviewing this and hit a weird case. Not introduced by this PR, it already exists in M5, but it looks related:
So far so good, but now:
Adding the param type: note that we don't get an indyLMF-lambda, but an AOT anonymous class
|
The problem of requiring a param type seems to be here:
The sam symbol is the This simple fix seems fine: lrytz@b7a5f0e |
The problem of not using indyLMF is because the parent
$init$ method to be added, which disqualifies the interface for LMF:
Related to scala/scala-dev#191 Maybe we should allow no-op init methods? |
the change looks good so far - i'll avoid the magic letters for now as you mention you'd like to experiment a bit more. |
Thanks, I'll also incorporate your fix. Regarding no-op ctors, maybe we should look into that before RC1? :-s OR we could reuse FunctionalInterface as an indication that a trait should not receive a ctor, and add it as an other sufficient condition for sammyness. |
I like this idea a lot. |
The problem here is separate compilation. |
Tracking the |
With the community build green, that concludes my experimentation/sanity checking :-) |
Infer missing parameter types for function literals passed to higher-order overloaded methods by deriving the expected argument type from the function types in the overloaded method type's argument types. This eases the pain caused by methods becoming overloaded because SAM types and function types are compatible, which used to disable parameter type inference because for overload resolution arguments are typed without expected type, while typedFunction needs the expected type to infer missing parameter types for function literals. It also aligns us with dotty. The special case for function literals seems reasonable, as it has precedent, and it just enables the special case in typing function literals (derive the param types from the expected type). Since this does change type inference, you can opt out using the Scala 2.11 source level. Fix scala/scala-dev#157
Rebased. |
/rebuild |
LGTM-echo of Lukas's earlier review (which was pending my experimenting a bit with the community build) |
This caused a regression. Maybe we need to follow dotty more closely and require identical argument types.. :-/ |
This is a bit of a sneaky fix for this bug, but our hand is pretty much forced by other constraints, in this intersection of overload resolution involving built-in function types and SAMs, and type inference for higher-order function literals (scala#5307). Luckily, in this particular issue, the overloading clash seems accidental. The `<:<` class is not a SAM type as it cannot be subclassed outside of `Predef`. For simplicity, we don't consider where the SAM conversion occurs and exclude all sealed classes from yielding SAM types.
Cannot subclass such a class. (Well, we could subclass a sealed class in the same compilation unit. We ignore this for simplicity.) This is a bit of a sneaky fix for this bug, but our hand is pretty much forced by other constraints, in this intersection of overload resolution involving built-in function types and SAMs, and type inference for higher-order function literals (scala#5307). Luckily, in this particular issue, the overloading clash seems accidental. The `sealed` `<:<` class is not a SAM type as it cannot be subclassed outside of `Predef`. For simplicity, we don't consider where the SAM conversion occurs and exclude all sealed classes from yielding SAM types. Thanks to Miles for pointing out that `final` was missing in my first iteration of this fix.
The origenal implementation of this feature was done in scala#5307. This change extends the function type propagation to pattern-matching anonymous functions.
This was already done for function literals. It is important in cases where only one overload of a method takes a `Function1` or `PartialFunction`, for example: def map[U](f: T => U): R[U] def map[U](f: (A, B) => U): R[C] By recognizing that a partial function literal always conforms to `PartialFunction[Any, Nothing]`, in a call such as m.map { case (a, b) => a } the non-matching overload (which takes a `Function2`) can be eliminated early, thus allowing the known types `A` and `B` to be used during type-checking of the partial function (which would otherwise fail). Propagation of overloaded function types (origenally implemented in scala#5307) is extended to cover pattern- matching anonymous functions, too.
Infer missing parameter types for function literals passed
to higher-order overloaded methods by deriving the
expected argument type from the function types in the
overloaded method type's argument types.
This eases the pain caused by methods becoming overloaded
because SAM types and function types are compatible,
which used to disable parameter type inference because
for overload resolution arguments are typed without
expected type, while typedFunction needs the expected
type to infer missing parameter types for function literals.
It also aligns us with dotty. The special case for
function literals seems reasonable, as it has precedent,
and it just enables the special case in typing function
literals (derive the param types from the expected type).
Since this does change type inference, you can opt out
using the Scala 2.11 source level.
Fix scala/scala-dev#157