Skip to content

Commit 85d3a30

Browse files
committed
Add Inferred return type of an override method
1 parent ad3b9dc commit 85d3a30

File tree

7 files changed

+85
-4
lines changed

7 files changed

+85
-4
lines changed

docs/incompatibilities/incompatibility-table.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ Some features are simplified or restricted to make the language easier and safer
8383
|[Invisible Bean Property](other-changed-features.md#invisible-bean-property)|||||
8484
|[Unsoundness fixes in variance checks](other-changed-features.md#unsoundness-fixes-in-variance-checks)|||||
8585
|[Unsoundness fixes in pattern matching](other-changed-features.md#unsoundness-fixes-in-pattern-matching)|||||
86+
|[Inferred return type of an override method](other-changed-features.md#inferred-return-type-of-an-override-method)|||||
8687

8788
### Implicit Resolution
8889

docs/incompatibilities/other-changed-features.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ title: Other Changed Features
3535

3636
```scala mdoc:file:incompat-30/pattern-match/README.md
3737
```
38+
39+
```scala mdoc:file:incompat-30/infer-return-type/README.md
40+
```
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
## Inferred return type of an override method
2+
3+
In Scala 2.13 the return type of an override method can be inferred from the left hand side, whereas in Scala 3 it would be inherited from the base method.
4+
5+
```scala
6+
class Parent {
7+
def foo: Foo = new Foo
8+
}
9+
10+
class Child extends Parent {
11+
override def foo = new RichFoo(super.foo)
12+
}
13+
```
14+
15+
In this example, `Child#foo` returns a `RichFoo` in its Scala 2.13 signature but a `Foo` in its Scala 3 signature.
16+
It can lead to compiler errors as demonstrated below.
17+
18+
```scala
19+
class Foo
20+
class RichFoo(foo: Foo) extends Foo {
21+
def show: String = ""
22+
}
23+
24+
class Parent {
25+
def foo = new Foo
26+
}
27+
28+
class Child extends Parent {
29+
override def foo = new RichFoo(super.foo)
30+
}
31+
32+
object Test {
33+
(new Child).foo.show // Scala 3 error: value show is not a member of Foo
34+
}
35+
```
36+
37+
In some rare cases involving implicit conversions and runtime casting it could even cause an runtime failure.
38+
39+
The solution is to make the return type of the override method explicit:
40+
41+
```diff
42+
class Child extends Parent {
43+
- override def foo = new RichFoo(super.foo)
44+
+ override def foo: RichFoo = new RichFoo(super.foo)
45+
}
46+
```
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class Foo
2+
class RichFoo(foo: Foo) extends Foo {
3+
def show: String = ""
4+
}
5+
6+
class Parent {
7+
def foo: Foo = new Foo
8+
}
9+
10+
class Child extends Parent {
11+
override def foo = new RichFoo(super.foo)
12+
}
13+
14+
object Test {
15+
(new Child).foo.show
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class Foo
2+
class RichFoo(foo: Foo) extends Foo {
3+
def show: String = ""
4+
}
5+
6+
class Parent {
7+
def foo: Foo = new Foo
8+
}
9+
10+
class Child extends Parent {
11+
override def foo: RichFoo = new RichFoo(super.foo)
12+
}
13+
14+
object Test {
15+
(new Child).foo.show
16+
}

incompat.sbt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ lazy val otherIncompats = Seq[ProjectReference](
121121
viewBound,
122122
caseClassCompanion,
123123
patternMatch,
124-
`bean-property`
124+
`bean-property`,
125+
`infer-return-type`
125126
)
126127

127128
// Syntactic incompatibilities
@@ -144,6 +145,7 @@ lazy val reflectiveCall = project.in(file("incompat-30/reflective-call")).incomp
144145
lazy val caseClassCompanion = project.in(file("incompat-30/case-class-companion")).incompat30Settings
145146
lazy val patternMatch = project.in(file("incompat-30/pattern-match")).incompat30Settings
146147
lazy val `bean-property` = project.in(file("incompat-30/bean-property")).incompat30Settings
148+
lazy val `infer-return-type` = project.in(file("incompat-30/infer-return-type")).incompat30Settings
147149

148150
// Contextual abstraction incompatibilities
149151
lazy val ambiguousConversion =

website/i18n/en.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
"compatibility/classpath": {
99
"title": "Classpath Level"
1010
},
11-
"get-started": {
12-
"title": "Introduction"
13-
},
1411
"compatibility/metaprogramming": {
1512
"title": "Metaprogramming"
1613
},

0 commit comments

Comments
 (0)