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
Incorrect inference of Nothing as type argument through eta expansion #8347
Comments
Imported From: https://issues.scala-lang.org/browse/SI-8347?orig=1 |
@clhodapp said: |
@paulp said: def test[C](x: X[C])(f: X[C] => X[C]): X[C] = f(x) |
@retronym said: scala> trait PPrint[A]
defined trait PPrint
scala> def foo[A: PPrint](a: A) = a
foo: [A](a: A)(implicit evidence$1: PPrint[A])A
scala> def test[A: PPrint](a: A) = Seq(a).foreach(foo(_))
test: [A](a: A)(implicit evidence$1: PPrint[A])Unit
scala> def test[A: PPrint](a: A) = Seq(a).foreach(foo)
<console>:9: error: could not find implicit value for evidence parameter of type PPrint[A]
def test[A: PPrint](a: A) = Seq(a).foreach(foo)
^ |
Here is a minimized test case:
It fails to compile, giving:
It would seem that the compiler is inferring
Int
to pass asC
, butNothing
to pass asB
intest(id, x)
. I would argue that itInt
should be passed as bothB
andC
.Let's look at (a fragment of) the typer-debug output:
We can see that the types for
x
andid
are computed before the type to use as an argument to test is computed. Specifically, the type to be passed asB
is computed asNothing
, since, given no other constraints, this is the most specific, and thus the most desirable, type to pass. This way of doing things might be acceptable if these were regarded as tentative types, with the possibility of being recomputed once the type to be passed as C was inferred. However, they are not recomputed, leading to the sorry state of affairs seen here.I do have one idea as to how to change the logic here, in case it helps anyone. Basically, it would seem to me that the best thing to do would be to infer type arguments from the outside in instead of from the inside out. Specifically, I would create a type range, which started as
<: Any >: Nothing
, and narrow it with each value parameter that referenced it, based on the restrictions created by the arguments passed as those parameters. For instance, here the type off
referencesC
andid
is passed asf
. However, the type ofid
does not narrow the range of possible values forC
. The type ofx
also referencesC
. Sincex0
is passed asx
, we have to see if the type ofx0
restricts the type ofC
. In fact it does! It restrictsC
to be>: Int <: Int
, meaning that it must just beInt
. From here, we can compute expected types for the value arguments oftest
. Specifically,Int
asC
gives us an expected type ofX[Int]
for the argument passed asx
, meaning thatInt
must be passed asB
.One other thing to note: this seems to only be a problem when eta-expansion is involved. I when I changed id to return a custom type similar to Function1:
The text was updated successfully, but these errors were encountered: