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
| Jan 19th 2024 | Clarification about current @unchecked behavior |
17
18
18
19
## Summary
19
20
@@ -57,6 +58,7 @@ Having to wrap the `@unchecked` in parentheses requires editing in two places, a
57
58
Nominally, the purpose of the annotation is to silence warnings (_from the [API docs](https://www.scala-lang.org/api/3.3.1/scala/unchecked.html#)_):
58
59
> An annotation to designate that the annotated entity should not be considered for additional compiler checks.
59
60
61
+
_The exact meaning of this description is open to interpretation, leading to differences between Scala 2.13 and Scala 3.x. See the [misinterpretation](#misinterpretation-of-unchecked) annex for more._
60
62
61
63
62
64
In the following code however, the word `unchecked` is a misnomer, so could be confused for another meaning by an inexperienced user:
@@ -159,6 +161,88 @@ The new method elaborates to an annotated expression before the associated patte
159
161
160
162
3) Should the `RuntimeCheck` annotation be in the `scala.annotation.internal` package?
161
163
164
+
### Misinterpretation of unchecked
165
+
166
+
We would further like to highlight that the `unchecked` annotation is unspecified except for its imprecise API documentation. This leads to a crucial difference in its behavior between Scala 2.13 and the latest Scala 3.3.1 release.
167
+
168
+
#### Scala 3 semantics
169
+
170
+
Say you have the following:
171
+
```scala
172
+
valxs=List(1:Any)
173
+
```
174
+
175
+
The following expression in Scala 3.3.1 yields two warnings:
|the typetestfor::[Int] cannot be checked at runtime because its typearguments can't be determined from List[Any]
197
+
```
198
+
199
+
using `@unchecked` on `xs` has the effect of silencing any warnings that depend on checking `xs`, so no warnings will be emitted for the following change:
200
+
201
+
```scala
202
+
(xs: @unchecked) match {
203
+
caseis: ::[Int] => is.head
204
+
}
205
+
```
206
+
207
+
####Scala2.13 semantics
208
+
209
+
However, in Scala2.13, this will only silence the `match may not be exhaustive` warning, and the user will still see the `type test for ::[Int] cannot be checked at runtime` warning:
210
+
211
+
```scala
212
+
scala> (xs: @unchecked) match {
213
+
|caseis: ::[Int] => is.head
214
+
| } ^
215
+
On line 2:warning: non-variable typeargumentInt in typepattern scala.collection.immutable.::[Int] (the underlying of ::[Int]) is unchecked since it is eliminated by erasure
216
+
valres2:Int=1
217
+
```
218
+
219
+
####Aligning to Scala2.13 semantics with runtimeCheck
220
+
221
+
with`xs.runtimeCheck` we should still produce an unchecked warning for `case is: ::[Int] =>`
|the typetestfor::[Int] cannot be checked at runtime because its typearguments can't be determined from List[Any]
231
+
valres13:Int=1
232
+
```
233
+
This is because `xs.runtimeChecked` means trust the user aslongasthe pattern can be checked at runtime.
234
+
235
+
To fully avoid warnings, the `@unchecked` will be put on the typeargument:
236
+
```scala
237
+
scala> xs.runtimeChecked match {
238
+
|caseis: ::[Int@unchecked] => is.head
239
+
| }
240
+
valres14:Int=1
241
+
```
242
+
This has a small extra migration cost because if the scrutinee changes from `(xs: @unchecked)` to `xs.runtimeCheck` now some individual cases might need to add `@unchecked` on typearguments to avoid creating new warnings - however this cost is offset by perhaps revealing unsafe patterns previously unaccounted for.
243
+
244
+
Once again `@nowarn` can be used to fully restore any old behavior
245
+
162
246
##Alternatives
163
247
164
248
1) make `runtimeCheck` a method on `Any` that returns the receiver (not inline). The compiler would check for presence of a call to this method when deciding to perform static checking of pattern exhaustivity. This idea was criticised for being brittle with respect to refactoring, or automatic code transformations via macro.
0 commit comments