Skip to content

subtype triangular rule mistake with UnionAll in Union #62464

Description

@vtjnash
julia> f(::Type{Union{T,Nothing}}, ::T) where {T} = T

julia> f(Nothing, nothing) # good
Nothing

julia> f(Union{Nothing, Integer}, nothing) # okay
Union{Nothing, Integer}

julia> f(Union{Nothing, Int}, nothing) # okay
Union{Nothing, Int64}

julia> f(Union{Nothing, Vector}, nothing) # bad
ERROR: MethodError: no method matching f(::Core.TypeEgal{Union{Nothing, Vector}}, ::Nothing)
The function `f` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  f(::Type{Union{Nothing, T}}, ::T) where T
   @ Main REPL[1]:1

Stacktrace:
 [1] top-level scope
   @ REPL[4]:1

The witness check is the clincher: with T explicitly bound to Union{Nothing,Vector}, x <: Tuple{Type{Union{T,Nothing}}, T} is true — so a valid witness exists, but forall_exists_subtype fails to find it in the where T form. That's a clean incompleteness in <:, and it's pre-existing (all versions).

Verdict: you found a real bug:
The bug x <: Y and typeintersect(x, Y) disagree, which they never should (x ∩ Y = x ⟹ x ⊆ Y ⟹ x <: Y):
x = Tuple{Type{Union{Nothing,Vector}}, Nothing}
Y = Tuple{Type{Union{T,Nothing}}, T} where T
x <: Y == false # WRONG
typeintersect(x,Y) == x == true # x ⊆ Y
x <: Y[T := Union{Nothing,Vector}] == true # witness exists Tight characterization — the failure needs both:

  1. the covariant ::T slot forces the absorbed solution (T must contain Nothing, so the exposed T=Vector is rejected by T >: Nothing); and 2. the other union member is a UnionAll (Vector). Make it concrete (Vector{Int}) and it works; use only the exposed solution (2nd slot Vector{Int}) and it works; use an abstract DataType (Integer, Real) and it works.

Metadata

Metadata

Assignees

No one assigned

    Labels

    types and dispatchTypes, subtyping and method dispatch

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions