Description
in Scala 2, one annotates the scrutinee:
scala 2.13.4> val Some(x) = Option(3)
^
warning: match may not be exhaustive.
It would fail on the following input: None
val x: Int = 3
scala 2.13.4> val Some(x) = Option(3): @unchecked
val x: Int = 3
whereas in Scala 3.0.0-M2 under -source:3.1
one must annotate the pattern, while annotating the scrutinee is ignored:
scala> val Some(x) = Option(3)
1 |val Some(x) = Option(3)
| ^^^^^^^
|pattern's type Some[Int] is more specialized than the right hand side expression's type Option[Int]
|
|If the narrowing is intentional, this can be communicated by writing `: @unchecked` after the full pattern.
scala> val Some(x) = Option(3): @unchecked
1 |val Some(x) = Option(3): @unchecked
| ^^^^^^^
|pattern's type Some[Int] is more specialized than the right hand side expression's type Option[Int] @unchecked
|
|If the narrowing is intentional, this can be communicated by writing `: @unchecked` after the full pattern.
scala> val Some(x): @unchecked = Option(3)
val x: Int = 3
Scala 3's behavior is as documented at https://dotty.epfl.ch/docs/reference/changed-features/pattern-bindings.html :
Sometimes one wants to decompose data anyway, even though the pattern is refutable. For instance, if at some point one knows that a list
elems
is non-empty one might want to decompose it like this:val first :: rest = elems // errorThis works in Scala 2. In fact it is a typical use case for Scala 2's rules. But in Scala 3.1 it will give a type error. One can avoid the error by marking the pattern with an @unchecked annotation:
val first :: rest : @unchecked = elems // OKThis will make the compiler accept the pattern binding. It might give an error at runtime instead, if the underlying assumption that
elems
can never be empty is wrong.
but I suggest that Scala 3 should adopt the Scala 2 convention, because:
- it is more consistent with
match
; one also annotates the scrutinee withmatch
, like(foo: @unchecked) match ...
- we want to support cross-building between 2 and 3, and 2's style is the established precedent
(this came up at scala/bug#12245)
This became more important with the release of Scala 2.13.4, where improved exhaustivity checking has sent many users scurrying to add @unchecked
to their matches.