Closed
Description
One of the stated goals of opaque types is to statically enforce invariants about some values without wrapping them. To achieve this, we must control what values are allowed to get converted into and out of the opaque type.
Matching on opaque types is currently allowed, and break this. For instance, it is possible to convert an immutable array into a mutable one by matching on it, which defeats its purpose.
minimized code
@main def main = {
// conversion into the opaque type:
val arr = Array(1,2,3)
val imm0: IArray[Int] // supposedly immutable
= oops(arr)
println(imm0(0)) // 1
arr(0) = 0
println(imm0(0)) // 0, the value has changed!
// conversion out of the opaque type:
val imm1 = IArray(1,2,3) // supposedly immutable
println(imm1(0)) // 1
imm1 match {
case a: Array[Int] =>
a(0) = 0
}
println(imm1(0)) // 0
}
def oops(a: Array[Int]): IArray[Int] = a match {
case a: IArray[Int] => a
}
https://scastie.scala-lang.org/hV46dfNWR6iTP2uLIMfS2g
expectation
Both matches should be rejected, or at the very least give warnings.