Scala 3.0.0-M1 is here

November 2020 brings an important milestone for Scala 3 – the release of Scala 3.0.0-M1. This milestone release is a precursor to the Scala 3.0.0 release candidate planned for the end of the year – which is as little as 6 weeks from now! Later on, the release candidate is planned to evolve into 3.0.0 stable release in February 2021.

Once 3.0.0 release candidate is out, no new features or breaking changes will take place on 3.0.x – it will only be updated for bug fixes. However, we are going to continue the work on making the language better and to test out our research in it. These changes will end up in Scala only as of 3.1.0.

For now though, our teams are focusing the efforts on getting done with the remainder of the 40-something projects that we planned for the upcoming release back in July 2020. Many of them are already completed. Those that aren't yet – get revised and re-planned. With the current global uncertainty and with the scale of the project, we cannot be certain, but we believe we have a reasonable chance of releasing 3.0.0-RC1 by Christmas.

Below, you can find a short summary of the changes that took place during between the 0.27.0-RC1 and 3.0.0-M1 releases.

Scala.js support for Scala 3

Dotty 0.27.0-RC1 had introduced preliminary Scala.js support with the portable subset of Scala and native JavaScript types. Scala 3.0.0-M1 significantly expands on that support:

  • support for non-native JS types (#9774), and
  • better support for other JS interop features, notably their interactions with Scala 3 features such as top-level declarations and enums (e.g, #9725 and #9955).

The only remaining feature of Scala.js that is not supported yet is JS exports: @JSExport and its siblings @JSExportAll, @JSExportTopLevel and @JSExportStatic are all ignored by Scala 3.0.0-M1. Support for JS exports will come in the next release.

For related reading, you can learn more on what it took to implement Scala.js support in Scala 3 on our blog.

Allow as in place of @ for pattern bindings

As the title suggests, this change is fairly straightforward. Now, instead of:

x match {
  case Foo(y @ Bar(z)) => println(y)
}

You can write:

x match {
  case Foo(y as Bar(z)) => println(y)
}

As of Scala 3.1.0, the @ syntax will be deprecated and the codebases should switch to as instead.

This change was implemented by PR #9837.

Pattern-Bound Given Instances

The syntax for given instances in patterns has also changed. In the for-comprehensions, the correct way of using givens is as follows:

for given Context <- applicationContexts do

And in match clauses, you can use them as follows:

pair match
  case (ctx as given Context, y) => ...

For more information, see documentation, and for discussion, see PR #10091.

Change wildcard given selectors

This is another syntactic change which aims to simplify the code. Instead of:

import p.{given _}

The correct version of the wildcard given import now becomes:

import p.given

This change was implemented by PR #9949.

Final API for enumerations

enum definitions are now released in their final design. since 0.27.0-RC1 we have made the following changes:

For the enum definition of Option:

enum Opt[+T] {
  case Sm(value: T)
  case Nn
}

we will now generate on the companion objects of class cases apply and copy methods with the precise subtype:

object Sm {
  ...
  def apply[T](value: T): Sm[T]
  ...
}

however expressions that call apply or copy will be widened to the parent enum type unless the precise type is expected, as we see here:

scala> Sm(23)
val res0: Opt[Int] = Sm(23)

scala> val sm: Sm[23] = Sm(23)
val sm: Opt.Sm[23] = Sm(23)

Previously, when an enumeration declared cases with value parameters, such as Opt.Sm, then the Opt.values array would no longer have indexes that match the enum case ordinals. We feel that this is problematic, so the values and valueOf methods will only be generated when an enum has exclusively singleton cases.

If an enumeration adds a case with value parameters, then consumers will recieve an error that explains why values has been removed.

scala> Opt.values
1 |Opt.values
  |^^^^^^^^^^
  |value values is not a member of object Opt.
  |Although class Opt is an enum, it has non-singleton cases,
  |meaning a values array is not defined

For code that previously relied upon values to lookup singleton cases, we now provide an optimised method fromOrdinal that reflects singleton values. This method is always generated:

scala> Opt.fromOrdinal(1)
val res1: Opt[?] = Nn

Keep @alpha optional for operators

Following the discussion on contributors, we now keep @alpha optional for operators. The checking behavior is still available when compiling with the -Yrequire-alpha.

@alpha annotations provide a way to define an alternate name for symbolic operators. You can learn more about @alpha annotations from the documentation. The change was implemented by PR #10093.

Optimizing the compiler

During the last months, a considerable amount of effort went into investigating performance bottlenecks in the compiler and optimizing its workflow. We also work on stabilizing the compiler and porting relevant changes from the Scala 2 compiler to Scala 3. The following PRs are relevant to highlighting this work:

  • Port classfile parsing improvements #10037
  • Semanticdb usability enhancements #9768
  • Optimize core and frontend #9867

Known issues

This release of Scala 3 doesn't work on JDK 14 because of a regression fixed in #10135. JDK 15 doesn't work either because of scala/bug#12172 which will be fixed in the new scala-library release.

Let us know what you think!

If you have questions or any sort of feedback, feel free to send us a message on our Gitter channel. If you encounter a bug, please open an issue on GitHub.

Contributors

Thank you to all the contributors who made this release possible 🎉

According to git shortlog -sn --no-merges 0.27.0-RC1..3.0.0-M1 these are:

   171  Martin Odersky
    94  Nicolas Stucki
    75  Liu Fengyun
    62  Aleksander Boruch-Gruszecki
    50  Filip Zybała
    35  Krzysztof Romanowski
    34  Anatolii Kmetiuk
    32  Sébastien Doeraene
    31  Guillaume Martres
    28  Jamie Thompson
    20  bishabosha
    19  Guillaume Raffin
    16  Krzysztof Romanwoski
    12  Ruslan Shevchenko
     9  Tom Grigg
     6  Som Snytt
     5  odersky
     5  Andrzej Ratajczak
     4  Michał Pałka
     3  Adrien Piquerez
     3  Tudor Voicu
     3  noti0na1
     2  Krzysztof Bochenek
     2  Tudor
     2  Raphael Jolly
     2  Miles Sabin
     1  Vasil Vasilev
     1  ansvonwa
     1  Greg Zoller
     1  felher
     1  gzoller
     1  zgrybus
     1  Fengyun Liu
     1  Philippus Baalman
     1  Krzysiek Bochenek
     1  Tomasz Godzik
     1  ysthakur

If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our Getting Started page for new contributors, and have a look at some of the good first issues. They make perfect entry points into hacking on the compiler.

We are looking forward to having you join the team of contributors.

Library authors: Join our community build

Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. Join our community build to make sure that our regression suite includes your library.