-
Notifications
You must be signed in to change notification settings - Fork 3.1k
SI-9178 Don't eta expand to an Function0-like SAM expected type #4822
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
Otherwise, we can end up with a subtle source incompatibility with the pre-SAM regime. Arguably we should phase out eta expansion to Function0 as well, but I'll leave that for another day.
|
That build showed a flaw in my first attempt, I've just pushed an improved fix. The enable-SAM-by-default build is running again on top of 639e52a. |
|
Do I understand correctly that the following code won't compile anymore? Because in I may be misunderstanding it, not very familiar with scalac sources :) |
|
That's right: |
|
If only I knew this several months earlier. Spent a lot of time trying to support eta expansion of SAMs in Intellij IDEA. That makes it simpler. If you are interested, here are tests on SAM for IntelliJ IDEA. Assuming this PR passes the tests, will this fix be backported to Scala 2.11? |
|
Thanks for that work, really great to have that done ahead of the 2.12 release! We hang out over at https://gitter.im/scala/contributors, so feel free to drop by with those sort of questions. |
|
Not sure about 2.11 yet, let's see how this proposal fares in 2.12. |
|
I will, thanks! Hopefully this proposal makes it into both 2.11 and 2.12! |
|
|
I've modified that job to archive JVM crash logs as an build artifact to get a bit more information it if happens again. /rebuild |
|
/rebuild - scaboooou only reads the headlines. |
|
The Should we emit a deprecation in this case? It'd be good to add the example as a test case. LGTM otherwise, but I'll let @adriaanm take a look. |
|
I've added the test case to show that the status quo is preserved. If we have a consensus to deprecate let's do so under the banner of a new PR. My vote is +1 unless we learn something from running the community build with the deprecation warning (ramped up to an error so we see where if/where it is used.) |
|
I'm taking another look at this failure to compile the library with the locker in the followup change, which enables SAM by default: |
|
Looks like that is a general problem with the SAM implementation. In order to support let SAMs participate in overload resolution, This seems pretty heaviweight from a performance perspective, and as the build failure shows, it also treads into cycles. We might be able to easily make this leaner by instead looking at the decls of all the base classes in the hope that we'll find more than one abstract method that would disqualify this as a SAM. Generalizing this, we could expose a variant of |
|
LGTM |
|
cool! @adriaanm wdyt about deprecating the Function0 case (#4822 (comment))? |
SI-9178 Don't eta expand to an Function0-like SAM expected type
|
Agreed with deprecating. @retronym, could you follow up with a PR for that? |
|
Also, SAM needs to be enabled by default? |
|
Is this why, under 2.12, the following code compiles: package object mypackage {
def render() = {}
val handler: Runnable = () => render
}yet this code does not? package object mypackage {
def render() = {}
val handler: Runnable = render _
}
Under 2.11, with the addition of an implicit conversion either form was valid. Originally noticed in the context of Scala.js (scala-js/scala-js#2656) |
|
Yes, you have to write the function literal in full now in the zero-arg
|
|
@adriaanm I have finally muddled my way through the spec. I will admit it is a little over my head, but this stackoverflow post on method type vs function type helped a lot. From what I read, it seems like the case I described above would be a bug. package object mypackage {
def render() = {}
val handler: Function0[Any] = render _
val handler2 = render _
val handler3: Runnable = handler2
val handler4: Runnable = render _
implicit def runnable(f: () => Unit): Runnable =
new Runnable() { def run() = f() }
}of contention is how In the above code, only the line of The spec says:
Since function application is listed first, it would seem that if function application was appropriate for What I expect is
Based on the this issue, I suppose it could be argued that because the method value explicitly triggers eta-expansion and Runnable is Continuing under the assumption that
It would then advance onto View Application, for which there is a suitable implicit defined. My interpretation that the implicit SAM conversion would not apply would seem consistent with the release note,
|
|
Thank you for digging in here -- this is tricky stuff. I think you're right that something's iffy here. Must indeed be something to do with it being 0-ary. Both these examples compile: Could you file a ticket over at scala/scala-dev? I think the right behavior is that the nullary case should behave just like the unary case in Ok1. (I.e., sam conversion applies) |
Otherwise, we can end up with a subtle source incompatibility with
the pre-SAM regime. Arguably we should phase out eta expansion to
Function0 as well, but I'll leave that for another day.
Review by @adriaanm