That’s what I remembered from another thread. But now that I’m actually trying the package and looking into the source code, it’s type-stable and scales up if every type has seconds::Float64
. For a more modest example that exceeds the automatic Union-splitting optimization of 3, getproperty
does something like this:
v = (LightSumTypes).unwrap(sumt)
if v isa T1
return (Base).getproperty(v, s)
elseif v isa T2
return (Base).getproperty(v, s)
elseif v isa T3
return (Base).getproperty(v, s)
elseif v isa T4
return (Base).getproperty(v, s)
elseif v isa T5
return (Base).getproperty(v, s)
else
error("THIS_SHOULD_BE_UNREACHABLE")
end
So while a normal getproperty
call or equivalent structure.property
expression for a type-unstable structure::Union{...}
would fail, the concrete LightSumType
would branch to every specified type and separately call getproperty
again. If all those inner getproperty
s have the same concrete return type, then the overall getproperty
shares the type; if they don’t, then it takes very little variation to lose type stability. Pretty much every fundamental function generated by @sumtype
has this branch, and it doesn’t have the extra help of assertions or conversions. The successor (in the sense that both are authored by Tortar) WrappedUnions.@unionsplit
puts that branch generation in the user’s hands, which I am guessing would also let the user add convert
calls to restore type stability. To manually write the branch’s expressions instead of generating duplicates, you’d need an API like @cases
of SumTypes.jl; I mention this because I expect the various time types to typically have different operations, not just Float64
arithmetic.
f
surprised me a bit. variant
evidently does not reach a stable return type via some large branch; that branch can’t happen at that stage anyway. However, the compiler was still able to spot the 50 f
methods for the 50 T#=i=#
types all reached seconds::Float64
; to my knowledge, that far exceeds the default Union-splitting optimization (3) and inference of multiple applicable methods (4). I don’t understand the compiler much, maybe someone else can comment. EDIT: The limit was removed for linear signatures, whatever that means RFC: inference: remove union-split limit for linear signatures by vtjnash · Pull Request #37378 · JuliaLang/julia · GitHub
A big set of types has other limits however. The Union
-annotated field of these approaches are internally implemented like C’s tagged unions if all the types are isbits
, but that only goes up to 256 types because the tag is 1 byte. Even if that limit is increased, the parser currently hits a recursion limit for if
-elseif
branches somewhere between 256 and 65536.