Widening Union Types have been discussed here but I can't seem to find an answer to the following case
Let's start by looking at the following
val x = List(1, 2, "a")
This heterogeneous list is inferred as List[Any]
Just like it would in Scala 2
However the following
val x2 = List(List(1, 2), Vector("a", "b"))
is inferred as List[scala.collection.immutable.AbstractSeq[Int | String]]
This is rather confusing behavior. Why does two disjoint types' LUB get inferred as Any
in one case but a union type in another?
If it is just a design decision, are there any such cases that one should be aware of ?
smarter states
we avoid inferring union types for the same reason we avoid inferring singleton types, because sometimes they're "too precise"
My interpretation of this statement is that it makes more sense to type List(1,2)
as List[Int]
instead of List[1 | 2]
, or List(new Cat, new Dog)
as List[Animal]
instead of List[Cat | Dog]
.
See also Dmytro's comment from related question (of mine)
Quote from guillaume.martres.me/talks/dotty-tutorial/#/1/13 (slide 15 "Type inference and union types"): "By default, Dotty does not infer union types, they are approximated by a non-union supertype. Union types can be "too precise" and prevent legitimate code from compiling"
Also see mention at 23:38 of the talk "Dotty and types: the story so far".
However widening of union is performed only once to avoid infinite LUB as per smarter:
when we do the widening once, the resulting type might have a union somewhere (like the example in the section Join of a union type in the doc), we won't widen that if we did do the widening recursively, we could get an infinite lub indeed
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With