Skip to content

Commit 7b3cf6b

Browse files
Merge pull request #245 from JuliaArrays/nothing
Revert missing to nothings
2 parents 63617dd + d497de8 commit 7b3cf6b

File tree

15 files changed

+178
-155
lines changed

15 files changed

+178
-155
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ jobs:
5252
- uses: julia-actions/setup-julia@latest
5353
with:
5454
version: '1.2'
55+
- run: julia --color=yes -e 'using Pkg; VERSION >= v"1.5-" && !isdir(joinpath(DEPOT_PATH[1], "registries", "General")) && Pkg.Registry.add("General")'
56+
shell: bash
57+
env:
58+
JULIA_PKG_SERVER: ""
5559
- run: julia --project=docs -e '
5660
using Pkg;
5761
Pkg.develop(PackageSpec(; path=pwd()));

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ArrayInterface"
22
uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
3-
version = "4.0.4"
3+
version = "5.0.0"
44

55
[deps]
66
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
@@ -14,5 +14,5 @@ Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
1414
Compat = "3.37"
1515
IfElse = "0.1"
1616
Requires = "0.5, 1.0"
17-
Static = "0.5"
17+
Static = "0.6"
1818
julia = "1.2"

docs/src/index.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ julia> ArrayInterface.size(a)
4444
(static(1), 3)
4545

4646
julia> ArrayInterface.known_size(typeof(a))
47-
(1, missing)
47+
(1, nothing)
4848

4949
```
5050

@@ -62,8 +62,8 @@ Methods should avoid forcing conversion to static sizes when dynamic sizes could
6262
Fore example, `fxn(x) = _fxn(Static.static(ArrayInterface.size(x)), x)` would result in dynamic dispatch if `x` is an instance of `Matrix`.
6363
Additionally, `ArrayInterface.size` should only be used outside of generated functions to avoid possible world age issues.
6464

65-
Generally, `ArrayInterface.size` uses the return of `known_size` to form a static value for those dimensions with known length and only queries dimensions corresponding to `missing`.
66-
For example, the previous example had a known size of `(1, missing)`.
65+
Generally, `ArrayInterface.size` uses the return of `known_size` to form a static value for those dimensions with known length and only queries dimensions corresponding to `nothing`.
66+
For example, the previous example had a known size of `(1, nothing)`.
6767
Therefore, `ArrayInterface.size` would have compile time information about the first dimension returned as `static(1)` and would only look up the size of the second dimension at run time.
6868
This means the above example `ArrayInterface.size(a)` would lower to code similar to this at compile time: `Static.StaticInt(1), Base.arraysize(x, 1)`.
6969
Generic support for `ArrayInterface.known_size` relies on calling `known_length` for each type returned from `axes_types`.
@@ -108,13 +108,13 @@ ArrayInterface.dimnames(::StaticDimnames{dnames}) where {dnames} = static(dnames
108108
struct DynamicDimnames{N}
109109
dimnames::NTuple{N,Symbol}
110110
end
111-
ArrayInterface.known_dimnames(::Type{DynamicDimnames{N}}) where {N} = ntuple(_-> missing, Val(N))
111+
ArrayInterface.known_dimnames(::Type{DynamicDimnames{N}}) where {N} = ntuple(_-> nothing, Val(N))
112112
ArrayInterface.dimnames(x::DynamicDimnames) = getfield(x, :dimnames)
113113

114114
```
115115

116-
Notice that `DynamicDimnames` returns `missing` instead of a symbol for each dimension.
117-
This indicates dimension names are present for `DynamicDimnames` but that information is missing at compile time.
116+
Notice that `DynamicDimnames` returns `nothing` instead of a symbol for each dimension.
117+
This indicates dimension names are present for `DynamicDimnames` but that information is nothing at compile time.
118118

119119
Dimension names should be appropriately propagated between nested arrays using `ArrayInterface.to_parent_dims`.
120120
This allows types such as `SubArray` and `PermutedDimsArray` to work with named dimensions.
@@ -166,7 +166,7 @@ using ArrayInterface: axes_types, parent_type, to_dims
166166
for dim in 1:ndims(A)
167167
# offset relative to parent array
168168
O = relative_known_offsets(A, dim)
169-
if O === missing # offset is not known at compile time and is an `Int`
169+
if O === nothing # offset is not known at compile time and is an `Int`
170170
push!(out.args, :(IdOffsetRange{Int, axes_types($P, $(static(dim)))}))
171171
else # offset is known, therefore it is a `StaticInt`
172172
push!(out.args, :(IdOffsetRange{StaticInt{$O}, axes_types($P, $(static(dim))}))

src/ArrayInterface.jl

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ buffer(x::SparseMatrixCSC) = getfield(x, :nzval)
8181
buffer(x::SparseVector) = getfield(x, :nzval)
8282

8383
"""
84-
known_length(::Type{T}) -> Union{Int,Missing}
84+
known_length(::Type{T}) -> Union{Int,Nothing}
8585
8686
If `length` of an instance of type `T` is known at compile time, return it.
87-
Otherwise, return `missing`.
87+
Otherwise, return `nothing`.
8888
"""
8989
known_length(x) = known_length(typeof(x))
9090
known_length(::Type{<:NamedTuple{L}}) where {L} = length(L)
@@ -93,10 +93,28 @@ known_length(::Type{<:Tuple{Vararg{Any,N}}}) where {N} = N
9393
known_length(::Type{<:Number}) = 1
9494
known_length(::Type{<:AbstractCartesianIndex{N}}) where {N} = N
9595
known_length(::Type{T}) where {T} = _maybe_known_length(Base.IteratorSize(T), T)
96-
_maybe_known_length(::Base.HasShape, ::Type{T}) where {T} = prod(known_size(T))
97-
_maybe_known_length(::Base.IteratorSize, ::Type) = missing
96+
97+
@generated function _prod_or_nothing(x::Tuple)
98+
p = 1
99+
for i in eachindex(x.parameters)
100+
x.parameters[i] === Nothing && return nothing
101+
p *= x.parameters[i].parameters[1]
102+
end
103+
StaticInt(p)
104+
end
105+
106+
function _maybe_known_length(::Base.HasShape, ::Type{T}) where {T}
107+
t = map(_static_or_nothing, known_size(T))
108+
_int_or_nothing(_prod_or_nothing(t))
109+
end
110+
111+
_maybe_known_length(::Base.IteratorSize, ::Type) = nothing
112+
_static_or_nothing(::Nothing) = nothing
113+
@inline _static_or_nothing(x::Int) = StaticInt{x}()
114+
_int_or_nothing(::StaticInt{N}) where {N} = N
115+
_int_or_nothing(::Nothing) = nothing
98116
function known_length(::Type{<:Iterators.Flatten{I}}) where {I}
99-
known_length(I) * known_length(eltype(I))
117+
_int_or_nothing(_prod_or_nothing((_static_or_nothing(known_length(I)),_static_or_nothing(known_length(eltype(I))))))
100118
end
101119

102120
"""
@@ -415,10 +433,10 @@ Indicates the most efficient way to access elements from the collection in low-l
415433
For `GPUArrays`, will return `ArrayInterface.GPU()`.
416434
For `AbstractArray` supporting a `pointer` method, returns `ArrayInterface.CPUPointer()`.
417435
For other `AbstractArray`s and `Tuple`s, returns `ArrayInterface.CPUIndex()`.
418-
Otherwise, returns `missing`.
436+
Otherwise, returns `nothing`.
419437
"""
420438
device(A) = device(typeof(A))
421-
device(::Type) = missing
439+
device(::Type) = nothing
422440
device(::Type{<:Tuple}) = CPUTuple()
423441
device(::Type{T}) where {T<:Array} = CPUPointer()
424442
device(::Type{T}) where {T<:AbstractArray} = _device(has_parent(T), T)
@@ -597,7 +615,7 @@ end
597615

598616
function Base.length(A::AbstractArray2)
599617
len = known_length(A)
600-
if len === missing
618+
if len === nothing
601619
return Int(prod(size(A)))
602620
else
603621
return Int(len)
@@ -1136,7 +1154,7 @@ function __init__()
11361154
Static.eachop_tuple(_offset_axis_type, Static.nstatic(Val(ndims(T))), ArrayInterface.parent_type(T))
11371155
end
11381156
function ArrayInterface.known_offsets(::Type{A}) where {A<:OffsetArrays.OffsetArray}
1139-
ntuple(identity -> missing, Val(ndims(A)))
1157+
ntuple(identity -> nothing, Val(ndims(A)))
11401158
end
11411159
function ArrayInterface.offsets(A::OffsetArrays.OffsetArray)
11421160
map(+, ArrayInterface.offsets(parent(A)), relative_offsets(A))

src/axes.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function axes_types(::Type{T}) where {T<:PermutedDimsArray}
4141
eachop_tuple(field_type, to_parent_dims(T), axes_types(parent_type(T)))
4242
end
4343
function axes_types(::Type{T}) where {T<:AbstractRange}
44-
if known_length(T) === missing
44+
if known_length(T) === nothing
4545
return Tuple{OneTo{Int}}
4646
else
4747
return Tuple{SOneTo{known_length(T)}}
@@ -62,7 +62,7 @@ end
6262
function _non_reshaped_axis_type(::Type{A}, d::StaticInt{D}) where {A,D}
6363
paxis = axes_types(parent_type(A), d)
6464
if D === 1
65-
if known_length(paxis) === missing
65+
if known_length(paxis) === nothing
6666
return paxis
6767
else
6868
return SOneTo{div(known_length(paxis) * sizeof(eltype(parent_type(A))), sizeof(eltype(A)))}
@@ -191,7 +191,7 @@ end
191191
# For now we just make sure the linear elements are accurate.
192192
parent_type(::Type{LazyAxis{:,P}}) where {P<:Array} = OneTo{Int}
193193
@inline function parent_type(::Type{LazyAxis{:,P}}) where {P}
194-
if known_length(P) === missing
194+
if known_length(P) === nothing
195195
return OptionallyStaticUnitRange{StaticInt{1},Int}
196196
else
197197
return SOneTo{known_length(P)}
@@ -208,14 +208,14 @@ known_first(::Type{LazyAxis{N,P}}) where {N,P} = known_offsets(P, static(N))
208208
known_first(::Type{LazyAxis{:,P}}) where {P} = 1
209209
Base.firstindex(x::LazyAxis) = first(x)
210210
@inline function Base.first(x::LazyAxis{N})::Int where {N}
211-
if known_first(x) === missing
211+
if known_first(x) === nothing
212212
return Int(offsets(parent(x), static(N)))
213213
else
214214
return Int(known_first(x))
215215
end
216216
end
217217
@inline function Base.first(x::LazyAxis{:})::Int
218-
if known_first(x) === missing
218+
if known_first(x) === nothing
219219
return first(parent(x))
220220
else
221221
return known_first(x)
@@ -225,20 +225,20 @@ known_last(::Type{LazyAxis{N,P}}) where {N,P} = known_last(axes_types(P, static(
225225
known_last(::Type{LazyAxis{:,P}}) where {P} = known_length(P)
226226
Base.lastindex(x::LazyAxis) = last(x)
227227
Base.last(x::LazyAxis) = _last(known_last(x), x)
228-
_last(::Missing, x) = last(parent(x))
228+
_last(::Nothing, x) = last(parent(x))
229229
_last(N::Int, x) = N
230230

231231
known_length(::Type{LazyAxis{N,P}}) where {N,P} = known_size(P, static(N))
232232
known_length(::Type{LazyAxis{:,P}}) where {P} = known_length(P)
233233
@inline function Base.length(x::LazyAxis{N})::Int where {N}
234-
if known_length(x) === missing
234+
if known_length(x) === nothing
235235
return size(getfield(x, :parent), static(N))
236236
else
237237
return known_length(x)
238238
end
239239
end
240240
@inline function Base.length(x::LazyAxis{:})::Int
241-
if known_length(x) === missing
241+
if known_length(x) === nothing
242242
return length(parent(x))
243243
else
244244
return known_length(x)
@@ -254,7 +254,7 @@ Base.axes1(x::Slice{<:LazyAxis}) = indices(parent(x.indices))
254254
Base.to_shape(x::LazyAxis) = length(x)
255255

256256
@inline function Base.checkindex(::Type{Bool}, x::LazyAxis, i::Integer)
257-
if known_first(x) === missing || known_last(x) === missing
257+
if known_first(x) === nothing || known_last(x) === nothing
258258
return checkindex(Bool, parent(x), i)
259259
else # everything is static so we don't have to retrieve the axis
260260
return (!(known_first(x) > i) || !(known_last(x) < i))

src/dimensions.jl

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ _is_named(x::NTuple{N,Symbol}) where {N} = x !== _nunderscore(Val(N))
160160
_is_named(::Any) = true
161161

162162
"""
163-
known_dimnames(::Type{T}) -> Tuple{Vararg{Union{Symbol,Missing}}}
164-
known_dimnames(::Type{T}, dim::Union{Int,StaticInt}) -> Union{Symbol,Missing}
163+
known_dimnames(::Type{T}) -> Tuple{Vararg{Union{Symbol,Nothing}}}
164+
known_dimnames(::Type{T}, dim::Union{Int,StaticInt}) -> Union{Symbol,Nothing}
165165
166166
Return the names of the dimensions for `x`. `:_` is used to indicate a dimension does not
167167
have a name.
@@ -176,7 +176,8 @@ function _known_dimnames(::Type{C}, ::Type{P}) where {C,P}
176176
eachop(_inbounds_known_dimname, to_parent_dims(C), known_dimnames(P))
177177
end
178178
@inline function _known_dimname(x::Tuple{Vararg{Any,N}}, dim::CanonicalInt) where {N}
179-
@boundscheck (dim > N || dim < 1) && return :_
179+
# we cannot have `@boundscheck`, else this will depend on bounds checking being enabled
180+
(dim > N || dim < 1) && return :_
180181
return @inbounds(x[dim])
181182
end
182183
@inline _inbounds_known_dimname(x, dim) = @inbounds(_known_dimname(x, dim))
@@ -195,7 +196,9 @@ have a name.
195196
end
196197
_dimnames(::False, x) = ntuple(_->static(:_), Val(ndims(x)))
197198
@inline function _dimname(x::Tuple{Vararg{Any,N}}, dim::CanonicalInt) where {N}
198-
@boundscheck (dim > N || dim < 1) && return static(:_)
199+
# we cannot have `@boundscheck`, else this will depend on bounds checking being enabled
200+
# for calls such as `dimnames(view(x, :, 1, :))`
201+
(dim > N || dim < 1) && return static(:_)
199202
return @inbounds(x[dim])
200203
end
201204
@inline _inbounds_dimname(x, dim) = @inbounds(_dimname(x, dim))
@@ -229,7 +232,7 @@ An error is thrown if any keywords are used which do not occur in `nda`'s names.
229232
230233
1. parse into static dimnension names and key words.
231234
2. find each dimnames in key words
232-
3. if missing is found use Colon()
235+
3. if nothing is found use Colon()
233236
4. if (ndims - ncolon) === nkwargs then all were found, else error
234237
=#
235238
@generated function find_all_dimnames(x::Tuple{Vararg{Any,ND}}, nd::Tuple{Vararg{Any,NI}}, inds::Tuple, default) where {ND,NI}

src/indexing.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ previously executed `to_index(old_axis, arg) -> index`. `to_axis` assumes that
277277
"""
278278
@inline function to_axis(axis, inds)
279279
if !can_change_size(axis) &&
280-
(known_length(inds) !== missing && known_length(axis) === known_length(inds))
280+
(known_length(inds) !== nothing && known_length(axis) === known_length(inds))
281281
return axis
282282
else
283283
return to_axis(IndexStyle(axis), axis, inds)

0 commit comments

Comments
 (0)