The two incompatibilities described in this page are intentional changes in the type inference rules.
Other incompatibilities could be caused by the replacement of the type inference algorithm. The new algorithm is better than the old one, but sometime it can fail where Scala 2.13 would succeed:
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.
Return Type of an Override Method
In Scala 3 the return type of an override method is inferred by inheritance from the base method, whereas in Scala 2.13 it is inferred from the left hand side of the override method.
class Foo
class RichFoo(foo: Foo) extends Foo {
def show: String = ""
}
class Parent {
def foo: Foo = new Foo
}
class Child extends Parent {
override def foo = new RichFoo(super.foo)
}
In this example, Child#foo
returns a RichFoo
in Scala 2.13 but a Foo
in Scala 3.
It can lead to compiler errors as demonstrated below.
(new Child).foo.show // Scala 3 error: value show is not a member of Foo
In some rare cases involving implicit conversions and runtime casting it could even cause a runtime failure.
The solution is to make the return type of the override method explicit so that it matches what is inferred in 2.13:
Reflective Type
Scala 2 reflective calls are dropped and replaced by the broader Programmatic Structural Types.
Scala 3 can imitate Scala 2 reflective calls by making scala.reflect.Selectable.reflectiveSelectable
available wherever scala.language.reflectiveCalls
is imported.
import scala.language.reflectiveCalls
val foo = new {
def bar: Unit = ???
}
However the Scala 3 compiler does not infer structural types by default.
It infers the type Object
for foo
instead of { def bar: Unit }
.
Therefore, the following structural selection fails to compile:
foo.bar // Error: value bar is not a member of Object
The straightforward solution is to explicitly write down the structural type.