-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Take expected result type into account for overloading resolution #665
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
Take expected result type into account for overloading resolution #665
Conversation
3eda187
to
7f2c2b9
Compare
There's a download failure for jline 2.12.jar. What to do? |
/rebuild |
@@ -1241,7 +1241,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit | |||
def expectedStr = err.expectedTypeStr(pt) | |||
resolveOverloaded(alts, pt) match { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder whether resolveOverloaded
could do adaptByResult
's work from the start? What's the rationale for doing this afterwards?
@adriaanm It would be much slower. I tried that first and it looked like at least 4 times blow-up in compilation times.I was surprised at that drastic result, and don't really have an explanation for the magnitude of it. But in principle it makes sense: When doing overloading resolution, we want to prune the search space as quickly as possible. Results of overloaded methods tend to be similar, so checking them first does not prune much. Better to concentrate on the arguments first. |
Ok, would be good to include this as a comment to avoid someone slowing down the compiler if they happened to implement what I was wondering about :-) |
One last concern: are there other calls to |
What alternative of
This comes from the the way that |
See also https://issues.scala-lang.org/browse/SI-8230, in which I've extract a standalone test case to mimic the overloads and associated implicit conversions of
I traced out the type inference here: scala/scala@2.11.x...retronym:ticket/8230 |
Overall, I think any intentional divergence between the Scala and dotty type checker around overloading/inference needs to be strongly motivated and thoroughly tested. While it can be tricky to reverse engineer some of the workings of the current system, it does represent "the devil we know". |
…olution Previously, the expected result type of a FunProto type was ignored and taken into account only in case of ambiguities. arrayclone-new.scala shows that this is not enough. In a case like val x: Array[Byte] = Array(1, 2) we typed 1, 2 to be Int, so overloading resulution would give the Array.apply of type (Int, Int*)Array[Int]. But that's a dead end, since Array[Int] is not a subtype of Array[Byte]. This commit proposes the following modified rule for overloading resulution: A method alternative is applicable if ... (as before), and if its result type is copmpatible with the expected type of the method application. The commit does not pre-select alternatives based on comparing with the expected result type. I tried that but it slowed down typechecking by a factor of at least 4. Instead, we proceed as usual, ignoring the result type except in case of ambiguities, but check whether the result of overloading resolution has a compatible result type. If that's not the case, we filter all alternatives for result type compatibility and try again.
Previously, this was not done when resolving through tpd. Also, improve comments to explain why we picked the "check afterwards" strategy. Finally, refactor so that the new logic is all inside resolveOverloaded.
7f2c2b9
to
aef3d57
Compare
New test case: array-overload.scala. Failed before, succeeds now.
…rloading Take expected result type into account for overloading resolution
Previously, the expected result type of a FunProto type was ignored and taken into
account only in case of ambiguities. run/arrayclone-new.scala shows that this is not enough.
In a case like
we typed 1, 2 to be Int, so overloading resolution would give the Array.apply of
type (Int, Int*)Array[Int]. But that's a dead end, since Array[Int] is not a subtype
of Array[Byte].
This commit proposes the following modified rule for overloading resolution:
A method alternative is applicable if ... (as before), and if its result type
is compatible with the expected type of the method application.
The commit does not pre-select alternatives based on comparing with the expected
result type. I tried that but it slowed down typechecking by a factor of at least 4.
Instead, we proceed as usual, ignoring the result type except in case of
ambiguities, but check whether the result of overloading resolution has a
compatible result type. If that's not the case, we filter all alternatives
for result type compatibility and try again.
Review by @adriaanm