Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple use of Scala collections from Java not compiling with 2.11

So I've got this super exciting Java class:

import scala.collection.immutable.Stream;

public class EmptyStreamFactory {
  public static Stream<String> createEmptyStringStream() {
    return Stream.<String>empty();
  }
}

Compiles just fine with the 2.10.4 scala-library.jar on the classpath (or 2.9.2, for what that's worth). Now I try it with 2.11:

EmptyStreamFactory.java:5: error: incompatible types
    return Stream.<String>empty();
                               ^
  required: Stream<String>
  found:    GenTraversable
1 error

How does this make any sense at all? At a glance the only difference that could be remotely relevant is the fact that Stream.Empty no longer extends Serializable in 2.11, but I don't see how that could cause this problem. The same thing happens with List, etc.

There's an easy workaround—you can just cast to the appropriate type—but I'd like to understand what's going on here.

(I'm on Oracle's JDK, version 1.7.0_67.)

like image 825
Travis Brown Avatar asked Aug 24 '14 00:08

Travis Brown


People also ask

What is the difference between Java and Scala libraries?

In particular, the Scala libraries put much more emphasis on immutable collections, and provide many more operations that transform a collection into a new one. Sometimes you might need to pass from one collection framework to the other. For instance, you might want to access an existing Java collection as if it were a Scala collection.

What version of Java should I use to compile Scala code?

We recommend using Java 8 for compiling Scala code. Since the JVM is backward compatible, it is usually safe to use a newer JVM to run your code compiled by the Scala compiler for older JVM versions. There are notable exceptions with experimental/unsafe features, and the introduction of the module system in Java 9.

Are collections copied when converting between Java and Scala?

So collections are never copied when converting between Java and Scala. An interesting property is that if you do a round-trip conversion from, say a Java type to its corresponding Scala type, and back to the same Java type, you end up with the identical collection object you have started with.

What is the Scala collection framework?

This framework enables you to work with data in memory at a high level, with the basic building blocks of a program being whole collections, instead of individual elements. This style of programming requires some learning. Fortunately, the adaptation is helped by several nice properties of the Scala collections.


1 Answers

The static forwarder for the bridge method isn't marked as a bridge method itself, and java for whatever reason prefers the one returning GenTraversable as it has two to choose from.

classOf[scala.collection.immutable.Stream[_]].getMethods filterNot 
  (_.isBridge) filter (_.getName == "empty") foreach println
public static scala.collection.immutable.Stream scala.collection.immutable.Stream.empty()
public static scala.collection.GenTraversable scala.collection.immutable.Stream.empty()

You can't overload on return type in java the language so it's anyone's guess what the compiler will do when it encounters it. I don't know if it's even specified, although it may be.

In general you can't call collections methods from java, and this has been judged wontfix.

Edit: re "still don't understand what changed in 2.11 to make this happen", here is an initial batch of candidates:

% git log --no-merges --oneline --grep=forwarder v2.10.4..v2.11.2
532ef331eb (pull/3868/head) Restore reporter forwarders in CompilationUnit
b724201383 Rip out reporting indirection from CompilationUnit
98216be3f3 Move reporting logic into Reporting trait
653c404d7f (pull/3493/head) SI-3452 GenBCode version of the static-forwarder signature fix
640e279500 SI-3452 A better fix for static forwarder generic sigs
f8d80ea26a SI-3452 Correct Java generic signatures for mixins, static forwarders
51ec62a8c3 (pull/3480/head) SI-6948 Make the Abstract* classes public.
731ed385de SI-8134 SI-5954 Fix companions in package object under separate comp.
3cc99d7b4a (pull/3103/head) Collections library tidying and deprecation.  Separate parts are listed below.
5d29697365 Flesh out the Delambdafy phase.
6e2cadb8bd (pull/2951/head) SI-7847 Static forwarders for case apply/unapply
9733f56c87 (pull/1173/head) Fixes SI-4996.

You're not going to find it by looking at the library code, that much is certain. It's a change in the compiler.

like image 168
psp Avatar answered Oct 25 '22 12:10

psp