Type instability with `Base.promote_type` and Static.jl types for Julia v1.10-beta2 and `--check-bounds=no`
When using Julia v1.10-beta2 with --check-bounds=no, using Static.jl types together with native types causes a type instability. In fact, it looks like Base.promote_type is not able to infer a concrete type at all anymore and just returns Any.
MWE (with julia-1.10-beta2 --check=bounds=no):
julia> using Pkg
julia> Pkg.activate(; temp=true, io=devnull)
julia> Pkg.add(name="Static", version="0.8.8", io=devnull)
julia> using Static
julia> i = 1; s = static(2);
julia> @code_warntype Base.promote_type(typeof(i), typeof(s))
MethodInstance for promote_type(::Type{Int64}, ::Type{StaticInt{2}})
from promote_type(::Type{T}, ::Type{S}) where {T, S} @ Base promotion.jl:306
Static Parameters
T = Int64
S = StaticInt{2}
Arguments
#self#::Core.Const(promote_type)
_::Core.Const(Int64)
_::Core.Const(StaticInt{2})
Body::Any
1 ─ nothing
│ %2 = $(Expr(:static_parameter, 1))::Core.Const(Int64)
│ %3 = $(Expr(:static_parameter, 2))::Core.Const(StaticInt{2})
│ %4 = Base.promote_rule($(Expr(:static_parameter, 1)), $(Expr(:static_parameter, 2)))::Core.Const(Union{})
│ %5 = Base.promote_rule($(Expr(:static_parameter, 2)), $(Expr(:static_parameter, 1)))::Core.Const(Union{})
│ %6 = Base.promote_result(%2, %3, %4, %5)::Any
└── return %6
The error does not occur if I use Julia v1.10 without --check-bounds=no or when using Julia v1.9 (with or without --check-bounds=no). On those cases, we get the following output for @code_warntype:
julia> @code_warntype Base.promote_type(typeof(i), typeof(s))
MethodInstance for promote_type(::Type{Int64}, ::Type{StaticInt{2}})
from promote_type(::Type{T}, ::Type{S}) where {T, S} @ Base promotion.jl:306
Static Parameters
T = Int64
S = StaticInt{2}
Arguments
#self#::Core.Const(promote_type)
_::Core.Const(Int64)
_::Core.Const(StaticInt{2})
Body::Type{Number}
1 ─ nothing
│ %2 = $(Expr(:static_parameter, 1))::Core.Const(Int64)
│ %3 = $(Expr(:static_parameter, 2))::Core.Const(StaticInt{2})
│ %4 = Base.promote_rule($(Expr(:static_parameter, 1)), $(Expr(:static_parameter, 2)))::Core.Const(Union{})
│ %5 = Base.promote_rule($(Expr(:static_parameter, 2)), $(Expr(:static_parameter, 1)))::Core.Const(Union{})
│ %6 = Base.promote_result(%2, %3, %4, %5)::Core.Const(Number)
└── return %6
The issue first appeared when trying to use PtrArray from StrideArrays.jl (see also https://github.com/JuliaSIMD/StrideArrays.jl/issues/78). There, the failure to determine a usable promotion type propagates into a regular array access returning values of type Any, making the code unusably slow.
Thanks to @ranocha for creating a more minimum MWE. Maybe @vchuravy has an idea how to fix this (since he resolved a similar issue for v1.9 and StaticArrays.jl)?
cc @chriselrod
I take it this is distinct from (though possibly indirectly related to) the issue discussed in https://github.com/JuliaLang/julia/pull/50239?
On 1.9 with --check-bounds=no
• %2 = < pure > typejoin(::Type{…},::Type{…})::Core.Const(Number) (+c,+e,+n,+t,+s,+m,+i)
On 1.10 with --check-bounds=no
• %1 = invoke typejoin(::Type{Int64},::Type{StaticInt{2}})::Any (+c,+e,!n,+t,+s,+m,+i)
This might be #48684 cc: @aviatesk
I hoped #50561 would improve the situation, but it doesn't seem enough.
Is this another consequence of the removal of @pure from some internals?
Kinda, https://github.com/JuliaLang/julia/pull/48684 replaced special handling of the almost intrinsics. So it's more than just a removal of pure.
Putting this on the milestone since we will need to fix this in either 1.10.0 or 1.10.x
Talking with @Keno, it seems that this cannot really be fixed in 1.10 and has to wait for 1.11, see e.g. https://github.com/JuliaLang/julia/pull/50641. So I will take this off the milestone.