I’d like to handle the conversion in structs just like when you have a concrete type for a field, but when a field as a Union
type like below:
struct A end
struct B
x::Union{A, Int}
end
I’d like this to work:
B(true) # should return B(1)
I was able to make everything work with:
# note: these definitions are not entirely correct in any case, see the issue for more details
Base.convert(::Type{Union{A,T}}, x) where T = convert(T, x)
Base.convert(::Type{Union{A,T}}, x::T) where T = convert(T, x)
Base.convert(::Type{Union{A,T}} where T, x::A) = x
everything seems to work very well
julia> b1 = B(A())
B(A())
julia> b2 = B(1)
B(1)
julia> b3 = B(true) # automatic conversion
B(1)
but then I was informed by @jameson in this issue: Ambiguity in Base.convert on 1.8/1.9 but not on 1.10 and master · Issue #53224 · JuliaLang/julia · GitHub that I’m committing type-piracy, and indeed this now fails!
julia> Union{Nothing, Union{A, Int}}[1][1]
ERROR: MethodError: convert(::Type{Union{Nothing, A, Int64}}, ::Int64) is ambiguous.
Candidates:
convert(::Type{Union{A, T}}, x::T) where T
@ Main REPL[4]:1
convert(::Type{T}, x) where T>:Nothing
@ Base some.jl:37
convert(::Type{Union{A, T}}, x) where T
@ Main REPL[3]:1
convert(::Type{T}, x::T) where T>:Nothing
@ Base some.jl:36
convert(::Type{T}, x::T) where T
@ Base Base.jl:84
To resolve the ambiguity, try making one of the methods more specific, or adding a new method more specific than any of the existing applicable methods.
but without the above extensions of Base.convert
it works fine:
julia> Union{Nothing, Union{A, Int}}[1][1]
1
Is there a way to achieve this without producing bugs?