Alternative for type ascriptions after tuple patterns in Scala 3.3.0

I have a function similar to this one, matching on outputSize:

def size(
    outputSize: Int | Option[Int] | (Option[Int], Option[Int]) | (Int, Int)
): (Option[Int], Option[Int]) = outputSize match
  case x: Int                             => (Some(x), Some(x))
  case x: Option[Int]                     => (x, x)
  case (h, w): (Int, Int)                 => (Some(h), Some(w))
  case (h, w): (Option[Int], Option[Int]) => (h, w)

After upgrading to Scala 3.3, the last two cases trigger a warning:

Type ascriptions after patterns other than:
  * variable pattern, e.g. `case x: String =>`
  * number literal pattern, e.g. `case 10.5: Double =>`
are no longer supported. Remove the type ascription or move it to a separate variable pattern.

The first can be solved by moving the type ascription into the tuple match:

  case (h: Int, w: Int)                   => (Some(h), Some(w))

But that doesn’t work for the second one due to type erasure:

  case (h: Option[Int], w: Option[Int]) => (h, w)
the type test for Option[Int] cannot be checked at runtime because its type arguments can't be determined from Any

Perhaps I’m missing the obvious here, but I’m having difficulties matching on that latest case in Scala 3.3.0 without a warning. Any ideas?

1 Like

You could use the @unchecked annotation, so the last case would become

case (h: Option[Int@unchecked], w: Option[Int@unchecked]) => (h, w)
1 Like

I’m actually kind of surprised that original code ever worked – given the reality of type erasure, it was kind of lying.

It looks to me like the way to clear the error is to allow the erasure to tell the truth:

  case (h: Option[_], w: Option[_])     => (h, w)

and maybe do a sub-match or something like that on the inner contents.

Note that your second case has the same problem: the issue is really about trying to match the inner type of Option, more than the tuples.

4 Likes

Note that your second case has the same problem: the issue is really about trying to match the inner type of Option, more than the tuples.

@jducoeur interestingly, the compiler is able to recognize the inner type for the second case case x: Option[Int] given the union type. If the type any as in your modified example, it shows the type test cannot be checked at runtime warning. It is not able to do so in the tuple case though, perhaps due to the additional level of nesting.

Anyway, in my case the suggestion by @abosshard is working fine as the function parameter type already ensures that the inner type is always Int.

Thanks for your help.

1 Like