Simple use of Java Scala collections not compiling with 2.11

So, I have this awesome Java class:

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

Compiled using 2.10.4 scala-library.jar on the way to classes (or 2.9.2, for what it's worth). Now I will try with 2.11:

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

How does that even make sense? On the one hand, the only difference that may be remotely relevant is that Stream.Empty no longer extends Serializable in 2.11, but I don’t see how this can cause this problem. The same thing happens with List , etc.

There is an easy workaround there - you can just apply to the appropriate type, but I would like to understand what is happening here.

(I am in Oracle JDK, version 1.7.0_67.)

+6
source share
2 answers

The static redirector for the bridge method is not marked as a bridge method, and for some reason java prefers to return GenTraversable for some reason, since 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 cannot overload the return type in the java language so that someone will guess what the compiler will do when it encounters it. I do not know if this was even indicated, although it may be.

In general, you cannot call collection methods from java , and this was appreciated by wontfix.

Edit: re "still do not understand what has changed in 2.11 for this to happen", here is the 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 will not find it by looking at the library code, that's for sure. This is a change in the compiler.

+4
source

What I learned today is that Java gladly ignores the extraneous type arg (JLS 15.12.2.1, small print at the end of the section).

This rule stems from compatibility issues and the principles of interchangeability.

Apparently, some rules are based on fundamental considerations, others on practical issues, and the random rule has a double origin.

 apm@mara :~/tmp$ javap -classpath ~/scala-2.11.2/lib/scala-library.jar scala.collection.immutable.Stream | grep empty public static <A extends java/lang/Object> scala.collection.immutable.Stream<A> empty(); public static scala.collection.GenTraversable empty(); apm@mara :~/tmp$ javap -classpath ~/scala-2.10.4/lib/scala-library.jar scala.collection.immutable.Stream | grep empty public static <A extends java/lang/Object> scala.collection.immutable.Stream<A> empty(); public static <A extends java/lang/Object> scala.collection.immutable.Stream<A> empty(); 

It looks like the bridge method forwarder has been fixed.

This compiles:

 import scala.collection.immutable.Stream; import scala.collection.immutable.Stream$; public class EmptyStreamFactory { public static Stream<String> createEmptyStringStream() { return Stream$.MODULE$.<String>empty(); } } 

I will need a three-day weekend to re-read the specification when overloaded in Java.

Maybe because Stream is abstract, the rule for the rule is for a particular type of return value.

+2
source

Source: https://habr.com/ru/post/974256/


All Articles