Scala 3 Migration Guide

Incompatibility Table

Language

An incompatibility is a piece of code that can be compiled with Scala 2.13 but not with Scala 3. Migrating a codebase involves finding and fixing all the incompatibilities of the source code. On rare occasions we can also have a runtime incompatibility: a piece of code that behaves differently at runtime.

In this page we propose a classification of the known incompatibilities. Each incompatibility is described by:

  • Its short name with a link towards the detailed description and proposed solutions
  • Whether the Scala 2.13 compiler emits a deprecation or a feature warning
  • The existence of a Scala 3 migration rule for it
  • The existence of a Scalafix rule that can fix it

Scala 2.13 deprecations and feature warnings

Run the 2.13 compilation with -Xsource:3 to locate those incompatibilities in the code.

Scala 3 migration versus Scalafix rewrites

The Scala 3 migration mode comes out-of-the-box. On the contrary, Scalafix is a tool that must be installed and configured manually. However Scalafix has its own advantages:

  • It runs on Scala 2.13.
  • It is composed of individual rules that you can apply one at a time.
  • It is easily extensible by adding custom rules.

Syntactic Changes

Some of the old syntax is not supported anymore.

Incompatibility Scala 2.13 Scala 3 Migration Rewrite Scalafix Rule
Restricted keywords    
Procedure syntax Deprecation
Parentheses around lambda parameter    
Open brace indentation for passing an argument    
Wrong indentation      
_ as a type parameter      
+ and - as type parameters      

Dropped Features

Some features are dropped to simplify the language.

Incompatibility Scala 2.13 Scala 3 Migration Rewrite Scalafix Rule
Symbol literals Deprecation  
do-while construct    
Auto-application Deprecation
Value eta-expansion Deprecation
any2stringadd conversion Deprecation  
Early initializer Deprecation    
Existential type Feature warning    

Contextual Abstractions

The redesign of contextual abstractions brings some well defined incompatibilities.

Incompatibility Scala 2.13 Scala 3 Migration Rewrite Scalafix Rule Runtime Incompatibility
Type of implicit def      
Implicit views       Possible
View bounds Deprecation      
Ambiguous conversion on A and => A        

Furthermore we have changed the implicit resolution rules so that they are more useful and less surprising. The new rules are described here.

Because of these changes, the Scala 3 compiler could possibly fail at resolving some implicit parameters of existing Scala 2.13 code.

Other Changed Features

Some other features are simplified or restricted to make the language easier, safer or more consistent.

Incompatibility Scala 3 Migration Rewrite
Inheritance shadowing
Non-private constructor in private class Migration Warning
Abstract override  
Case class companion  
Explicit call to unapply  
Invisible bean property  
=>T as type argument  
Wildcard type argument  

Type Checker

The Scala 2.13 type checker is unsound in some specific cases. This can lead to surprising runtime errors in places we would not expect. Scala 3 being based on stronger theoretical foundations, these unsoundness bugs in the type checker are now fixed.

Incompatibility
Variance checks
Pattern matching

Type Inference

Some specific type inference rules have changed between Scala 2.13 and Scala 3.

Incompatibility
Return type of override method
Reflective type

Also we have improved the type inference algorithm by redesigning it entirely. This fundamental change leads to a few incompatibilities:

  • A different type can be inferred
  • A new type-checking error can appear

It is always good practice to write the result types of all public values and methods explicitly. It prevents the public API of your library from changing with the Scala version, because of different inferred types.

This can be done prior to the Scala 3 migration by using the ExplicitResultTypes rule in Scalafix.

Macros

The Scala 3 compiler is not able to expand Scala 2.13 macros. Under such circumstances it is necessary to re-implement the Scala 2.13 macros using the new Scala 3 metaprogramming features.

You can go back to the Metaprogramming page to learn about the new metaprogramming features.

Contributors to this page: