Why is union type is not inferred?

“A union type is widened in type inference to the least supertype that is not a union type.”

Example code:

trait Kind
case object Var extends Kind
case object Val extends Kind
case object Const extends Kind
val x = Set(if condition then Val else Var)

Here is the inferred type of x will be Set[Kind]

The more I use union types the more I feel the lack of inference for them.

Is there a reason why the inferred type of x is not Val.type | Var.type ?

1 Like

I would guess the reasons are:

  • The common supertype decides, which members are accessible, so that is the most relevant

  • If you allow union types to be inferred, the inferred types may run up to enormously complex types pretty quickly, leading to completely incomprehensible error messages

So, let me ask the reverse: why would you want union types to be inferred?

Some details here:

Inferring types which are “too precise” can lead to unintuitive typechecking issues later on. Note: Since this behavior limits the usability of union types, it might be changed in the future.

3 Likes

The same reason we want any types inferred.

val x = if condition then 1 else "one"

In a language which has union types and type inference, it would have been awesome if x was Int | String instead of Any. Int | String is more “informative” and more “strongly typed”

Having said that, it allows me to write

val x: Int | String = if condition then 1 else "one"

but then, writing it manually just feels so unintuitive and verbose