Skip to content

Commit

Permalink
-Yscala-release support: fix documentation; run extended CI only for …
Browse files Browse the repository at this point in the history
…nightly builds
  • Loading branch information
prolativ committed Jan 19, 2022
1 parent 0c8ac84 commit 85cf9be
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 10 deletions.
6 changes: 0 additions & 6 deletions .github/workflows/ci.yaml
Expand Up @@ -327,12 +327,6 @@ jobs:
- ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache
- ${{ github.workspace }}/../../cache/general:/root/.cache
if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty'
|| github.event_name == 'push'
|| (
github.event_name == 'pull_request'
&& !contains(github.event.pull_request.body, '[skip ci]')
&& !contains(github.event.pull_request.body, '[skip community_build]')
)
|| (
github.event_name == 'workflow_dispatch'
&& github.repository == 'lampepfl/dotty'
Expand Down
Expand Up @@ -975,6 +975,9 @@ class ClassfileParser(
entry.underlyingSource.map(_.name.startsWith("scala3-library_")).getOrElse(false)
case _ => false
}
// While emitting older TASTy the the newer standard library used by the compiler will still be on the class path so trying to read its TASTy files should not cause a crash.
// This is OK however because references to elements of stdlib API are validated according to the values of their `@since` annotations.
// This should guarantee that the code won't crash at runtime when used with the stdlib provided by an older compiler.
val isTastyCompatible = fileTastyVersion.isCompatibleWith(ctx.tastyVersion) || isStdlibClass(classRoot)
if !isTastyCompatible then
reportWrongTasty(s"its TASTy format is not compatible with the one of the targeted Scala release (${ctx.scalaRelease.show})", ctx.tastyVersion)
Expand Down
11 changes: 7 additions & 4 deletions docs/docs/reference/language-versions/binary-compatibility.md
Expand Up @@ -3,12 +3,15 @@ layout: doc-page
title: "Binary Compatibility"
---

In Scala 2 different minor versions of the compiler were free to change the way how they encode different language features in JVM bytecode so each bump of the compiler's minor version resulted in breaking binary compatibility and if a project had any Scala dependencies they all needed to be (cross-)compiled to the same minor Scala version that was used in that project itself.
While in Scala 3 the JVM encoding might still change between minor versions, an additional intermediate format of code representation called TASTy (from `Typed Abstract Syntax Tree`) was introduced.
In Scala 2 different minor versions of the compiler were free to change the way how they encode different language features in JVM bytecode so each bump of the compiler's minor version resulted in breaking binary compatibility and if a project had any Scala dependencies they all needed to be (cross-)compiled to the same minor Scala version that was used in that project itself. On the contrary, Scala 3 has a stable encoding into JVM bytecode.

TASTy files are produced from Scala 3 sources during compilation, together with classfiles, and they're normally also included in published artifacts. A Scala compiler in version `3.x1.y1` is able to read TASTy files produced by another compiler in version `3.x2.y2` if `x1 >= x2` (assuming two stable versions of the compiler are considered - `SNAPSHOT` or `NIGHTLY` compiler versions can read TASTy in an older stable format but their TASTY versions are not compatible between each other even if the compilers have the same minor version; also compilers in stable versions cannot read TASTy generated by an unstable version). While having TASTy files in an understandable format on its classpath a Scala 3 compiler can generate bytecode for a project's dependencies on the fly.
In addition to classfiles the compilation process in Scala 3 also produces files with `.tasty` extension. The [TASTy](https://docs.scala-lang.org/scala3/guides/tasty-overview.html) format is an intermediate representation of Scala code containing full information about sources together with information provided by the typer. Some of this information is lost during generation of bytecode so Scala 3 compilers read TASTy files during compilation in addition to classfiles to know the exact types of values, methods, etc. in already compiled classes (although compilation from TASTy files only is also possible). TASTy files are also typically distributed together with classfiles in published artifacts.

Being able to bump the compiler version in a project without having to wait for all of its dependencies to do the same is already a big leap forward when compared to Scala 2. However, me might still try to do better, especially from the perspective of authors of libraries.
TASTy format is extensible but it preserves backward compatibility and the evolution happens between minor releases of the language. This means a Scala compiler in version `3.x1.y1` is able to read TASTy files produced by another compiler in version `3.x2.y2` if `x1 >= x2` (assuming two stable versions of the compiler are considered - `SNAPSHOT` or `NIGHTLY` compiler versions can read TASTy in an older stable format but their TASTY versions are not compatible between each other even if the compilers have the same minor version; also compilers in stable versions cannot read TASTy generated by an unstable version).

TASTy version number has the format of `<major_version>.<minor_version>-<experimental_version>` and the numbering changes in parallel to language releases in such a way that a bump in language minor version corresponds to a bump in TASTy minor version (e.g. for Scala `3.0.0` the TASTy version is `28.0-0`). Experimental version set to 0 signifies a stable version while others are considered unstable/experimental. TASTy version is not strictly bound to the data format itself - any changes to the API of the standard library also require a change in TASTy minor version.

Being able to bump the compiler version in a project without having to wait for all of its dependencies to do the same is already a big leap forward when compared to Scala 2. However, we might still try to do better, especially from the perspective of authors of libraries.
If you maintain a library and you would like it to be usable as a dependency for all Scala 3 projects, you would have to always emit TASTy in a version that would be readble by everyone, which would normally mean getting stuck at 3.0.x forever.

To solve this problem a new experimental compiler flag `-Yscala-release <release-version>` (available since 3.1.2-RC1) has been added. Setting this flag makes the compiler produce TASTy files that should be possible to use by all Scala 3 compilers in version `<release-version>` or newer (this flag was inspired by how `-release` works for specifying the target version of JDK). More specifically this enforces emitting TASTy files in an older format ensuring that:
Expand Down

0 comments on commit 85cf9be

Please sign in to comment.