Took `strictEqualityPatternMatching` and `subCases` for a test ride.

`strictEqualityPatternMatching` works pretty good. also across `sum`/`enum` types and `union` types. Nice!

`subCases` interfered with exhaustivity checks. Maybe I am doing something wrong. `subCases` for `sum` types to tease them out separately would be solid.

`Integer` pattern match was deemed exhaustive when shouldn't have been. (will do some more tests here.)


https://scastie.scala-lang.org/CE9rW97WRSSnFkQsP83TKg

#scala #scastie

Scastie - An interactive playground for Scala.

//> using scala 3.8.1 //> using option -language:experimental.saferExceptions //> using option -language:experimental.captureChecking // Describes computations that can fail with error `E` final class CanThrow[-E] // Internal exception used to jump to the catch block private final case class Break[E](value: E, label: CanThrow[E]) extends RuntimeException(null, null, false, false) // Library version of `throw` def failWith[A](a: A)(using l: CanThrow[A]): Nothing = throw Break(a, l) // Provides a way to catch errors. object Catch: def apply[A, E](op: CanThrow[E] ?=> A)(default: E => A): A = given label: CanThrow[E] = new CanThrow() try op catch case Break(value, `label`) => default(value) // Error types sealed trait Error extends Exception case class NegativeNumber(i: Int) extends Error case class InvalidInput(s: String) extends Error // sqrt can fail if its argument is negative. def sqrt(i: Int)(using CanThrow[NegativeNumber]): Double = if i >= 0 then math.sqrt(i) else failWith(NegativeNumber(i)) // parse can fail if its argument is not a valid int. def parse(s: String)(using CanThrow[InvalidInput]): Int = scala.util.Try(s.toInt).getOrElse(failWith(InvalidInput(s))) // Composing both widens the type of the error to the parent of `NegativeNumber` and `InvalidInput`. def composed(s: String)(using CanThrow[Error]): Double = sqrt(parse(s)) // I like this better - auto-widening is nice, but note how `Error` is not sealed: `composedSubtype` // forces me to deal with error cases that don't exist. def composedBetter(s: String)(using CanThrow[NegativeNumber | InvalidInput] ): Double = sqrt(parse(s)) def printSqrt(s: String): Unit = Catch(println(composedBetter(s))): case NegativeNumber(i) => println(s"Negative number: $i") case InvalidInput(s) => println(s"Invalid input: '$s'") @main def run = printSqrt("abc") printSqrt("-4") printSqrt("4")

@ppurang interesting findings.

I'm not part of Scala 3 team, but would you mind reporting the exhaustivity check bug to https://github.com/scala/scala3/issues plz?

Using language.experimental.subCases interferes with pattern match exhaustivity checking · Issue #25234 · scala/scala3

Compiler version Scala CLI version: 1.12.2 Scala version (default): 3.8.1 Minimized code //> using scala 3.8.1 //> using options -deprecation -feature -Wunused:all -Werror import language.experimen...

GitHub