Scala 3.0.0-M3: developer's preview before RC1

We are happy to announce the release of Scala 3.0.0-M3. This release is the Developer's Preview release. It is intended to contain all the features meant for RC1, which is tentatively planned for January 2021. The purpose of M3 is to give the larger community, beyond early adopters, a chance to try out all the features and give us feedback before sealing them in RC1.

To collect the feedback, we have designed a Scala 3 Developer’s Preview satisfaction survey (3-5 min) – please fill it in to express how you feel about Scala 3.

During the weeks between M2 and M3, we have been tying up all the loose ends, so that everything intended for the release could be finished before ending 2020. In addition, we have used this time to review and fine-tune the language syntax. Finally, a large number of consultations with the community took place during this time.

In this article, you will find the most important changes of this release compared to Scala 3.0.0-M2.

To read more about all things that surround the Scala 3 release in the next months, check out the "Scala 3 - Crossing the finish line" blog post on scala-lang.org

You can try out the M3 version online via Scastie.

sbt plugin update

We published a new version of the sbt plugin sbt-dotty, v0.5.1. Because of the changes in PR #10607, this release of Scala 3 will not work with earlier versions of sbt-dotty. You will need to upgrade sbt-dotty to 0.5.1 to be able to use Scala 3.0.0-M3.

Final syntactic tweaks

as dropped from the given syntax

The following syntax is obsolete:

given intOrd as Ordering[Int]:
  ...
given listOrd[T: Ordering] as Ordering[List[T]]:
  ...

given Ordering[Int]:
  ...
given [T: Ordering] as Ordering[List[T]]:
  ...

given global as ExecutionContext = ForkJoinContext()
given Context = ctx

Here is how the above is expressed now:

given intOrd: Ordering[Int] with
  ...
given listOrd[T: Ordering]: Ordering[List[T]] with
  ...

given Ordering[Int] with
  ...
given [T: Ordering]: Ordering[List[T]] with
  ...

given global: ExecutionContext = ForkJoinContext()
given Context = ctx

You can find a discussion of the above change in the PR #10538.

Drop as in patterns

Since we dropped as from givens, we lost a strong reason for having as at all. Therefore, we dropped as from patterns as well. The following syntax, valid in Scala 3.0.0-M2, is not accepted anymore:

case opt as Some(foo)

Instead, code that used it should be reverted to use the existing syntax of Scala 2, using @:

case opt @ Some(foo)

Switch back to the old context function closure syntax

Previously, context function closures were written as follows:

(using s: Show[String]) => s.show("foobar")

Now, we have reverted to the following syntax:

(s: Show[String]) ?=> s.show("foobar")

Matchable trait – a new top-level type

Although opaque types are supposed to provide an opaque abstraction of their underlying types, it is currently too easy to break the abstraction using pattern matching:

val imm = IArray(1,2,3) // supposedly immutable...
imm match
  case a: Array[Int] => a(0) = 0  // but that's shown to be lie

To address this change, we introduce a new trait Matchable near the top of the type hierarchy:

abstract class Any:
  def asInstanceOf
  def ==
  def !=
  def ##
  def equals
  def hashCode
  def toString

trait Matchable extends Any:
  def isInstanceOf
  def getClass

class AnyVal extends Any, Matchable

class Object extends Any, Matchable

Matchable is currently a marker trait without any methods. Over time, we intend to migrate the methods getClass and isInstanceOf to it, since these are closely related to pattern-matching.

In the meantime, the compiler will emit warnings when trying to call those methods, or when performing a match, on an value that is not a Matchable. For example, the above example is now flagged:

-- Warning: i7314.scala:6:12 ---------------------------------------------------
6 |    case a: Array[Int] =>
  |            ^^^^^^^^^^
  |            pattern selector should be an instance of Matchable,
  |            but it has unmatchable type opaques.IArray[Int] instead

Note that the warnings are only active with language mode 3.1-migration or higher - see the documentation on the Language Versions to learn how to enable it.

You can read the discussion of this change in the PR #10670. You can also read more about it in the documentation.

Tooling improvements

As we are getting closer to a stable release of Scala 3, the focus increasingly shifts on the tooling available to get started with Scala 3.

For a while now, we are not using the old dottydoc documentation tool for building the documentation. We are developing an entirely new tool, scala3doc, from scratch. This new documentation tool is more robust and faster than the old one.

As part of the tooling effort, this new Scala 3 documentation tool is rapidly improved. PR #10522 proves that the doctool can generate documentation for the community build projects. You can access this documentation via the following link.

PR #10491 introduced scripting support in Scala 3. Consider the following source named Main.scala:

@main def Test(name: String): Unit =
  println(s"Hello ${name}!")

If you have Scala 3 binaries on your path (which you can get by following the steps on the Dotty website, in the section "Try Dotty"), you can run the following command:

$ scala Main.scala World

This will compile the source in question to a temporary directory and run the discovered main method with the argument World.

Note the difference from the Scala 2 scripting implementation. In Scala 2, we do not require the users to have a main method in their scripts due to it being too cumbersome to write. In Scala 3, thanks to the top-level definitions and the @main annotations, main methods are one-liners and hence are more suited for scripts.

The documentation for this feature is available here.

Metaprogramming changes

We have been polishing the metaprogramming API and making it more uniform. The following notable changes occurred between M2 and M3:

  • Add Expr.asTerm #10694
  • Add reflect MatchCase TypeRepr #10735
  • Rework reflect Symbol fields API #10705
  • Remove Expr.StringContext.unapply #10675
  • Rename Liftable to ToExpr and Unliftable to FromExpr #10618
  • Remove Unliftable[Unit] #10570
  • Remove reflect.LambdaType #10548
  • Add scala.quoted.Expr.unapply as dual of Expr.apply #10580
  • Move Quotes as last parameter in ExprMap.transform #10519
  • Rework reflect Constant API #10753
  • Unify quoted.report and reflect.Reporting #10474
  • Fix #10359: Add GivenSelector to reflection API #10469
  • Rework reflect show API #10661
  • Fix #10709: Add missing level check before inlining #10781

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 3.0.0-M2..3.0.0-M3 these are:

    80  Nicolas Stucki
    73  Martin Odersky
    64  Krzysztof Romanowski
    32  Liu Fengyun
    28  Aleksander Boruch-Gruszecki
    22  Anatolii Kmetiuk
    17  Guillaume Martres
    17  Sébastien Doeraene
    14  Andrzej Ratajczak
    13  Tom Grigg
     8  Filip Zybała
     7  Lan, Jian
     5  Olivier Blanvillain
     5  Som Snytt
     5  Jamie Thompson
     4  Stéphane Micheloud
     4  Lionel Parreaux
     3  Adrien Piquerez
     3  Artur Opala
     3  Hanns Holger Rutz
     3  Michael Pilquist
     3  Michał Pałka
     3  bishabosha
     2  Jonathan Brachthäuser
     2  Camila Andrea Gonzalez Williamson
     1  Mikael Blomstrand
     1  Francois GORET
     1  Felix Mulder
     1  Raphael Jolly
     1  Robert Stoll
     1  Ruslan Shevchenko
     1  Seth Tisue
     1  Eugene Yokota
     1  Amadou CISSE
     1  Akhtiam Sakaev
     1  Martin Duhem
     1  Tomasz Godzik
     1  Matthew Pickering
     1  odersky

If you want to get your hands dirty and contribute to Scala 3, head to our Getting Started page for new contributors and read the docs on contributing. You are also very welcome to contact someone from our team to help you get started and see what currently we need help with.

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

Library authors: Join our community build

Scala 3 is regularly tested against a sample of libraries known as the "community build". You can add your library to the community build by submitting a PR.