Trying to wrap my head around an issue I get calling some Scala code from Java (dummified example):
// $ cat Bar.scala:
trait Bar[F] {
def f : F
final def bar: F = f // the real life example is more involved here
}
// ==================================================
//$ cat Foo.scala:
class Foo() extends Bar[Foo] {
override def f: Foo = this
}
// ==================================================
//$ cat Baz.java:
class Baz {
public static void main(String args[]) {
// Foo foo = new Foo().bar(); // compilation error: incompatible types: Object cannot be converted to Foo
Foo foo = (Foo)(new Foo().bar()); // compiles
}
}
Why is the cast to (Foo)
necessary? The .bar
method is supposed to return an F, which in the context of Foo is necessarily a Foo (?)
Notes:
- If I call
.f()
directly instead of .bar()
, the cast is no longer necessary
- I wrote a Java-only version which doesn’t seem to need the cast (compiles): See gist - hopefully it is indeed equivalent
- If I change the example to using an F-bounded quantification (
[F <: Bar[F]]
), the message changes from complaining about having a “Object” to complaining about a “Bar”
Any insight would be appreciated
Anthony
EDIT: using scala 2.12.13 for the above example
1 Like
My first thought was “type erasure” but having used Scala 3.1.1 to compile Bar
and Foo
, Java 16 compiled
Foo foo = new Foo().bar();
without complaints. So maybe Scala 2.12 is to blame?
1 Like
Interesting… I just tested with 2.13.4
and got the compilation error too
PS: my javac is 1.8.0_161
What about 2.13.8? 2.13.4 is pretty old, too.
Just tried it with 2.13.8: same problem.
To be sure this is what I use to test it: rm *.class || :; ~/bin/scala/2.13.8/bin/scalac Bar.scala Foo.scala && javac -cp ~/bin/scala/2.13.8/lib/scala-library.jar:. Baz.java && java -cp ~/bin/scala/2.13.8/lib/scala-library.jar:. Baz
which gets me:
Baz.java:3: error: incompatible types: Object cannot be converted to Foo
Foo foo = new Foo().bar(); // error: incompatible types: Object cannot be converted to Foo
^
1 error
1 Like
Any reasons to using the CLI commands directly instead of using a build tool like sbt?
Mostly to keep the example minimal
1 Like
Any reason to use CLI commands which aren’t named something-cli
?
I think they are converging on scala-cli
.
It’s nice to get a small repo as a repro, but usually they are not minimal. If I try to update the scala version, then there is often a missing dependency. So I expect scala-cli
to usher in a new era of reproducible snippets.
For such a minimal minimalization, I didn’t even need scala-library.jar
on the path.
It would be nice if I could just run scala
and it does the obvious thing (compile sources in cwd).
Also compile java sources. Was that not obvious enough?
So I think I will report it as an issue in Issues · scala/bug · GitHub, as it seems like it’s legitimate problem.
Thanks all for the help!
PS: reported on as Unexpected compilation error while calling Scala from Java · Issue #12556 · scala/bug · GitHub