You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _overviews/scala3-migration/incompat-other-changes.md
+97-56
Original file line number
Diff line number
Diff line change
@@ -25,14 +25,18 @@ Some other features are simplified or restricted to make the language easier, sa
25
25
An inherited member, from a parent trait or class, can shadow an identifier defined in an outer scope.
26
26
That pattern is called inheritance shadowing.
27
27
28
-
```scala
28
+
{% tabs shared-inheritance_1 %}
29
+
{% tab 'Scala 2 and 3' %}
30
+
~~~scala
29
31
objectB {
30
32
valx=1
31
33
classCextendsA {
32
34
println(x)
33
35
}
34
36
}
35
-
```
37
+
~~~
38
+
{% endtab %}
39
+
{% endtabs %}
36
40
37
41
For instance, in this preceding piece of code, the `x` term in C can refer to the `x` member defined in the outer class `B` or it can refer to a `x` member of the parent class `A`.
38
42
You cannot know until you go to the definition of `A`.
@@ -42,8 +46,9 @@ This is known for being error prone.
42
46
That's why, in Scala 3, the compiler requires disambiguation if the parent class `A` does actually have a member `x`.
43
47
44
48
It prevents the following piece of code from compiling.
45
-
46
-
```scala
49
+
{% tabs scala-2-inheritance_2 %}
50
+
{% tab 'Scala 2 Only' %}
51
+
~~~scala
47
52
classA {
48
53
valx=2
49
54
}
@@ -54,8 +59,11 @@ object B {
54
59
println(x)
55
60
}
56
61
}
57
-
```
62
+
~~~
63
+
{% endtab %}
64
+
{% endtabs %}
58
65
66
+
But if you try to compile with Scala 3 you should see an error of the same kind as:
| non-private constructor Bar in class Bar refers to private class Bar
88
99
| in its type signature (): foo.Foo.Bar
89
-
```
100
+
{% endhighlight %}
90
101
91
102
The [Scala 3 migration compilation](tooling-migration-mode.html) warns about this but no automatic rewrite is provided.
92
103
@@ -97,8 +108,9 @@ The solution is to make the constructor private, since the class is private.
97
108
In Scala 3, overriding a concrete def with an abstract def causes subclasses to consider the def abstract, whereas in Scala 2 it was considered as concrete.
98
109
99
110
In the following piece of code, the `bar` method in `C` is considered concrete by the Scala 2.13 compiler but abstract by the Scala 3 compiler, causing the following error.
100
-
101
-
```scala
111
+
{% tabs scala-2-abstract_1 %}
112
+
{% tab 'Scala 2 Only' %}
113
+
~~~scala
102
114
traitA {
103
115
defbar(x: Int):Int= x +3
104
116
}
@@ -107,8 +119,10 @@ trait B extends A {
107
119
defbar(x: Int):Int
108
120
}
109
121
110
-
classCextendsB// Error: class C needs to be abstract, since def bar(x: Int): Int is not defined
111
-
```
122
+
classCextendsB// In Scala 3, Error: class C needs to be abstract, since def bar(x: Int): Int is not defined
123
+
~~~
124
+
{% endtab %}
125
+
{% endtabs %}
112
126
113
127
This behavior was decided in [Dotty issue #4770](https://github.com/lampepfl/dotty/issues/4770).
114
128
@@ -120,17 +134,20 @@ The companion object of a case class does not extend any of the `Function{0-23}`
120
134
In particular, it does not inherit their methods: `tupled`, `curried`, `andThen`, `compose`...
121
135
122
136
For instance, this is not permitted anymore:
123
-
124
-
```scala
137
+
{% tabs scala-2-companion_1 %}
138
+
{% tab 'Scala 2 Only' %}
139
+
~~~scala
125
140
caseclassFoo(x: Int, b: Boolean)
126
141
127
142
Foo.curried(1)(true)
128
143
Foo.tupled((2, false))
129
-
```
144
+
~~~
145
+
{% endtab %}
146
+
{% endtabs %}
130
147
131
148
A cross-compiling solution is to explicitly eta-expand the method `Foo.apply`.
132
-
133
149
{% highlight diff %}
150
+
134
151
-Foo.curried(1)(true)
135
152
+(Foo.apply _).curried(1)(true)
136
153
@@ -139,13 +156,16 @@ A cross-compiling solution is to explicitly eta-expand the method `Foo.apply`.
139
156
{% endhighlight %}
140
157
141
158
Or, for performance reasons, you can introduce an intermediate function value.
142
-
143
-
```scala
159
+
{% tabs scala-3-companion_2 %}
160
+
{% tab 'Scala 2 and 3' %}
161
+
~~~scala
144
162
valfooCtr: (Int, Boolean) =>Foo= (x, b) =>Foo(x, b)
145
163
146
164
fooCtr.curried(1)(true)
147
165
fooCtr.tupled((2, false))
148
-
```
166
+
~~~
167
+
{% endtab %}
168
+
{% endtabs %}
149
169
## Explicit Call to `unapply`
150
170
151
171
In Scala, case classes have an auto-generated extractor method, called `unapply` in their companion object.
@@ -156,36 +176,48 @@ The new signature is option-less (see the new [Pattern Matching]({{ site.scala3r
156
176
Note that this problem does not affect user-defined extractors, whose signature stays the same across Scala versions.
157
177
158
178
Given the following case class definition:
159
-
160
-
```scala
179
+
{% tabs shared-unapply_1 %}
180
+
{% tab 'Scala 2 and 3' %}
181
+
~~~scala
161
182
caseclassLocation(lat: Double, long: Double)
162
-
```
183
+
~~~
184
+
{% endtab %}
185
+
{% endtabs %}
163
186
164
187
The Scala 2.13 compiler generates the following `unapply` method:
The getter and setter methods generated by the `BeanProperty` annotation are now invisible in Scala 3 because their primary use case is the interoperability with Java frameworks.
201
233
202
-
For instance, in the below example:
203
-
204
-
```scala
234
+
For instance, the below Scala 2 code would fail to compile in Scala 3:
235
+
{% tabs scala-2-bean_1 %}
236
+
{% tab 'Scala 2 Only' %}
237
+
~~~scala
205
238
classPojo() {
206
239
@BeanPropertyvarfooBar:String=""
207
240
}
208
241
209
242
valpojo=newPojo()
210
243
211
-
pojo.setFooBar("hello") // [E008] Not Found Error: value setFooBar is not a member of Pojo
244
+
pojo.setFooBar("hello") // [E008] In Scala 3, Not Found Error: value setFooBar is not a member of Pojo
212
245
213
-
println(pojo.getFooBar()) // [E008] Not Found Error: value getFooBar is not a member of Pojo
214
-
```
246
+
println(pojo.getFooBar()) // [E008] In Scala 3, Not Found Error: value getFooBar is not a member of Pojo
247
+
~~~
248
+
{% endtab %}
249
+
{% endtabs %}
215
250
216
-
The solution is to call the more idiomatic `pojo.fooBar` getter and setter.
251
+
In Scala 3, the solution is to call the more idiomatic `pojo.fooBar` getter and setter.
217
252
218
253
{% highlight diff %}
219
254
val pojo = new Pojo()
@@ -233,7 +268,7 @@ This decision is explained in [this comment](https://github.com/lampepfl/dotty/b
233
268
234
269
For instance, it is not allowed to pass a function of type `Int => (=> Int) => Int` to the `uncurried` method since it would assign `=> Int` to the type parameter `T2`.
235
270
236
-
```
271
+
{% highlight text %}
237
272
-- [E134] Type Mismatch Error: src/main/scala/by-name-param-type-infer.scala:3:41
238
273
3 | val g: (Int, => Int) => Int = Function.uncurried(f)
239
274
| ^^^^^^^^^^^^^^^^^^
@@ -244,7 +279,7 @@ For instance, it is not allowed to pass a function of type `Int => (=> Int) => I
244
279
| [T1, T2, T3, R](f: T1 => T2 => T3 => R): (T1, T2, T3) => R
245
280
| [T1, T2, R](f: T1 => T2 => R): (T1, T2) => R
246
281
|match arguments ((Test.f : Int => (=> Int) => Int))
247
-
```
282
+
{% endhighlight %}
248
283
249
284
The solution depends on the situation. In the given example, you can either:
250
285
- define your own `uncurried` method with the appropriate signature
@@ -254,15 +289,18 @@ The solution depends on the situation. In the given example, you can either:
254
289
255
290
Scala 3 cannot reduce the application of a higher-kinded abstract type member to the wildcard argument.
256
291
257
-
For instance, the following example does not compile.
258
-
259
-
```scala
292
+
For instance, the below Scala 2 code would fail to compile in Scala 3:
293
+
{% tabs scala-2-wildcard_1 %}
294
+
{% tab 'Scala 2 Only' %}
295
+
~~~scala
260
296
traitExample {
261
297
typeFoo[A]
262
298
263
-
deff(foo: Foo[_]):Unit// [E043] Type Error: unreducible application of higher-kinded type Example.this.Foo to wildcard arguments
299
+
deff(foo: Foo[_]):Unit// [E043] In Scala 3, Type Error: unreducible application of higher-kinded type Example.this.Foo to wildcard arguments
264
300
}
265
-
```
301
+
~~~
302
+
{% endtab %}
303
+
{% endtabs %}
266
304
267
305
We can fix this by using a type parameter:
268
306
@@ -272,10 +310,13 @@ We can fix this by using a type parameter:
272
310
{% endhighlight %}
273
311
274
312
But this simple solution does not work when `Foo` is itself used as a type argument.
275
-
276
-
```scala
313
+
{% tabs scala-2-wildcard_2 %}
314
+
{% tab 'Scala 2 Only' %}
315
+
~~~scala
277
316
defg(foos: Seq[Foo[_]]):Unit
278
-
```
317
+
~~~
318
+
{% endtab %}
319
+
{% endtabs %}
279
320
280
321
In such case, we can use a wrapper class around `Foo`:
281
322
@@ -284,4 +325,4 @@ In such case, we can use a wrapper class around `Foo`:
0 commit comments