Dotty union types: matching with a type alias does not allow run-time type checking?

I expected that using union types directly or using a type alias should produce the same result.
However when using a type alias in a match I get the warning:

    [warn] 25 |      case a:Numeric => println(s"numeric = $a")
    [warn]    |           ^^^^^^^^^
    [warn]    |  the type test for gg.SlidingIssue.Numeric cannot be checked at runtime
    [warn] one warning found

Assuming I declare:

  type Numeric = Double | Int

Aren’t Double | Int and Numeric equivalent?

See the full example below (check2 results in the warning).

TIA,

  type Numeric = Double | Int

  val v1 = 100
  val v2 = 100.0
  def check1(i: Double | Int | String): Unit = {
    i match {
      case a:(Double | Int) => println(s"numeric = $a")
      case _ => println("categorical")
    }
  }
  /*
    [warn] 25 |      case a:Numeric => println(s"numeric = $a")
    [warn]    |           ^^^^^^^^^
    [warn]    |  the type test for gg.SlidingIssue.Numeric cannot be checked at runtime
    [warn] one warning found
   */
  def check2(i: Double | Int | String): Unit = {
    i match {
      case a:Numeric => println(s"numeric = $a")
      case _ => println("categorical")
    }
  }
1 Like

I’m a bit surprised that you can reliably match and isInstanceOf with union types. But it does seem to work. I think the warning is a bug, or at least overeager. Probably there’s a line somewhere in the compiler like if (tp.isAlias && !tp.dealias.isClassType) warn(...) that doesn’t take into account that instanceOf checks with union types also work.

Does this mean that I have used union types incorrectly?

Should I report this?

TIA

The way you used them seems to work, so I don’t think it’s incorrect.

Probably yes. If it is something that can be improved they’ll be happy to know about it.

Thanks.

For future reference:

2 Likes