diff --git a/Project.toml b/Project.toml index 9dbe642..0527678 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Static" uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" authors = ["chriselrod", "ChrisRackauckas", "Tokazama"] -version = "0.3.3" +version = "0.3.4" [deps] IfElse = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173" diff --git a/src/Static.jl b/src/Static.jl index 8081bf9..6d86350 100644 --- a/src/Static.jl +++ b/src/Static.jl @@ -30,11 +30,12 @@ Returns the known value corresponding to a static type `T`. If `T` is not a stat See also: [`static`](@ref), [`is_static`](@ref) """ known -@constprop :aggressive known(x) = known(typeof(x)) +#@constprop :aggressive known(x) = known(typeof(x)) +known(@nospecialize(x)) = known(typeof(x)) known(::Type{T}) where {T} = nothing -known(::Type{StaticInt{N}}) where {N} = N::Int -known(::Type{StaticFloat64{N}}) where {N} = N::Float64 -known(::Type{StaticSymbol{S}}) where {S} = S::Symbol +known(@nospecialize(x::Type{<:StaticInt}))::Int = @inbounds(getfield(x, :parameters)[1]) +known(@nospecialize(x::Type{<:StaticSymbol}))::Symbol = @inbounds(getfield(x, :parameters)[1]) +known(@nospecialize(x::Type{<:StaticFloat64}))::Float64 = @inbounds(getfield(x, :parameters)[1]) known(::Type{Val{V}}) where {V} = V known(::Type{True}) = true known(::Type{False}) = false @@ -116,9 +117,9 @@ end Returns the "dynamic" or non-static form of `x`. """ -dynamic(x::X) where {X} = _dynamic(is_static(X), x) -_dynamic(::True, x::X) where {X} = known(X) -_dynamic(::False, x::X) where {X} = x +dynamic(@nospecialize(x)) = _dynamic(is_static(x), x) +_dynamic(::True, @nospecialize(x)) = known(typeof(x)) +_dynamic(::False, x) = x @constprop :aggressive dynamic(x::Tuple) = map(dynamic, x) dynamic(x::NDIndex) = CartesianIndex(dynamic(Tuple(x))) diff --git a/src/bool.jl b/src/bool.jl index b578b1e..424855f 100644 --- a/src/bool.jl +++ b/src/bool.jl @@ -126,5 +126,5 @@ ifelse(::True, x, y) = x ifelse(::False, x, y) = y -Base.show(io::IO, ::StaticBool{bool}) where {bool} = print(io, "static($bool)") +Base.show(io::IO, @nospecialize(x::StaticBool)) = print(io, "static($(dynamic(x)))") diff --git a/src/float.jl b/src/float.jl index 3af005f..9331b42 100644 --- a/src/float.jl +++ b/src/float.jl @@ -21,9 +21,9 @@ StaticFloat64(x::StaticInt{N}) where {N} = float(x) const FloatOne = StaticFloat64{one(Float64)} const FloatZero = StaticFloat64{zero(Float64)} -Base.show(io::IO, ::StaticFloat64{N}) where {N} = print(io, "static($N)") +Base.show(io::IO, @nospecialize(x::StaticFloat64)) = print(io, "static($(dynamic(x)))") -Base.convert(::Type{T}, ::StaticFloat64{N}) where {N,T<:AbstractFloat} = T(N) +Base.convert(::Type{T}, @nospecialize(x::StaticFloat64)) where {T<:AbstractFloat} = T(dynamic(x)) Base.promote_rule(::Type{StaticFloat64{N}}, ::Type{T}) where {N,T} = promote_type(T, Float64) Base.promote_rule(::Type{StaticFloat64{N}}, ::Type{Float64}) where {N} = Float64 Base.promote_rule(::Type{StaticFloat64{N}}, ::Type{Float32}) where {N} = Float32 @@ -33,13 +33,13 @@ Base.promote_rule(::Type{StaticFloat64{N}}, ::Type{Float16}) where {N} = Float16 Base.promote_rule(::Type{StaticFloat64{N}}, ::Type{Any}) where {N} = Any end -Base.eltype(::Type{T}) where {T<:StaticFloat64} = Float64 +Base.eltype(@nospecialize(x::Type{<:StaticFloat64})) = Float64 Base.iszero(::FloatZero) = true -Base.iszero(::StaticFloat64) = false +Base.iszero(@nospecialize(x::StaticFloat64)) = false Base.isone(::FloatOne) = true -Base.isone(::StaticFloat64) = false -Base.zero(::Type{T}) where {T<:StaticFloat64} = FloatZero() -Base.one(::Type{T}) where {T<:StaticFloat64} = FloatOne() +Base.isone(@nospecialize(x::StaticFloat64)) = false +Base.zero(@nospecialize(x::Type{<:StaticFloat64})) = FloatZero() +Base.one(@nospecialize(x::Type{<:StaticFloat64})) = FloatOne() Base.@pure function fsub(::StaticFloat64{X}, ::StaticFloat64{Y}) where {X,Y} return StaticFloat64{Base.sub_float(X, Y)::Float64}() diff --git a/src/int.jl b/src/int.jl index 33d5b39..de92a6d 100644 --- a/src/int.jl +++ b/src/int.jl @@ -12,23 +12,23 @@ end const Zero = StaticInt{0} const One = StaticInt{1} -Base.show(io::IO, ::StaticInt{N}) where {N} = print(io, "static($N)") +Base.show(io::IO, @nospecialize(x::StaticInt)) = print(io, "static($(dynamic(x)))") StaticInt(N::Int) = StaticInt{N}() StaticInt(N::Integer) = StaticInt(convert(Int, N)) StaticInt(::StaticInt{N}) where {N} = StaticInt{N}() StaticInt(::Val{N}) where {N} = StaticInt{N}() # Base.Val(::StaticInt{N}) where {N} = Val{N}() -Base.convert(::Type{T}, ::StaticInt{N}) where {T<:Number,N} = convert(T, N) -Base.Bool(x::StaticInt{N}) where {N} = Bool(N) -Base.BigInt(x::StaticInt{N}) where {N} = BigInt(N) +Base.convert(::Type{T}, @nospecialize(x::StaticInt)) where {T<:Number} = convert(T, dynamic(x)) +Base.Bool(@nospecialize(x::StaticInt)) = Bool(dynamic(x)) +Base.BigInt(@nospecialize(x::StaticInt)) = BigInt(dynamic(x)) Base.Integer(x::StaticInt{N}) where {N} = x -(::Type{T})(x::StaticInt{N}) where {T<:Integer,N} = T(N) +(::Type{T})(@nospecialize(x::StaticInt)) where {T<:Integer} = T(dynamic(x)) (::Type{T})(x::Int) where {T<:StaticInt} = StaticInt(x) Base.convert(::Type{StaticInt{N}}, ::StaticInt{N}) where {N} = StaticInt{N}() -Base.promote_rule(::Type{<:StaticInt}, ::Type{T}) where {T<:Number} = promote_type(Int, T) -function Base.promote_rule(::Type{<:StaticInt}, ::Type{T}) where {T<:AbstractIrrational} +Base.promote_rule(@nospecialize(x::Type{<:StaticInt}), ::Type{T}) where {T<:Number} = promote_type(Int, T) +function Base.promote_rule(@nospecialize(x::Type{<:StaticInt}), ::Type{T}) where {T<:AbstractIrrational} return promote_type(Int, T) end # Base.promote_rule(::Type{T}, ::Type{<:StaticInt}) where {T <: AbstractIrrational} = promote_rule(T, Int) @@ -43,44 +43,44 @@ end function Base.promote_rule(::Type{T}, ::Type{<:StaticInt}) where {T>:Union{Missing,Nothing}} return promote_type(T, Int) end -Base.promote_rule(::Type{T}, ::Type{<:StaticInt}) where {T>:Nothing} = promote_type(T, Int) -Base.promote_rule(::Type{T}, ::Type{<:StaticInt}) where {T>:Missing} = promote_type(T, Int) +Base.promote_rule(::Type{T}, @nospecialize(x::Type{<:StaticInt})) where {T>:Nothing} = promote_type(T, Int) +Base.promote_rule(::Type{T}, @nospecialize(x::Type{<:StaticInt})) where {T>:Missing} = promote_type(T, Int) for T in [:Bool, :Missing, :BigFloat, :BigInt, :Nothing, :Any] # let S = :Any @eval begin - function Base.promote_rule(::Type{S}, ::Type{$T}) where {S<:StaticInt} + function Base.promote_rule(@nospecialize(x::Type{<:StaticInt}), ::Type{$T}) return promote_type(Int, $T) end - function Base.promote_rule(::Type{$T}, ::Type{S}) where {S<:StaticInt} + function Base.promote_rule(::Type{$T}, @nospecialize(x::Type{<:StaticInt})) return promote_type($T, Int) end end end -Base.promote_rule(::Type{<:StaticInt}, ::Type{<:StaticInt}) = Int -Base.:(%)(::StaticInt{N}, ::Type{Integer}) where {N} = N +Base.promote_rule(@nospecialize(x::Type{<:StaticInt}), @nospecialize(y::Type{<:StaticInt})) = Int +Base.:(%)(@nospecialize(x::StaticInt), ::Type{Integer}) = dynamic(x) -Base.eltype(::Type{T}) where {T<:StaticInt} = Int +Base.eltype(@nospecialize(x::Type{<:StaticInt})) = Int Base.iszero(::Zero) = true -Base.iszero(::StaticInt) = false +Base.iszero(@nospecialize(x::StaticInt)) = false Base.isone(::One) = true -Base.isone(::StaticInt) = false -Base.zero(::Type{T}) where {T<:StaticInt} = Zero() -Base.one(::Type{T}) where {T<:StaticInt} = One() +Base.isone(@nospecialize(x::StaticInt)) = false +Base.zero(@nospecialize(x::Type{<:StaticInt})) = Zero() +Base.one(@nospecialize(x::Type{<:StaticInt})) = One() for T in [:Real, :Rational, :Integer] @eval begin @inline Base.:(+)(i::$T, ::Zero) = i - @inline Base.:(+)(i::$T, ::StaticInt{M}) where {M} = i + M + @inline Base.:(+)(i::$T, @nospecialize(m::StaticInt)) = i + dynamic(m) @inline Base.:(+)(::Zero, i::$T) = i - @inline Base.:(+)(::StaticInt{M}, i::$T) where {M} = M + i + @inline Base.:(+)(@nospecialize(m::StaticInt), i::$T) = dynamic(m) + i @inline Base.:(-)(i::$T, ::Zero) = i - @inline Base.:(-)(i::$T, ::StaticInt{M}) where {M} = i - M + @inline Base.:(-)(i::$T, @nospecialize(m::StaticInt)) = i - dynamic(m) @inline Base.:(*)(i::$T, ::Zero) = Zero() @inline Base.:(*)(i::$T, ::One) = i - @inline Base.:(*)(i::$T, ::StaticInt{M}) where {M} = i * M + @inline Base.:(*)(i::$T, @nospecialize(m::StaticInt)) = i * dynamic(m) @inline Base.:(*)(::Zero, i::$T) = Zero() @inline Base.:(*)(::One, i::$T) = i - @inline Base.:(*)(::StaticInt{M}, i::$T) where {M} = M * i + @inline Base.:(*)(@nospecialize(m::StaticInt), i::$T) = dynamic(m) * i end end @inline Base.:(+)(::Zero, ::Zero) = Zero() @@ -112,8 +112,8 @@ end for f in [:(==), :(!=), :(<), :(≤), :(>), :(≥)] @eval begin @inline Base.$f(::StaticInt{M}, ::StaticInt{N}) where {M,N} = $f(M, N) - @inline Base.$f(::StaticInt{M}, x::Int) where {M} = $f(M, x) - @inline Base.$f(x::Int, ::StaticInt{M}) where {M} = $f(x, M) + @inline Base.$f(@nospecialize(m::StaticInt), x::Int) = $f(dynamic(m), x) + @inline Base.$f(x::Int, @nospecialize(m::StaticInt)) = $f(x, dynamic(m)) end end @@ -126,17 +126,17 @@ end end end -@inline Base.widen(::StaticInt{N}) where {N} = widen(N) +@inline Base.widen(@nospecialize(x::StaticInt)) = widen(dynamic(x)) -Base.UnitRange{T}(start::StaticInt, stop) where {T<:Real} = UnitRange{T}(T(start), T(stop)) -Base.UnitRange{T}(start, stop::StaticInt) where {T<:Real} = UnitRange{T}(T(start), T(stop)) -function Base.UnitRange{T}(start::StaticInt, stop::StaticInt) where {T<:Real} +Base.UnitRange{T}(@nospecialize(start::StaticInt), stop) where {T<:Real} = UnitRange{T}(T(start), T(stop)) +Base.UnitRange{T}(start, @nospecialize(stop::StaticInt)) where {T<:Real} = UnitRange{T}(T(start), T(stop)) +function Base.UnitRange{T}(@nospecialize(start::StaticInt), @nospecialize(stop::StaticInt)) where {T<:Real} return UnitRange{T}(T(start), T(stop)) end -Base.UnitRange(start::StaticInt, stop) = UnitRange(Int(start), stop) -Base.UnitRange(start, stop::StaticInt) = UnitRange(start, Int(stop)) -Base.UnitRange(start::StaticInt, stop::StaticInt) = UnitRange(Int(start), Int(stop)) +Base.UnitRange(@nospecialize(start::StaticInt), stop) = UnitRange(Int(start), stop) +Base.UnitRange(start, @nospecialize(stop::StaticInt)) = UnitRange(start, Int(stop)) +Base.UnitRange(@nospecialize(start::StaticInt), @nospecialize(stop::StaticInt)) = UnitRange(Int(start), Int(stop)) """ eq(x, y) diff --git a/src/symbol.jl b/src/symbol.jl index 05f8dd4..26934f9 100644 --- a/src/symbol.jl +++ b/src/symbol.jl @@ -19,5 +19,5 @@ StaticSymbol(x, y, z...) = StaticSymbol(StaticSymbol(x, y), z...) Base.Symbol(::StaticSymbol{s}) where {s} = s::Symbol -Base.show(io::IO, ::StaticSymbol{s}) where {s} = print(io, "static(:$s)") +Base.show(io::IO, @nospecialize(x::StaticSymbol)) = print(io, "static(:$(dynamic(x)))")