Scala 2.13 and Scala 3 Binary Interoperability via TASTy
26.5K reputation · 22 Jan 2023, 15:21 UTC
JVM Bytecode and TASTy Integration
Scala 3 introduces the TASTy (Typed Abstract Syntax Tree) format to decouple the compiler from the runtime representation, aiming to solve long-standing binary compatibility issues found in the Scala 2.x series. While the Scala 3 compiler can consume Scala 2.13 binaries, the reverse interaction and the stability of the binary interface across minor version increments remain complex.
The primary goal is to ensure that libraries compiled with different compiler versions can coexist on the same classpath without triggering NoSuchMethodError or ClassCastException, particularly when using reflection-based access to members that may undergo name mangling.
Given the differences in how Scala 2.13 and Scala 3 map traits and case classes to JVM bytecode, there is uncertainty regarding the long-term stability of the binary interface during minor version updates.
- How does the TASTy format specifically resolve the name mangling discrepancies between Scala 2.13 and Scala 3 binaries?
- What are the specific constraints when linking a Scala 3 project against a library compiled with a minor version of Scala 2.13?
1 answer
1 question comment
Use comments to ask for clarification. Post a solution as an answer.
26,525 reputation · 22 Jan 2023, 17:05 UTC
TASTy is a Scala‑3‑specific metadata format that survives compilation only inside the Scala 3 compiler pipeline. When the Scala 3 backend targets the JVM, it erases all TASTy information and emits ordinary .class files whose signatures are exactly those produced by the Scala 2.13 compiler for the same source (modulo the erasure of Scala‑3‑only features). Consequently, Scala 2.13 code can link against a Scala 3 library without ever reading TASTy; the JVM sees only the erased bytecode.
One practical implication is that, to maintain binary compatibility across Scala 3 minor versions, you must avoid exposing any Scala‑3‑specific constructs that survive erasure (e.g., opaque types, match types, or inline methods) in the public API. If such constructs are needed, they should be marked @inline or moved to a private implementation detail, or you must publish separate artifacts for each Scala 3 minor version.