-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #3945: Fix eta expansion for partially applied methods #3981
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
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.
If I remove the explicit type annotation from int in q
I get:
9 | val p: (String => String) => (String) => (Int) => String = int
| ^
| found: String => Nothing => String => Int => String
| required: String => String => String => Int => String
|
After tracing the constraint set a bit I see that the constraint A <: String
is indeed added. But the type is approximated from below and is instantiated with Nothing
. WDYT?
Take bindingTree into account when deciding which type variables to instantiate before an implicit search. The additions to i3945.scala fail without this change. Also two other tweaks.
Test output for failed tests is missing. I just see |
Looking into it |
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.
LGTM!
This is an altogether unsatisfying scenario. In scala#4032 there's an unconstrained type variable that should be interpolated and it's a coin flip whether we instantiate it to the lower or upper bound. A completely unrelated change in scala#3981 meant that we instantiated the variable to the upper instead of the lower bound which caused the program to fail. We now fix it by adding another condition which is also more or less arbitrary: if neither lower bound nor upper bound is defined, we now prefer again the lower bound. But all of this is quite arbitrary. The fact is that we do cut off some parts of the search space in arbitrary ways and programs have come on rely on the specific arbitrary way in which we do it.
Intrepolation is a pretty delicate scenario. It's difficult to even say what is right and what is wrong. In scala#4032 there's an unconstrained type variable that should be interpolated and it's a coin flip whether we instantiate it to the lower or upper bound. A completely unrelated change in scala#3981 meant that we instantiated the variable to the upper instead of the lower bound which caused the program to fail. The failure was because the type variable appeared covariantly in the lower bound of some other type variable. So maximizing the type first type variable overconstrained the second. We avoid this problem now by computing the variance of the type variable that's eliminated in the rest of the constraint. We take this into account to instantiate the variable so that it narrows the overall constraint the least, defaulting again to lower bound if there is not best direction. Since the test is expensive (linear in the constraint size), we do this only if the variable's lower bound is unconstrained. We could do it for all non-occurring type variables, but have to see how that would affect performance.
This was a tricky one to fix.