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
+56-89
Original file line number
Diff line number
Diff line change
@@ -108,8 +108,8 @@ The solution is to make the constructor private, since the class is private.
108
108
109
109
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.
110
110
111
-
{% tabs scala-3-abstract_1 %}
112
-
{% tab 'Scala 3 Only' %}
111
+
{% tabs scala-2-abstract_1 %}
112
+
{% tab 'Scala 2 Only' %}
113
113
114
114
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.
115
115
~~~scala
@@ -121,7 +121,7 @@ trait B extends A {
121
121
defbar(x: Int):Int
122
122
}
123
123
124
-
classCextendsB// Error: class C needs to be abstract, since def bar(x: Int): Int is not defined
124
+
classCextendsB//In Scala 3, Error: class C needs to be abstract, since def bar(x: Int): Int is not defined
125
125
~~~
126
126
127
127
This behavior was decided in [Dotty issue #4770](https://github.com/lampepfl/dotty/issues/4770).
@@ -135,8 +135,8 @@ An easy fix is simply to remove the abstract def, since in practice it had no ef
135
135
The companion object of a case class does not extend any of the `Function{0-23}` traits anymore.
136
136
In particular, it does not inherit their methods: `tupled`, `curried`, `andThen`, `compose`...
137
137
138
-
{% tabs companion_1 class=tabs-scala-version %}
139
-
{% tab 'Scala 2' for=companion_1 %}
138
+
{% tabs scala-2-companion_1 %}
139
+
{% tab 'Scala 2 Only' %}
140
140
141
141
For instance, this is not permitted anymore:
142
142
~~~scala
@@ -146,21 +146,23 @@ Foo.curried(1)(true)
146
146
Foo.tupled((2, false))
147
147
~~~
148
148
{% endtab %}
149
-
{% tab 'Scala 3' for=companion_1 %}
149
+
{% endtabs %}
150
150
151
151
A cross-compiling solution is to explicitly eta-expand the method `Foo.apply`.
152
-
~~~scala
153
-
caseclassFoo(x: Int, b: Boolean)
152
+
{% highlight diff %}
154
153
155
-
(Foo.apply _).curried(1)(true)
156
-
(Foo.apply _).tupled((2, false))
157
-
~~~
154
+
-Foo.curried(1)(true)
155
+
+(Foo.apply _).curried(1)(true)
158
156
159
-
Or, for performance reasons, you can introduce an intermediate function value.
157
+
-Foo.tupled((2, false))
158
+
+(Foo.apply _).tupled((2, false))
159
+
{% endhighlight %}
160
160
161
-
~~~scala
162
-
caseclassFoo(x: Int, b: Boolean)
161
+
{% tabs scala-3-companion_2 %}
162
+
{% tab 'Scala 3 Only' %}
163
163
164
+
Or, for performance reasons, you can introduce an intermediate function value.
165
+
~~~scala
164
166
valfooCtr: (Int, Boolean) =>Foo= (x, b) =>Foo(x, b)
165
167
166
168
fooCtr.curried(1)(true)
@@ -208,45 +210,39 @@ object Location {
208
210
defunapply(location: Location):Location= location
209
211
}
210
212
~~~
211
-
212
-
Consequently the following code does not compile anymore.
213
-
~~~scala
214
-
deftuple(location: Location): (Int, Int) = {
215
-
Location.unapply(location).get // [E008] Not Found Error: value get is not a member of Location
216
-
}
217
-
~~~
218
213
{% endtab %}
219
214
{% endtabs %}
220
215
221
-
A possible solution is to use pattern binding:
222
-
223
-
{% tabs unaply_3 class=tabs-scala-version %}
224
-
{% tab 'Scala 2' for=unaply_3 %}
216
+
{% tabs scala-2-unapply_3 %}
217
+
{% tab 'Scala 2 Only' %}
225
218
219
+
Consequently the following code does not compile anymore in Scala 3.
226
220
~~~scala
227
221
deftuple(location: Location): (Int, Int) = {
228
-
Location.unapply(location).get
222
+
Location.unapply(location).get// [E008] In Scala 3, Not Found Error: value get is not a member of Location
229
223
}
230
224
~~~
231
225
{% endtab %}
232
-
{% tab 'Scala 3' for=unaply_3 %}
233
-
~~~scala
226
+
{% endtabs %}
227
+
228
+
A possible solution, in Scala 3, is to use pattern binding:
229
+
230
+
{% highlight diff %}
234
231
def tuple(location: Location): (Int, Int) = {
235
-
valLocation(lat, lon) = location
236
-
(lat, lon)
232
+
- Location.unapply(location).get
233
+
+ val Location(lat, lon) = location
234
+
+ (lat, lon)
237
235
}
238
-
~~~
239
-
{% endtab %}
240
-
{% endtabs %}
236
+
{% endhighlight %}
241
237
242
238
## Invisible Bean Property
243
239
244
240
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.
245
241
246
-
{% tabs scala-3-bean_1 %}
247
-
{% tab 'Scala 3 Only' %}
242
+
{% tabs scala-2-bean_1 %}
243
+
{% tab 'Scala 2 Only' %}
248
244
249
-
For instance, in the below example:
245
+
For instance, the below Scala 2 code would fail to compile in Scala 3:
250
246
251
247
~~~scala
252
248
classPojo() {
@@ -255,36 +251,24 @@ class Pojo() {
255
251
256
252
valpojo=newPojo()
257
253
258
-
pojo.setFooBar("hello") // [E008] Not Found Error: value setFooBar is not a member of Pojo
254
+
pojo.setFooBar("hello") // [E008] In Scala 3, Not Found Error: value setFooBar is not a member of Pojo
259
255
260
-
println(pojo.getFooBar()) // [E008] Not Found Error: value getFooBar is not a member of Pojo
256
+
println(pojo.getFooBar()) // [E008] In Scala 3, Not Found Error: value getFooBar is not a member of Pojo
261
257
~~~
262
258
{% endtab %}
263
259
{% endtabs %}
264
260
265
-
The solution is to call the more idiomatic `pojo.fooBar` getter and setter.
266
-
267
-
{% tabs bean_2 class=tabs-scala-version %}
268
-
{% tab 'Scala 2' for=bean_2 %}
261
+
In Scala 3, the solution is to call the more idiomatic `pojo.fooBar` getter and setter.
269
262
270
-
~~~scala
271
-
valpojo=newPojo()
272
-
273
-
pojo.setFooBar("hello")
274
-
275
-
println(pojo.getFooBar())
276
-
~~~
277
-
{% endtab %}
278
-
{% tab 'Scala 3' for=bean_2 %}
279
-
~~~scala
263
+
{% highlight diff %}
280
264
val pojo = new Pojo()
281
265
282
-
pojo.fooBar ="hello"
266
+
-pojo.setFooBar("hello")
267
+
+pojo.fooBar = "hello"
283
268
284
-
println(pojo.fooBar)
285
-
~~~
286
-
{% endtab %}
287
-
{% endtabs %}
269
+
-println(pojo.getFooBar())
270
+
+println(pojo.fooBar)
271
+
{% endhighlight %}
288
272
289
273
## `=> T` as Type Argument
290
274
@@ -315,40 +299,31 @@ The solution depends on the situation. In the given example, you can either:
315
299
316
300
Scala 3 cannot reduce the application of a higher-kinded abstract type member to the wildcard argument.
317
301
318
-
{% tabs scala-3-wildcard_1 %}
319
-
{% tab 'Scala 3 Only' %}
302
+
{% tabs scala-2-wildcard_1 %}
303
+
{% tab 'Scala 2 Only' %}
320
304
321
-
For instance, the following example does not compile.
305
+
For instance, the below Scala 2 code would fail to compile in Scala 3:
322
306
323
307
~~~scala
324
308
traitExample {
325
309
typeFoo[A]
326
310
327
-
deff(foo: Foo[_]):Unit// [E043] Type Error: unreducible application of higher-kinded type Example.this.Foo to wildcard arguments
311
+
deff(foo: Foo[_]):Unit// [E043] In Scala 3, Type Error: unreducible application of higher-kinded type Example.this.Foo to wildcard arguments
328
312
}
329
313
~~~
330
314
{% endtab %}
331
315
{% endtabs %}
332
316
333
317
We can fix this by using a type parameter:
334
318
335
-
{% tabs wildcard_2 class=tabs-scala-version %}
336
-
{% tab 'Scala 2' for=wildcard_2 %}
337
-
338
-
~~~scala
339
-
deff(foo: Foo[_]):Unit
340
-
~~~
341
-
{% endtab %}
342
-
{% tab 'Scala 3' for=wildcard_2 %}
343
-
~~~scala
344
-
deff[A](foo: Foo[A]):Unit
345
-
~~~
346
-
{% endtab %}
347
-
{% endtabs %}
319
+
{% highlight diff %}
320
+
-def f(foo: Foo[_]): Unit
321
+
+def f[A](foo: Foo[A]): Unit
322
+
{% endhighlight %}
348
323
349
324
But this simple solution does not work when `Foo` is itself used as a type argument.
350
-
{% tabs shared-wildcard_3 %}
351
-
{% tab 'Scala 2 and 3' %}
325
+
{% tabs scala-2-wildcard_2 %}
326
+
{% tab 'Scala 2 Only' %}
352
327
~~~scala
353
328
defg(foos: Seq[Foo[_]]):Unit
354
329
~~~
@@ -357,17 +332,9 @@ def g(foos: Seq[Foo[_]]): Unit
357
332
358
333
In such case, we can use a wrapper class around `Foo`:
0 commit comments