Skip to content
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

Binary incompatibility across Scala 2.12.2/2.12.1 and 2.12.3 versions #10489

Closed
Lazu13 opened this issue Aug 30, 2017 · 5 comments
Closed

Binary incompatibility across Scala 2.12.2/2.12.1 and 2.12.3 versions #10489

Lazu13 opened this issue Aug 30, 2017 · 5 comments

Comments

@Lazu13
Copy link

Lazu13 commented Aug 30, 2017

The following simple project: https://github.com/Lazu13/algebirdTest.git shows binary incompatibility across Scala 2.12.3 used in project and Scala 2.12.1 used to compile Algebird 0.13.0 library.

Code from Test.scala compiles but fails in runtime with exception:

Exception in thread "main" java.lang.BootstrapMethodError: java.lang.NoSuchMethodError: scala.math.Ordering$.$anonfun$by$1$adapted(Lscala/Function1;Lscala/math/Ordering;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
	at com.twitter.algebird.Aggregator$.minBy(Aggregator.scala:174)
Aggregator.minBy

uses

Ordering.by(fn)

from scala.math.Ordering

Please note:

  1. Compiling project with Scala 2.12.3 and Algebird library with 2.12.3 makes it works
  2. Compiling project with Scala 2.12.2/2.12.1 and Algebird with 2.12.1/2.12.2 makes it works

JDK 1.8.0_144

@som-snytt
Copy link

algebird is built with -opt:l:classpath, and the release note says When inlining code from the classpath, you must ensure that all dependencies have exactly the same versions at compile time and run time.

@Lazu13
Copy link
Author

Lazu13 commented Sep 1, 2017

I checked it, building with Scala 2.12.1 without the flag and it didn’t work with project in Scala 2.12.3.

However, building Algebird with compiler flag with Scala 2.12.1 and project with Scala 2.12.2 (and vice versa) works even though those are different versions of Scala.

I can't see any uses of inline annotation in Aggregator.minBy neither at definition site nor callsite (In the project there is a use of inline identity method, however replacing it with other non-inline method still does not work)

EDIT:
higher-order methods are inlined if the function argument is a lambda, or a parameter of the caller.
Ok, so the method Aggregator.minBy and Ordering.by is made inline using Scala version 2.12.X and I must ensure that in the runtime the same version of Scala is used. Otherwise I get an exception. However, I turned the flag off, so I shouldn't be getting the error...

Thanks

@som-snytt
Copy link

Thanks for checking. I meant to try it back home. I don't know much about it, but I'm pretty sure the optimizer will inline what it can, such as unannotated static finals. Eventually @lrytz will show up to explain it to us. I think you can do that when you control the downstream dependencies, of which scala itself has none. I'll try it out if I'm not travelling for the US Labor Day weekend. They call it Labor Day because it's a long weekend for catching up on work you were supposed to finish last week.

@Lazu13
Copy link
Author

Lazu13 commented Sep 1, 2017

Thanks.
OK. I checked the Algebird library once again and I found out that when I use -optimize flag it also uses the -opt:l:classpath.
So getting rid of the optimize helped.

Once again thanks

EDIT
What about versions Scala 2.12.2 project and Scala 2.12.1 Algebird? Why does it work with flag turned on? My observations are that those methods bodies are the same in 2.12.1 and 2.12.2 (changed in 2.12.3) and that might be the reason why it doesn't fail in runtime across those Scala versions.

@lrytz
Copy link
Member

lrytz commented Sep 5, 2017

The issue is not caused by a difference in the bytecode of the test project (algebirdTest). 2.12.2 and 2.12.3 produce (almost) the same bytecode for that project. The difference is the run-time classpath: when you switch from 2.12.2 to 2.12.3, the Scala library version on the classpath also changes.

In 2.12.2, Ordering.by was implemented using a lambda. This changed in 2.12.3 in scala/scala#5854, so the method $anonfun$by$1$adapted which implements the lambda body in 2.12.2 no longer exists in 2.12.3. The by method of 2.12.2 was inlined into Algebird 0.13.0, so it will not work with the 2.12.3 Scala library on the classpath.

We have to communicate more clearly that the inliner must not be enabled when building a library that's being distributed and expected to be binary compatible.

twitter/algebird#640

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants