Upcoming Scala releases: 2.12.3 and 2.13.0-M2

2.12.3

Highlights:

2.13.0-M2

The REPL is undergoing renovations and features better positioning of errors and a cleaner internal implementation. multi-line editing and syntax highlighting.

Right associative methods with a by-name parameter no longer eagerly evaluate the operand.

Furthermore, all changes in the 2.12.3 will be part of 2.13.0-M2.

What’s next?

We are planning to make 2.13.x the default branch for pull requests after these releases to help us focus our collective attention on working towards 2.13.0. We’ll still target some changes to 2.12.x that are high reward and low risk, that fix important regressions.

3 Likes

This looks great.

One question: by default is the inliner on 2.12 inlining from any class in the classpath?

The reason I ask is that bazel uses a technique to create interface jars of removing all the code in the classes and leaving only the method signatures. This is so the hash of the interface jars does not change when only private methods change. Clearly, these jars are not suitable for inlining as they lack any code.

However, we also don’t know what classes are in those jars typically. We just know the jar names. So, if by default we inline from everywhere in 2.12, the only safe move will be to set the inliner to only inline from I guess scala.** or something.

For us, the ideal would probably be to allow inlining from the source you are compiling, but none of the jars. Is that the same as limiting the class inlining to scala.** or similar?

No one has implemented 2.12 support in the bazel scala rules yet:

so we have not hit this issue, but we are considering how to do this now.

Firstly, its worth reiterating that we’d like people to move from scalac -optimize to scalac -opt:.... The new option requires an explicit opt-in to an inlining policy.

For backwards compatibility, we deprecated the old option with the following advice:

% scalac -deprecation -optimize sandbox/test.scala
warning: -optimise is deprecated: In 2.12, -optimise enables -opt:l:inline -opt-inline-from:**. Check -opt:help for using the Scala 2.12 optimizer.

Previous releases of 2.12 had a course grained way to select where to inline from. These are now also deprecated in favour of the new option.

  l:project            [deprecated, use -opt:l:inline, -opt-inline-from] Enable cross-method optimizations within the current project.
  l:classpath          [deprecated, use -opt:l:inline, -opt-inline-from] Enable cross-method optimizations across the entire classpath.

We no longer to express an inlining rule to mean “the sources in the current compile run”. We left the possibility open to add -opt-inline-from:<sources> for this purpose, but we haven’t implemented it yet.

I think it is preferable to use a package based approach so that scalac A.scala B.scala has the same end result as scalac A.scala B.scala; scalac A.scala, as is common under incremental compilation. I suppose for use cases when you know you are performing a full build, the <sources> option would be more convenient.

Okay. l:project seems like exactly what we would want. But you say that is deprecated, but I guess it will still work. When did it get deprecated? In 2.12.3 (the upcoming release?). That’s a shame since it seems the only convenient way to use optimizations with bazel.

We get incrementalism in bazel by having small targets and having bazel only invoke scalac on the portions of the graph that have changed (since bazel needs to manage all the state of the build in order to give its correctness guarantees).

BTW, unless you’re preserving the @ScalaSignature and @ScalaLongSignature annotations (aka the “pickle”) which contain the Scala-type-system-view of the API, you’ll get some spurious non-compiles.

Here’s an example of a change that is invisible to Java.

% for i in Int Float; do scalac $(f "class Test(a: Option[$i])"); ~/bin/jardiff -g /tmp/diff -q Test.class; done

% (cd /tmp/diff && git show)
commit e7c345ab1e10a0020c5de1e43d9dc9aa8c9180b4 (HEAD -> master)
Author: Jason Zaugg <[email protected]>
Date:   Fri Jul 7 19:48:51 2017 +0200

    jardiff textified output of: Test.class

diff --git a/Test.class.scalap b/Test.class.scalap
index 2313292..f03499a 100644
--- a/Test.class.scalap
+++ b/Test.class.scalap
@@ -1,3 +1,3 @@
 class Test extends scala.AnyRef {
-  def this(a: scala.Option[scala.Int]) = { /* compiled code */ }
+  def this(a: scala.Option[scala.Float]) = { /* compiled code */ }
 }

Our jardiff tool also compares the output of scalap, which is based on the pickles, and only in that output is the change visible.

The pickle contains more info than you want, notably all private methods are in there. You’d need a diet pickle with just public stuff.

Yep, its about to be deprecated in 2.12.3. But we might have time to add the meta-pattern for <sources> now that we see the use case.

At least for SBT (or Zinc based incremental compilation), the recommendation is to disable the inliner during development builds. If you want to enable it at all, then do so in your CI and release builds. SBT doesn’t make any guarantees about correctness of incremental compilation with it enabled.

We use -opt:l:project everywhere in our libraries because its the optimizer setting that you are meant to use when deploying libraries since it only optimizes what is visible in your project

I would also advice in deprecating it (however it is correct that for local building you shouldn’t be using this setting since it trips up the incremental compilation, you should only use this flag when packaging)

PR https://github.com/scala/scala/pull/5989 adds -opt-inline-from:<sources>, which is the same as -opt:l:project. So the functionality will be there in 2.12.3.

Is July still the 2.12.3 release date target?

When I checked this morning the issue tracker had a clean slate, so was hoping to see 2.12.3 sooner than later.

We have some test failures related to the Scaladoc tool that need to be fixed before the release. A bug in our build hid these failures from us.

I’m working on this issue today.

yes, ijar preserves the scala signatures:

We have been using the bazel scala rules in production for over a year. No issues that we have seen.

You are missing ScalaLongSig (used when the contents are too larges to
store in a single annotation argument)

I would also expect that you get spurious recompiles because private
methods signatures are part of the pickle.

I think not, they are parsing classfile attributes, not annotations, at this point. The ScalaLongSignature is an annotation. AFAIK there was no (need for a) long signature back when the pickle was stored in an attribute.

That doesn’t work: since 2.10 the scala signature is no longer stored in the ScalaSig classfile attribute, but in a RuntimeVisibleAnnotation scala/reflect/ScalaSignature (or ScalaLongSignature for very large pickles).

class C {
  def f = 1
}

gives (disassembled with asm)

// class version 52.0 (52)
// access flags 0x21
public class C {

  // compiled from: Test.scala

  @Lscala/reflect/ScalaSignature;(bytes="\u0006\u0001]1A!\u0001\u0002\u0001\u000b\u0009\u00091IC\u0001\u0004\u0003\u001daT-\u001c9usz\u001a\u0001a\u0005\u0002\u0001\rA\u0011qAC\u0007\u0002\u0011)\u0009\u0011\"A\u0003tG\u0006d\u0017-\u0003\u0002\u000c\u0011\u00091\u0011I\\=SK\u001aDQ!\u0004\u0001\u0005\u00029\u0009a\u0001P5oSRtD#A\u0008\u0011\u0005A\u0001Q\"\u0001\u0002\u0009\u000bI\u0001A\u0011A\n\u0002\u0003\u0019,\u0012\u0001\u0006\u0009\u0003\u000fUI!A\u0006\u0005\u0003\u0007%sG\u000f")

  ATTRIBUTE ScalaSig : unknown

  ATTRIBUTE ScalaInlineInfo : unknown

...

The ScalaSig attribute is just kept as a marker that the classfile has a Scala signature (stored in the annotation), but the attribute itself is empty.

Though if I understand the ijar code correctly, all RuntimeVisibleAnnotations are kept, so that would include Scala signatures.

Scala 2.13.0-M2 is now staged in https://oss.sonatype.org/content/repositories/staging/. Distributions and official announcements will follow soon.

2 Likes

The 2.12.3 release is staged. You can already use it (to help our testing) by adding the “https://oss.sonatype.org/content/repositories/staging” resolver.

It hasn’t been tagged or pushed to maven central yet, though.

More info at https://github.com/scala/scala-dev/issues/404

2.12.3 has hit Maven Central. The release announcement will be live on scala-lang.org shortly.

1 Like

The compiler plugins for Scala.js 0.6.18 and 1.0.0-M1 are on their way to Maven Central.

3 Likes

scalacheck, scalatest, scalaprops, shapeless, scalaz 7.2, and some other libraries have been published for 2.13.0-M2

see https://github.com/scala/make-release-notes/blob/2.13.x/projects-2.13.md for a list of available libraries, as well as some links to issues or pull requests for missing libraries