Description
When using structural type scala sometimes successfully matches java class with it, and sometimes doesn't - see below:
Directory structure is as follows:
foo
foo/Incomp.java
baz
baz/UsesBar.scala
bar
bar/Bar.scala
where classes Incomp, Bar, UsesBar sources are:
// Incomp.java
package foo;
import java.util.List;
import java.util.ArrayList;
public class Incomp {
public List returnsJavaList() {
return new ArrayList();
}
}
// Bar.scala
package bar
import foo.Incomp
object Bar {
def useBogus(bogus: BogusType) {
println("Hello, " + bogus.returnsJavaList().size().toString + "-element list!")
}
type BogusType = {
def returnsJavaList(): java.util.List[_]
}
def useIncomp = useBogus(new Incomp)
}
// UsesBar.scala
package baz
import foo.Incomp
import bar.Bar
class UsesBar {
Bar.useBogus(new Incomp)
}
There is a structural type defined in Bar.scala which Incomp is compatible with. Despite that, when I tried to compile Bar.scala along with Incomp.java I got this error:
maciej@maciej-laptop:~/tmp/scala-java$ ~/opt/scala-2.10.0-RC1/bin/scalac foo/Incomp.java bar/Bar.scala
bar/Bar.scala:15: error: type mismatch;
found : foo.Incomp
required: bar.Bar.BogusType
(which expands to) AnyRef{def returnsJavaList(): java.util.List[_]}
def useIncomp = useBogus(new Incomp)
^
one error found
Now, everything compiles fine, when scalac has Incomp.class at its disposal:
maciej@maciej-laptop:~/tmp/scala-java$ javac foo/Incomp.java
maciej@maciej-laptop:~/tmp/scala-java$ ~/opt/scala-2.10.0-RC1/bin/scalac bar/Bar.scala
warning: there were 1 feature warnings; re-run with -feature for details
one warning found
I believe this incosistency alone would justify filing a bug report. But then, as it turns out, even having Incomp.class is not enough sometimes:
maciej@maciej-laptop:~/tmp/scala-java$ ~/opt/scala-2.10.0-RC1/bin/scalac baz/UsesBar.scala
baz/UsesBar.scala:8: error: type mismatch;
found : foo.Incomp
required: bar.Bar.BogusType
(which expands to) AnyRef{def returnsJavaList(): java.util.List[_]}
Bar.useBogus(new Incomp)
^
one error found
So I can't compile UsesBar neither with Incomp.java nor Incomp.class
maciej@maciej-laptop:~/tmp/scala-java$ ~/opt/scala-2.10.0-RC1/bin/scalac foo/Incomp.java baz/UsesBar.scala
baz/UsesBar.scala:8: error: type mismatch;
found : foo.Incomp
required: bar.Bar.BogusType
(which expands to) AnyRef{def returnsJavaList(): java.util.List[_]}
Bar.useBogus(new Incomp)
^
one error found
To compile UsesBar I had to compile it with Bar.scala
maciej@maciej-laptop:~/tmp/scala-java$ ~/opt/scala-2.10.0-RC1/bin/scalac bar/Bar.scala baz/UsesBar.scala
warning: there were 1 feature warnings; re-run with -feature for details
one warning found
But adding Incomp.java would result in error again:
maciej@maciej-laptop:~/tmp/scala-java$ ~/opt/scala-2.10.0-RC1/bin/scalac foo/Incomp.java bar/Bar.scala baz/UsesBar.scala
bar/Bar.scala:15: error: type mismatch;
found : foo.Incomp
required: bar.Bar.BogusType
(which expands to) AnyRef{def returnsJavaList(): java.util.List[_]}
def useIncomp = useBogus(new Incomp)
^
baz/UsesBar.scala:8: error: type mismatch;
found : foo.Incomp
required: bar.Bar.BogusType
(which expands to) AnyRef{def returnsJavaList(): java.util.List[_]}
Bar.useBogus(new Incomp)
^
two errors found
This seems quite unpredictable - and while you can eventually compile what you want, provided that you compile all scala sources at once, this for example disrupts maven configuration, where test sources are compiled independently from the main source tree, resulting in errors similar to those shown above.