|
| 1 | +# promote_type/promote_typejoin already works for Identity and Nothing (aka Options) |
| 2 | +# ========================================================================== |
| 3 | + |
| 4 | +# nothing todo, as `Nothing` is already super well supported for promote_type and promote_typejoin |
| 5 | + |
| 6 | + |
| 7 | +# promote_type/promote_typejoin should work with Identity and Const (aka Either) |
| 8 | +# ========================================================================== |
| 9 | + |
| 10 | +# promote_type only has to deal with concrete types, including Unions in our case |
| 11 | + |
| 12 | +# promote_type Const & Identity |
| 13 | +# ----------------------------- |
| 14 | + |
| 15 | +Base.promote_rule(::Type{C}, ::Type{I}) where {C<:Const, I<:Identity} = Union{C, I} |
| 16 | + |
| 17 | + |
| 18 | +# promote_type Const & Either |
| 19 | +# ----------------------------- |
| 20 | + |
| 21 | +Base.promote_rule(::Type{Const}, ::Type{Either{L, R}}) where {L, R} = Either{<:Any, R} |
| 22 | +Base.promote_rule(::Type{Const{L}}, ::Type{Either{L, R}}) where {L, R} = Either{L, R} |
| 23 | +Base.promote_rule(::Type{Const{L1}}, ::Type{Either{L2, R}}) where {L1, R, L2 <: L1} = Either{L1, R} |
| 24 | +Base.promote_rule(::Type{Const{L2}}, ::Type{Either{L1, R}}) where {L1, R, L2 <: L1} = Either{L1, R} |
| 25 | + |
| 26 | +Base.promote_rule(::Type{Const}, ::Type{Either{L, <:Any}}) where {L} = Either |
| 27 | +Base.promote_rule(::Type{Const{L}}, ::Type{Either{L, <:Any}}) where {L} = Either{L, <:Any} |
| 28 | +Base.promote_rule(::Type{Const{L1}}, ::Type{Either{L2, <:Any}}) where {L1, L2 <: L1} = Either{L1, <:Any} |
| 29 | +Base.promote_rule(::Type{Const{L2}}, ::Type{Either{L1, <:Any}}) where {L1, L2 <: L1} = Either{L1, <:Any} |
| 30 | + |
| 31 | +Base.promote_rule(::Type{Const}, ::Type{Either}) = Either |
| 32 | + |
| 33 | + |
| 34 | +# promote_type Identity & Either |
| 35 | +# ----------------------------- |
| 36 | + |
| 37 | +Base.promote_rule(::Type{Identity}, ::Type{Either{L, R}}) where {L, R} = Either{L, <:Any} |
| 38 | +Base.promote_rule(::Type{Identity{R}}, ::Type{Either{L, R}}) where {L, R} = Either{L, R} |
| 39 | +Base.promote_rule(::Type{Identity{R1}}, ::Type{Either{L, R2}}) where {L, R1, R2 <: R1} = Either{L, R1} |
| 40 | +Base.promote_rule(::Type{Identity{R2}}, ::Type{Either{L, R1}}) where {L, R1, R2 <: R1} = Either{L, R1} |
| 41 | + |
| 42 | +Base.promote_rule(::Type{Identity}, ::Type{Either{<:Any, R}}) where {R} = Either |
| 43 | +Base.promote_rule(::Type{Identity{R}}, ::Type{Either{<:Any, R}}) where {R} = Either{<:Any, R} |
| 44 | +Base.promote_rule(::Type{Identity{R1}}, ::Type{Either{<:Any, R2}}) where {R1, R2 <: R1} = Either{<:Any, R1} |
| 45 | +Base.promote_rule(::Type{Identity{R2}}, ::Type{Either{<:Any, R1}}) where {R1, R2 <: R1} = Either{<:Any, R1} |
| 46 | + |
| 47 | +Base.promote_rule(::Type{Identity}, ::Type{Either}) = Either |
| 48 | + |
| 49 | + |
| 50 | +# promote_type Either & Either |
| 51 | +# ----------------------------- |
| 52 | + |
| 53 | +# we need to be cautious here, as we cannot dispatch on Type{<:Either{<:Any, R}} or similar, because R might not be defined |
| 54 | +Base.promote_rule(::Type{Either{L, R}}, ::Type{Either{L, R}}) where {L, R} = Either{L, R} |
| 55 | +Base.promote_rule(::Type{Either{L1, R}}, ::Type{Either{L2, R}}) where {L1, R, L2 <: L1} = Either{L1, R} |
| 56 | +Base.promote_rule(::Type{Either{L, R1}}, ::Type{Either{L, R2}}) where {L, R1, R2 <: R1} = Either{L, R1} |
| 57 | +Base.promote_rule(::Type{Either{L1, R1}}, ::Type{Either{L2, R2}}) where {L1, R1, L2 <: L1, R2 <: R1} = Either{L1, R1} |
| 58 | +Base.promote_rule(::Type{Either{L2, R1}}, ::Type{Either{L1, R2}}) where {L1, R1, L2 <: L1, R2 <: R1} = Either{L1, R1} |
| 59 | + |
| 60 | +Base.promote_rule(::Type{Either{L, <:Any}}, ::Type{Either{L, <:Any}}) where {L} = Either{L, <:Any} |
| 61 | +Base.promote_rule(::Type{Either{L1, <:Any}}, ::Type{Either{L2, <:Any}}) where {L1, L2 <: L1} = Either{L1, <:Any} |
| 62 | + |
| 63 | +Base.promote_rule(::Type{Either{<:Any, R}}, ::Type{Either{<:Any, R}}) where {L, R} = Either{<:Any, R} |
| 64 | +Base.promote_rule(::Type{Either{<:Any, R1}}, ::Type{Either{<:Any, R2}}) where {L, R1, R2 <: R1} = Either{<:Any, R1} |
| 65 | + |
| 66 | +# NOTE we cannot use `Base.promote_rule(::Type{<:Either}, ::Type{<:Either}) = Either` as apparently this interferes |
| 67 | +# with more concrete implementations of promote_rule |
| 68 | +# promote_type seem to assume, that you really only define promote_rule for concrete types |
| 69 | +Base.promote_rule(::Type{Either}, ::Type{Either}) = Either |
| 70 | + |
| 71 | + |
| 72 | +# promote_typejoin |
| 73 | +# ----------------------------- |
| 74 | + |
| 75 | +# We also support `promote_typejoin`, as the semantics between promote_typejoin and promote_type overlap |
| 76 | +# in our case of Unions (similar to how they are already defined for Nothing and Missing in Base). |
| 77 | +# In addition note that `promote_typejoin` has to be defined for both flipped and non-flipped versions. |
| 78 | +# We solve this by referring to the symmetric `promote_type` instead of the asymmtric `promote_rule`. |
| 79 | +Base.promote_typejoin(::Type{E1}, ::Type{E2}) where {E1<:OptionEither, E2<:OptionEither} = promote_type(E1, E2) |
| 80 | +# TODO typejoin should actually not combine Identity{AbstractString} and Identity{String} to Identity{AbstractString} |
| 81 | +# hence we really need to redefine everything alike to be safe. |
| 82 | + |
| 83 | + |
| 84 | +# promote_type/promote_typejoin should work with all three Identity, Nothing and Const (aka OptionEither) |
| 85 | +# ========================================================================== |
| 86 | + |
| 87 | +# nothing todo, as `Nothing` is already super well supported for promote_type and promote_typejoin |
0 commit comments