@@ -59,36 +59,51 @@ Base.promote_rule(::Type{Identity}, ::Type{Either}) = Either
5959
6060# As a workaround, we overload `promote_type` to deal with our symmetric case
6161function Base. promote_type (:: Type{Either{L1, R1}} , :: Type{Either{L2, R2}} ) where {L1, R1, L2, R2}
62- Base. @_inline_meta
6362 T = Either{L1, R1}
6463 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))
64+ either_promote_type_fix (T, S)
6865end
6966
7067function Base. promote_type (:: Type{Either{<:Any, R1}} , :: Type{Either{<:Any, R2}} ) where {R1, R2}
71- Base. @_inline_meta
7268 T = Either{<: Any , R1}
7369 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))
70+ either_promote_type_fix (T, S)
7771end
7872
7973function Base. promote_type (:: Type{Either{L1, <:Any}} , :: Type{Either{L2, <:Any}} ) where {L1, L2}
80- Base. @_inline_meta
8174 T = Either{L1, <: Any }
8275 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))
76+ either_promote_type_fix (T, S)
77+ end
78+
79+ function either_promote_type_fix (T, S)
80+ # In addition we need to check for MethodAmbiguities, as we cannot resolve them on one side, we just ignore them
81+ a = @TryCatch MethodError promote_rule (T, S)
82+ b = @TryCatch MethodError promote_rule (S, T)
83+
84+ if isexception (a) && isexception (b)
85+ error (" Could not `promote_type{T=$T , S=$S }`, as both `promote_rule(T, S)` and `promote_rule(S, T)` result in
86+ MethodErrors: $a , $b ." )
87+ elseif issuccess (a) && issuccess (b)
88+ # We use typeintersect, as we get an Either for the non-fitting site,
89+ # thanks to
90+ # * Base.promote_rule(::Type{Either{L1, R1}}, ::Type{Either{L2, R2}}) where {L1, R1, L2, R2} = Either
91+ # * Base.promote_rule(::Type{Either{<:Any, R1}}, ::Type{Either{<:Any, R2}}) where {R1, R2} = Either
92+ # * Base.promote_rule(::Type{Either{L1, <:Any}}, ::Type{Either{L2, <:Any}}) where {L1, L2} = Either
93+ typeintersect (a[], b[])
94+ elseif issuccess (a)
95+ a[]
96+ else
97+ b[]
98+ end
8699end
87100
88101# we need to be cautious here, as we cannot dispatch on Type{<:Either{<:Any, R}} or similar, because R might not be defined
89102Base. promote_rule (:: Type{Either{L, R}} , :: Type{Either{L, R}} ) where {L, R} = Either{L, R}
90103Base. promote_rule (:: Type{Either{L1, R}} , :: Type{Either{L2, R}} ) where {L1, R, L2 <: L1 } = Either{L1, R}
91104Base. promote_rule (:: Type{Either{L, R1}} , :: Type{Either{L, R2}} ) where {L, R1, R2 <: R1 } = Either{L, R1}
105+ Base. promote_rule (:: Type{Either{L1, R1}} , :: Type{Either{L2, R2}} ) where {L1, R1, L2 <: L1 , R2} = Either{L1, <: Any }
106+ Base. promote_rule (:: Type{Either{L2, R1}} , :: Type{Either{L1, R2}} ) where {L1, R1, L2, R2 <: R1 } = Either{<: Any , R1}
92107Base. promote_rule (:: Type{Either{L1, R1}} , :: Type{Either{L2, R2}} ) where {L1, R1, L2 <: L1 , R2 <: R1 } = Either{L1, R1}
93108Base. promote_rule (:: Type{Either{L2, R1}} , :: Type{Either{L1, R2}} ) where {L1, R1, L2 <: L1 , R2 <: R1 } = Either{L1, R1}
94109
0 commit comments