Skip to content

remove all uses of @pure #1130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/src/pages/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ same vector. We can now do this with the `Scalar` type:
The size of a statically sized array is a static parameter associated with the
type of the array. The `Size` trait is provided as an abstract representation of
the dimensions of a static array. An array `sa::SA` of size `(dims...)` is
associated with `Size{(dims...)}()`. The following are equivalent (`@pure`)
associated with `Size{(dims...)}()`. The following are equivalent
constructors:
```julia
Size{(dims...,)}()
Expand Down
4 changes: 2 additions & 2 deletions src/SHermitianCompact.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ end
end
end

Base.@pure triangularnumber(N::Int) = div(N * (N + 1), 2)
Base.@pure triangularroot(L::Int) = div(isqrt(8 * L + 1) - 1, 2) # from quadratic formula
triangularnumber(N::Int) = div(N * (N + 1), 2)
triangularroot(L::Int) = div(isqrt(8 * L + 1) - 1, 2) # from quadratic formula

lowertriangletype(::Type{SHermitianCompact{N, T, L}}) where {N, T, L} = SVector{L, T}
lowertriangletype(::Type{SHermitianCompact{N, T}}) where {N, T} = SVector{triangularnumber(N), T}
Expand Down
4 changes: 2 additions & 2 deletions src/SOneTo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ end
Base.first(::SOneTo) = 1
Base.last(::SOneTo{n}) where {n} = n::Int

@pure function Base.iterate(::SOneTo{n}) where {n}
function Base.iterate(::SOneTo{n}) where {n}
if n::Int < 1
return nothing
else
Expand Down Expand Up @@ -68,7 +68,7 @@ function Base.show(io::IO, ::SOneTo{n}) where {n}
print(io, "SOneTo(", n::Int, ")")
end

Base.@pure function Base.checkindex(::Type{Bool}, ::SOneTo{n1}, ::SOneTo{n2}) where {n1, n2}
function Base.checkindex(::Type{Bool}, ::SOneTo{n1}, ::SOneTo{n2}) where {n1, n2}
return n1::Int >= n2::Int
end

Expand Down
6 changes: 3 additions & 3 deletions src/SUnitRange.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ struct SUnitRange{Start, L} <: StaticVector{L, Int}
end
end

@pure function check_sunitrange_params(L::Int)
function check_sunitrange_params(L::Int)
if L < 0
error("Static unit range length is negative")
end
Expand All @@ -16,9 +16,9 @@ function check_sunitrange_params(L)
throw(TypeError(:SUnitRange, "type parameters must be `Int`", Tuple{Int,}, Tuple{typeof(L),}))
end

@pure SUnitRange(a::Int, b::Int) = SUnitRange{a, max(0, b - a + 1)}()
SUnitRange(a::Int, b::Int) = SUnitRange{a, max(0, b - a + 1)}()

@pure @propagate_inbounds function getindex(x::SUnitRange{Start, L}, i::Int) where {Start, L}
@propagate_inbounds function getindex(x::SUnitRange{Start, L}, i::Int) where {Start, L}
@boundscheck if i < 1 || i > L
throw(BoundsError(x, i))
end
Expand Down
2 changes: 1 addition & 1 deletion src/StaticArrays.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module StaticArrays

import Base: @_propagate_inbounds_meta, @propagate_inbounds, @pure
import Base: @_propagate_inbounds_meta, @propagate_inbounds

import Base: getindex, setindex!, size, similar, vec, show, length, convert, promote_op,
promote_rule, map, map!, reduce, mapreduce, foldl, mapfoldl, broadcast,
Expand Down
10 changes: 5 additions & 5 deletions src/abstractarray.jl
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
length(a::StaticArrayLike) = prod(Size(a))::Int
length(a::Type{SA}) where {SA <: StaticArrayLike} = prod(Size(SA))::Int

@pure size(::Type{SA}) where {SA <: StaticArrayLike} = Tuple(Size(SA))
size(::Type{SA}) where {SA <: StaticArrayLike} = Tuple(Size(SA))
@inline function size(t::Type{<:StaticArrayLike}, d::Int)
S = size(t)
d > length(S) ? 1 : S[d]
end
@inline size(a::StaticArrayLike) = Tuple(Size(a))

Base.axes(s::StaticArray) = _axes(Size(s))
@pure function _axes(::Size{sizes}) where {sizes}
function _axes(::Size{sizes}) where {sizes}
map(SOneTo, sizes)
end
Base.axes(rv::Adjoint{<:Any,<:StaticVector}) = (SOneTo(1), axes(rv.parent)...)
Expand Down Expand Up @@ -86,9 +86,9 @@ sizedarray_similar_type(::Type{T},s::Size{S},::Type{Val{D}}) where {T,S,D} = Siz
# Utility for computing the eltype of an array instance, type, or type
# constructor. For type constructors without a definite eltype, the default
# value is returned.
Base.@pure _eltype_or(a::AbstractArray, default) = eltype(a)
Base.@pure _eltype_or(::Type{<:AbstractArray{T}}, default) where {T} = T
Base.@pure _eltype_or(::Type{<:AbstractArray}, default) = default # eltype not available
_eltype_or(a::AbstractArray, default) = eltype(a)
_eltype_or(::Type{<:AbstractArray{T}}, default) where {T} = T
_eltype_or(::Type{<:AbstractArray}, default) = default # eltype not available

"""
_construct_similar(a, ::Size, elements::NTuple)
Expand Down
30 changes: 15 additions & 15 deletions src/convert.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ Length(x::Args) = Length(length(x.args))
const BadArgs = Args{<:Tuple{Tuple{<:Tuple}}}

# Some help functions.
@pure has_ndims(::Type{<:StaticArray{<:Tuple,<:Any,N}}) where {N} = @isdefined N
@pure has_ndims(::Type{<:StaticArray}) = false
has_ndims(::Type{<:StaticArray{<:Tuple,<:Any,N}}) where {N} = true
has_ndims(::Type{<:StaticArray}) = false
if VERSION < v"1.7"
Base.ndims(::Type{<:StaticArray{<:Tuple,<:Any,N}}) where {N} = N
Base.ndims(::Type{<:StaticArray{<:Tuple,<:Any,N}}) where {N} = true
end
@pure has_eltype(::Type{<:StaticArray{<:Tuple,T}}) where {T} = @isdefined T
@pure has_eltype(::Type{<:StaticArray}) = false
@pure has_size(::Type{<:StaticArray{S}}) where {S<:Tuple} = @isdefined S
@pure has_size(::Type{<:StaticArray}) = false
has_eltype(::Type{<:StaticArray{<:Tuple,T}}) where {T} = true
has_eltype(::Type{<:StaticArray}) = false
has_size(::Type{<:StaticArray{S}}) where {S<:Tuple} = true
has_size(::Type{<:StaticArray}) = false
# workaround for https://github.com/JuliaArrays/StaticArrays.jl/issues/1047
has_size(::Type{SVector}) = false
has_size(::Type{MVector}) = false
Expand All @@ -27,11 +27,11 @@ has_size(::Type{MMatrix}) = false
has_size(::Type{SMatrix{N}}) where {N} = false
has_size(::Type{MMatrix{N}}) where {N} = false

@pure has_size1(::Type{<:StaticMatrix{M}}) where {M} = @isdefined M
@pure has_size1(::Type{<:StaticMatrix}) = false
has_size1(::Type{<:StaticMatrix{M}}) where {M} = true
has_size1(::Type{<:StaticMatrix}) = false
_size1(::Type{<:StaticMatrix{M}}) where {M} = M
@generated function _sqrt(::Length{L}) where {L}
N = round(Int, sqrt(L))
N = isqrt(L)
N^2 == L && return :($N)
throw(DimensionMismatch("Input's length must be perfect square"))
end
Expand All @@ -40,15 +40,15 @@ end
SA′ = construct_type(::Type{SA}, x) where {SA<:StaticArray}

Pick a proper constructor `SA′` based on `x` if `SA(x)`/`SA(x...)` has no specific definition.
The default returned `SA′` is `SA` itself for user defined `StaticArray`s. This differs from
The default returned `SA′` is `SA` itself for user defined `StaticArray`s. This differs from
`similar_type()` in that `SA′` should always be a subtype of `SA`.

!!! note
To distinguish `SA(x...)` and `SA(x::Tuple)`, the former calls
To distinguish `SA(x...)` and `SA(x::Tuple)`, the former calls
`construct_type(SA, StaticArrays.Args(x))` instead of `construct_type(SA, x)`.

!!! note
Please make sure `SA'(x)` has a specific definition if the default behavior is overloaded.
Please make sure `SA'(x)` has a specific definition if the default behavior is overloaded.
Otherwise construction might fall into infinite recursion.

---
Expand All @@ -66,7 +66,7 @@ The adaption rules for offical `StaticArray`s could be summarized as:

If `SA` is not fully static-sized, then we always try to fill `SA` with `x`'s elements,
and the constructor's `Size` is derived based on:
1. If `SA <: StaticVector`, then we use `length(x)` as the output `Length`
1. If `SA <: StaticVector`, then we use `length(x)` as the output `Length`
2. If `SA <: StaticMatrix{M}`, then we use `(M, N)` (`N = length(x) ÷ M`) as the output `Size`
3. If `SA <: StaticMatrix{M,M} where M`, then we use `(N, N)` (`N = sqrt(length(x)`) as the output `Size`.
- SA(x...)
Expand Down Expand Up @@ -215,4 +215,4 @@ end

# `float` and `real` of StaticArray types, analogously to application to scalars (issue 935)
float(::Type{SA}) where SA<:StaticArray{_S,T,_N} where {_S,T,_N} = similar_type(SA, float(T))
real(::Type{SA}) where SA<:StaticArray{_S,T,_N} where {_S,T,_N} = similar_type(SA, real(T))
real(::Type{SA}) where SA<:StaticArray{_S,T,_N} where {_S,T,_N} = similar_type(SA, real(T))
2 changes: 1 addition & 1 deletion src/indexing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ end
## Indexing utilities ##
#########################

@pure unpack_size(::Type{Size{S}}) where {S} = map(Size, S)
unpack_size(::Type{Size{S}}) where {S} = map(Size, S)

@inline index_size(::Size, ::Int) = Size()
@inline index_size(::Size, a::StaticArray) = Size(a)
Expand Down
6 changes: 2 additions & 4 deletions src/initializers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,9 @@ const SA_F64 = SA{Float64}
@inline Base.typed_hcat(sa::Type{SA}, xs::Number...) = similar_type(sa, Size(1,length(xs)))(xs)
@inline Base.typed_hcat(sa::Type{SA{T}}, xs::Number...) where T = similar_type(sa, Size(1,length(xs)))(xs)

Base.@pure function _SA_hvcat_transposed_size(rows)
function _SA_hvcat_transposed_size(rows)
M = rows[1]
if any(r->r != M, rows)
# @pure may not throw... probably. See
# https://discourse.julialang.org/t/can-pure-functions-throw-an-error/18459
return nothing
end
Size(M, length(rows))
Expand All @@ -65,7 +63,7 @@ if VERSION >= v"1.7"
args = (:(x[$i]) for i in a)
return :(tuple($(args...)))
end

@inline function _SA_typed_hvncat(sa, dimsshape, row_first, xs)
msize = Size(dimsshape)
xs′ = row_first ? reorder(xs, Val(msize[1]), Val(msize[2])) : xs
Expand Down
32 changes: 15 additions & 17 deletions src/traits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,34 +33,32 @@ Base.show(io::IO, ::Length{L}) where {L} = print(io, "Length(", L, ")")

Length(a::AbstractArray) = Length(Size(a))
Length(::Type{A}) where {A <: AbstractArray} = Length(Size(A))
@pure Length(L::Int) = Length{L}()
Length(L::Int) = Length{L}()
Length(::Size{S}) where {S} = _Length(S...)
@pure _Length(S::Int...) = Length{prod(S)}()
_Length(S::Int...) = Length{prod(S)}()
@inline _Length(S...) = Length{Dynamic()}()

# Some @pure convenience functions for `Size`
@pure (::Type{Tuple})(::Size{S}) where {S} = S
(::Type{Tuple})(::Size{S}) where {S} = S

@pure getindex(::Size{S}, i::Int) where {S} = i <= length(S) ? S[i] : 1
getindex(::Size{S}, i::Int) where {S} = i <= length(S) ? S[i] : 1

@pure length(::Size{S}) where {S} = length(S)
@pure length_val(::Size{S}) where {S} = Val{length(S)}
length(::Size{S}) where {S} = length(S)
length_val(::Size{S}) where {S} = Val{length(S)}

# Note - using === here, as Base doesn't inline == for tuples as of julia-0.6
@pure Base.:(==)(::Size{S}, s::Tuple{Vararg{Int}}) where {S} = S === s
@pure Base.:(==)(s::Tuple{Vararg{Int}}, ::Size{S}) where {S} = s === S
Base.:(==)(::Size{S}, s::Tuple{Vararg{Int}}) where {S} = S === s
Base.:(==)(s::Tuple{Vararg{Int}}, ::Size{S}) where {S} = s === S

@pure Base.prod(::Size{S}) where {S} = prod(S)
Base.prod(::Size{S}) where {S} = prod(S)

Base.LinearIndices(::Size{S}) where {S} = LinearIndices(S)

@pure size_tuple(::Size{S}) where {S} = Tuple{S...}
size_tuple(::Size{S}) where {S} = Tuple{S...}

# Some @pure convenience functions for `Length`
@pure (::Type{Int})(::Length{L}) where {L} = L
(::Type{Int})(::Length{L}) where {L} = L

@pure Base.:(==)(::Length{L}, l::Int) where {L} = L == l
@pure Base.:(==)(l::Int, ::Length{L}) where {L} = l == L
Base.:(==)(::Length{L}, l::Int) where {L} = L == l
Base.:(==)(l::Int, ::Length{L}) where {L} = l == L

# unroll_tuple also works with `Length`
@propagate_inbounds unroll_tuple(f, ::Length{L}) where {L} = unroll_tuple(f, Val{L})
Expand All @@ -72,7 +70,7 @@ Base.LinearIndices(::Size{S}) where {S} = LinearIndices(S)
Determine whether two sizes match, in the sense that they have the same
number of dimensions, and their dimensions match as determined by [`dimmatch`](@ref).
"""
@pure sizematch(::Size{S1}, ::Size{S2}) where {S1, S2} = sizematch(S1, S2)
sizematch(::Size{S1}, ::Size{S2}) where {S1, S2} = sizematch(S1, S2)
@inline sizematch(::Tuple{}, ::Tuple{}) = true
@inline sizematch(S1::Tuple{Vararg{StaticDimension, N}}, S2::Tuple{Vararg{StaticDimension, N}}) where {N} =
dimmatch(S1[1], S2[1]) && sizematch(Base.tail(S1), Base.tail(S2))
Expand Down Expand Up @@ -115,4 +113,4 @@ end

# Return the "diagonal size" of a matrix - the minimum of the two dimensions
diagsize(A::StaticMatrix) = diagsize(Size(A))
@pure diagsize(::Size{S}) where {S} = min(S...)
diagsize(::Size{S}) where {S} = min(S...)