Skip to content

Commit 2efc14f

Browse files
Stephan SahmStephan Sahm
authored andcommitted
fixed promote_type for Either (it was broken due to promote_type internals)
1 parent f89bb27 commit 2efc14f

1 file changed

Lines changed: 35 additions & 1 deletion

File tree

src/promote_type.jl

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,41 @@ Base.promote_rule(::Type{Identity}, ::Type{Either}) = Either
5050
# promote_type Either & Either
5151
# -----------------------------
5252

53+
# It turns out for this symmetric case we need to define both versions of promote_rule, including the flipped one
54+
# This is needed, because `promote_type` assumes promote_rule to fallback to the general fallback returning Union{}
55+
# for its feature "you only need to define one" to work out correctly.
56+
57+
# It turns out further, that there is a major bug in Julia, not allowing for these kinds of dispatch as of now
58+
# see https://github.com/JuliaLang/julia/issues/36804 the issue and possible future updates
59+
60+
# As a workaround, we overload `promote_type` to deal with our symmetric case
61+
function Base.promote_type(::Type{Either{L1, R1}}, ::Type{Either{L2, R2}}) where {L1, R1, L2, R2}
62+
Base.@_inline_meta
63+
T = Either{L1, R1}
64+
S = Either{L2, R2}
65+
# we use typeintersect, as we get an Either for the non-fitting site,
66+
# thanks to Base.promote_rule(::Type{Either{L1, R1}}, ::Type{Either{L2, R2}}) where {L1, R1, L2, R2} = Either
67+
typeintersect(promote_rule(T, S), promote_rule(S, T))
68+
end
69+
70+
function Base.promote_type(::Type{Either{<:Any, R1}}, ::Type{Either{<:Any, R2}}) where {R1, R2}
71+
Base.@_inline_meta
72+
T = Either{<:Any, R1}
73+
S = Either{<:Any, R2}
74+
# we use typeintersect, as we get an Either for the non-fitting site,
75+
# thanks to Base.promote_rule(::Type{Either{<:Any, R1}}, ::Type{Either{<:Any, R2}}) where {R1, R2} = Either
76+
typeintersect(promote_rule(T, S), promote_rule(S, T))
77+
end
78+
79+
function Base.promote_type(::Type{Either{L1, <:Any}}, ::Type{Either{L2, <:Any}}) where {L1, L2}
80+
Base.@_inline_meta
81+
T = Either{L1, <:Any}
82+
S = Either{L2, <:Any}
83+
# we use typeintersect, as we get an Either for the non-fitting site,
84+
# thanks to Base.promote_rule(::Type{Either{L1, <:Any}}, ::Type{Either{L2, <:Any}}) where {L1, L2} = Either
85+
typeintersect(promote_rule(T, S), promote_rule(S, T))
86+
end
87+
5388
# we need to be cautious here, as we cannot dispatch on Type{<:Either{<:Any, R}} or similar, because R might not be defined
5489
Base.promote_rule(::Type{Either{L, R}}, ::Type{Either{L, R}}) where {L, R} = Either{L, R}
5590
Base.promote_rule(::Type{Either{L1, R}}, ::Type{Either{L2, R}}) where {L1, R, L2 <: L1} = Either{L1, R}
@@ -75,7 +110,6 @@ Base.promote_rule(::Type{Either{<:Any, R1}}, ::Type{Either{<:Any, R2}}) where {R
75110
Base.promote_rule(::Type{Either}, ::Type{Either}) = Either
76111

77112

78-
79113
# promote_typejoin
80114
# ================
81115

0 commit comments

Comments
 (0)