Lilith
1
Shouldn’t type checks for statically known types be free at runtime?
julia> const IntUInt = Union{Int, UInt}
Union{Int64, UInt64}
julia> struct T{U <: Integer}
x::U
end
julia> @btime 1 isa T{<:IntUInt}
151.025 ns (3 allocations: 128 bytes)
false
julia> f() = 1 isa T{<:IntUInt}
f (generic function with 1 method)
julia> @btime f()
140.869 ns (3 allocations: 128 bytes)
false
julia> @btime 1 isa Int
1.433 ns (0 allocations: 0 bytes)
true
julia> @btime 1 isa Union{Integer, AbstractFloat}
1.722 ns (0 allocations: 0 bytes)
true
julia> @btime 1 isa T
1.843 ns (0 allocations: 0 bytes)
false
Keno
2
Yes, but the elision only works if the compiler knows what RHS is. In this case, it does not:
CodeInfo(
1 ─ %1 = Core.TypeVar(Symbol("#s1"), Main.IntUInt)::Core.Compiler.PartialTypeVar(var"#s1"<:Union{Int64, UInt64}, true, true)
│ (@_2 = %1)::Core.Compiler.PartialTypeVar(var"#s1"<:Union{Int64, UInt64}, true, true)
│ %3 = @_2::Core.Compiler.PartialTypeVar(var"#s1"<:Union{Int64, UInt64}, true, true)
│ %4 = Core.apply_type(Main.T, @_2::Core.Compiler.PartialTypeVar(var"#s1"<:Union{Int64, UInt64}, true, true))::Any
│ %5 = Core.UnionAll(%3, %4)::Any
│ %6 = (1 isa %5)::Bool
└── return %6
) => Bool
If you’re feeling adventurous, you could take a look at apply_type_tfunc
to see if this case can be made to work: