Why does (AbstractArray{Union{Number, T}} where T <: Nothing) != (AbstractArray{Union{Number, Nothing}})

In the search to find something that would match an `Vector{Union{MyType,Nothing}}` and `Vector{MyType}` but not `Vector{Nothing}`.
I found the signature that works is `Vector{Union{MyType,T}} where T<:Nothing`, but now I need to understand why.

Because apparently:

``````true ==  (AbstractArray{Union{Number, Nothing}})  <: (AbstractArray{Union{Number, T}} where T <: Nothing)
false ==  (AbstractArray{Union{Number, Nothing}})  :> (AbstractArray{Union{Number, T}} where T <: Nothing)
``````

but strangely if you simplify further

``````true ==  Union{Number, Nothing}  <: (Union{Number, T} where T <: Nothing)
true ==  Union{Number, Nothing}  :> (Union{Number, T} where T <: Nothing)
true ==  Union{Number, Nothing}  == (Union{Number, T} where T <: Nothing)
``````

Is there any easy way to expalain why that happens?

The key is that your `T` can match anything thatâ€™s a subtype of `Nothing`. Now while it may feel like that should just be `Nothing` itself and nothing more, it also includes the â€śbottomâ€ť type â€” `Union{}`.

``````julia> Union{} <: (T where T <: Nothing)
true
``````

Thus itâ€™s not just substituting in a `Nothing` where that `T` goes â€” a `Union{}` could go there, too. And if that happens, we end up with simply:

``````julia> Union{Number, Union{}}
Number
``````

So that means that we have an additional subtype here:

``````julia> AbstractArray{Number} <: AbstractArray{Union{Number, T}} where T <: Nothing
true
``````
4 Likes