Skip to content

Commit abdec58

Browse files
authored
Merge pull request #111 from scala/mbovel-patch-1
Rename `.runtimeCheck` to `.runtimeChecked`
2 parents 9efca18 + e97acd7 commit abdec58

File tree

1 file changed

+16
-15
lines changed

1 file changed

+16
-15
lines changed

content/replace-nonsensical-unchecked-annotation.md

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ title: SIP-57 - Replace non-sensical @unchecked annotations
1515
|---------------|--------------------|
1616
| Dec 8th 2023 | Initial Draft |
1717
| Jan 19th 2024 | Clarification about current @unchecked behavior |
18+
| Jun 3rd 2025 | Rename `.runtimeCheck` to `.runtimeChecked` |
1819

1920
## Summary
2021

2122
We propose to replace the mechanism to silence warnings for "unchecked" patterns, in the cases where silencing the warning will still result in the pattern being checked at runtime.
2223

23-
Currently, a user can silence warnings that a scrutinee may not be matched by a pattern, by annotating the scrutinee with the `@unchecked` annotation. This SIP proposes to use a new annotation `@RuntimeCheck` to replace `@unchecked` for this purpose. For convenience, an extension method will be added to `Predef` that marks the receiver with the annotation (used as follows: `foo.runtimeCheck`). Functionally it behaves the same as the old annotation, but improves readability at the callsite.
24+
Currently, a user can silence warnings that a scrutinee may not be matched by a pattern, by annotating the scrutinee with the `@unchecked` annotation. This SIP proposes to use a new annotation `@RuntimeCheck` to replace `@unchecked` for this purpose. For convenience, an extension method will be added to `Predef` that marks the receiver with the annotation (used as follows: `foo.runtimeChecked`). Functionally it behaves the same as the old annotation, but improves readability at the callsite.
2425

2526
## Motivation
2627

@@ -92,15 +93,15 @@ In all usages where the compiler looks for `@unchecked` for this purpose, we ins
9293

9394
By placing the annotation in the `internal` package, we communicate that the user is not meant to directly use the annotation.
9495

95-
Instead, for convenience, we provide an extension method `Predef.runtimeCheck`, which can be applied to any expression.
96+
Instead, for convenience, we provide an extension method `Predef.runtimeChecked`, which can be applied to any expression.
9697

9798
The new usage to assert that a pattern is checked at runtime then becomes as follows:
9899
```scala
99100
def xs: List[Any] = ???
100-
val y :: ys = xs.runtimeCheck
101+
val y :: ys = xs.runtimeChecked
101102
```
102103

103-
We also make `runtimeCheck` a transparent inline method. This ensures that the elaboration of the method defines its semantics. (i.e. `runtimeCheck` is not meaningful because it is immediately inlined at type-checking).
104+
We also make `runtimeChecked` a transparent inline method. This ensures that the elaboration of the method defines its semantics. (i.e. `runtimeChecked` is not meaningful because it is immediately inlined at type-checking).
104105

105106
### Specification
106107

@@ -113,7 +114,7 @@ import scala.annotation.internal.RuntimeCheck
113114

114115
object Predef:
115116
extension [T](x: T)
116-
transparent inline def runtimeCheck: x.type =
117+
transparent inline def runtimeChecked: x.type =
117118
x: @RuntimeCheck
118119
```
119120

@@ -128,8 +129,8 @@ Considering backwards source compatibility, the following situation will change:
128129
package example
129130

130131
extension (predef: scala.Predef.type)
131-
transparent inline def runtimeCheck[T](x: T): x.type =
132-
println("fake runtimeCheck")
132+
transparent inline def runtimeChecked[T](x: T): x.type =
133+
println("fake runtimeChecked")
133134
x
134135
```
135136
```scala
@@ -138,16 +139,16 @@ package example
138139

139140
@main def Test =
140141
val xs = List[Any](1,2,3)
141-
val y :: ys = Predef.runtimeCheck(xs)
142+
val y :: ys = Predef.runtimeChecked(xs)
142143
assert(ys == List(2, 3))
143144
```
144145

145-
Previously this code would print `fake runtimeCheck`, however with the proposed change then recompiling this code will _succeed_ and no longer will print.
146+
Previously this code would print `fake runtimeChecked`, however with the proposed change then recompiling this code will _succeed_ and no longer will print.
146147

147148
Potentially we could mitigate this if necessary with a migration warning when the new method is resolved (`@experimental` annotation would be a start)
148149

149150

150-
In general however, the new `runtimeCheck` method will not change any previously linking method without causing an ambiguity compilation error.
151+
In general however, the new `runtimeChecked` method will not change any previously linking method without causing an ambiguity compilation error.
151152

152153
### Other concerns
153154

@@ -216,9 +217,9 @@ On line 2: warning: non-variable type argument Int in type pattern scala.collect
216217
val res2: Int = 1
217218
```
218219

219-
#### Aligning to Scala 2.13 semantics with runtimeCheck
220+
#### Aligning to Scala 2.13 semantics with `runtimeChecked`
220221

221-
with `xs.runtimeCheck` we should still produce an unchecked warning for `case is: ::[Int] =>`
222+
with `xs.runtimeChecked` we should still produce an unchecked warning for `case is: ::[Int] =>`
222223
```scala
223224
scala> xs.runtimeChecked match {
224225
| case is: ::[Int] => is.head
@@ -239,15 +240,15 @@ scala> xs.runtimeChecked match {
239240
| }
240241
val res14: Int = 1
241242
```
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 type arguments to avoid creating new warnings - however this cost is offset by perhaps revealing unsafe patterns previously unaccounted for.
243+
This has a small extra migration cost because if the scrutinee changes from `(xs: @unchecked)` to `xs.runtimeChecked` now some individual cases might need to add `@unchecked` on type arguments to avoid creating new warnings - however this cost is offset by perhaps revealing unsafe patterns previously unaccounted for.
243244

244245
Once again `@nowarn` can be used to fully restore any old behavior
245246

246247
## Alternatives
247248

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.
249+
1) make `runtimeChecked` 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.
249250

250-
2) `runtimeCheck` should elaborate to code that matches the expected type, e.g. to heal `t: Any` to `Int` when the expected type is `Int`. The problem is that this is not useful for patterns that can not be runtime checked by type alone. Also, it implies a greater change to the spec, because now `runtimeCheck` would have to be specially treated.
251+
2) `runtimeChecked` should elaborate to code that matches the expected type, e.g. to heal `t: Any` to `Int` when the expected type is `Int`. The problem is that this is not useful for patterns that can not be runtime checked by type alone. Also, it implies a greater change to the spec, because now `runtimeChecked` would have to be specially treated.
251252

252253
## Related work
253254

0 commit comments

Comments
 (0)