@@ -33,17 +33,17 @@ const LoTri{T,M} = Union{LowerTriangular{T,M},UnitLowerTriangular{T,M}}
3333Returns the parent array that type `T` wraps.
3434"""
3535parent_type (x) = parent_type (typeof (x))
36- parent_type (:: Type{<:SubArray{T,N,P}} ) where {T,N,P} = P
37- parent_type (:: Type{<:Base.ReshapedArray{T,N,P}} ) where {T,N,P} = P
38- parent_type (:: Type{Adjoint{T,S}} ) where {T,S} = S
39- parent_type (:: Type{Transpose{T,S}} ) where {T,S} = S
4036parent_type (:: Type{Symmetric{T,S}} ) where {T,S} = S
4137parent_type (:: Type{<:AbstractTriangular{T,S}} ) where {T,S} = S
42- parent_type (:: Type{<:PermutedDimsArray{T,N,I1,I2,A}} ) where {T,N,I1,I2,A} = A
43- parent_type (:: Type{Base.Slice{T}} ) where {T} = T
44- parent_type (:: Type{T} ) where {T} = T
45- parent_type (:: Type{R} ) where {S,T,A,N,R<: Base.ReinterpretArray{T,N,S,A} } = A
38+ parent_type (@nospecialize T:: Type{<:PermutedDimsArray} ) = fieldtype (T, :parent )
39+ parent_type (@nospecialize T:: Type{<:Adjoint} ) = fieldtype (T, :parent )
40+ parent_type (@nospecialize T:: Type{<:Transpose} ) = fieldtype (T, :parent )
41+ parent_type (@nospecialize T:: Type{<:SubArray} ) = fieldtype (T, :parent )
42+ parent_type (@nospecialize T:: Type{<:Base.ReinterpretArray} ) = fieldtype (T, :parent )
43+ parent_type (@nospecialize T:: Type{<:Base.ReshapedArray} ) = fieldtype (T, :parent )
44+ parent_type (@nospecialize T:: Type{<:Union{Base.Slice,Base.IdentityUnitRange}} ) = fieldtype (T, :indices )
4645parent_type (:: Type{Diagonal{T,V}} ) where {T,V} = V
46+ parent_type (T:: Type ) = T
4747
4848"""
4949 buffer(x)
@@ -54,6 +54,18 @@ may not return another array type.
5454buffer (x) = parent (x)
5555buffer (x:: SparseMatrixCSC ) = getfield (x, :nzval )
5656buffer (x:: SparseVector ) = getfield (x, :nzval )
57+ buffer (@nospecialize x:: Union{Base.Slice,Base.IdentityUnitRange} ) = getfield (x, :indices )
58+
59+ """
60+ is_forwarding_wrapper(::Type{T}) -> Bool
61+
62+ Returns `true` if the type `T` wraps another data type and does not alter any of its
63+ standard interface. For example, if `T` were an array then its size, indices, and elements
64+ would all be equivalent to its wrapped data.
65+ """
66+ is_forwarding_wrapper (T:: Type ) = false
67+ is_forwarding_wrapper (@nospecialize T:: Type{<:Base.Slice} ) = true
68+ is_forwarding_wrapper (@nospecialize x) = is_forwarding_wrapper (typeof (x))
5769
5870"""
5971 can_change_size(::Type{T}) -> Bool
@@ -62,7 +74,9 @@ Returns `true` if the Base.size of `T` can change, in which case operations
6274such as `pop!` and `popfirst!` are available for collections of type `T`.
6375"""
6476can_change_size (x) = can_change_size (typeof (x))
65- can_change_size (:: Type{T} ) where {T} = false
77+ function can_change_size (:: Type{T} ) where {T}
78+ is_forwarding_wrapper (T) ? can_change_size (parent_type (T)) : false
79+ end
6680can_change_size (:: Type{<:Vector} ) = true
6781can_change_size (:: Type{<:AbstractDict} ) = true
6882can_change_size (:: Type{<:Base.ImmutableDict} ) = false
123137Query whether a type can use `setindex!`.
124138"""
125139can_setindex (x) = can_setindex (typeof (x))
126- can_setindex (:: Type ) = true
127- can_setindex (:: Type{<:AbstractRange} ) = false
140+ can_setindex (T :: Type ) = is_forwarding_wrapper (T) ? can_setindex ( parent_type (T)) : true
141+ can_setindex (@nospecialize T :: Type{<:AbstractRange} ) = false
128142can_setindex (:: Type{<:AbstractDict} ) = true
129143can_setindex (:: Type{<:Base.ImmutableDict} ) = false
130144can_setindex (@nospecialize T:: Type{<:Tuple} ) = false
@@ -463,15 +477,10 @@ julia> ArrayInterface.known_first(typeof(Base.OneTo(4)))
463477```
464478"""
465479known_first (x) = known_first (typeof (x))
466- function known_first (:: Type{T} ) where {T}
467- if parent_type (T) <: T
468- return nothing
469- else
470- return known_first (parent_type (T))
471- end
472- end
473- known_first (:: Type{Base.OneTo{T}} ) where {T} = 1
474- known_first (:: Type{<:Base.IdentityUnitRange{T}} ) where {T} = known_first (T)
480+ known_first (T:: Type ) = is_forwarding_wrapper (T) ? known_first (parent_type (T)) : nothing
481+ known_first (:: Type{<:Base.OneTo} ) = 1
482+ known_first (@nospecialize T:: Type{<:LinearIndices} ) = 1
483+ known_first (@nospecialize T:: Type{<:Base.IdentityUnitRange} ) = known_first (parent_type (T))
475484function known_first (:: Type{<:CartesianIndices{N,R}} ) where {N,R}
476485 _cartesian_index (ntuple (i -> known_first (R. parameters[i]), Val (N)))
477486end
@@ -483,16 +492,16 @@ If `last` of an instance of type `T` is known at compile time, return it.
483492Otherwise, return `nothing`.
484493
485494```julia
486- julia> ArrayInterface .known_last(typeof(1:4))
495+ julia> ArrayInterfaceCore .known_last(typeof(1:4))
487496nothing
488497
489- julia> ArrayInterface .known_first(typeof(static(1):static(4)))
498+ julia> ArrayInterfaceCore .known_first(typeof(static(1):static(4)))
4904994
491500
492501```
493502"""
494503known_last (x) = known_last (typeof (x))
495- known_last (:: Type{T} ) where {T} = parent_type (T) <: T ? nothing : known_last (parent_type (T))
504+ known_last (T :: Type ) = is_forwarding_wrapper (T) ? known_last (parent_type (T)) : nothing
496505function known_last (:: Type{<:CartesianIndices{N,R}} ) where {N,R}
497506 _cartesian_index (ntuple (i -> known_last (R. parameters[i]), Val (N)))
498507end
@@ -513,12 +522,12 @@ julia> ArrayInterface.known_step(typeof(1:4))
513522```
514523"""
515524known_step (x) = known_step (typeof (x))
516- known_step (:: Type{T} ) where {T} = parent_type (T) <: T ? nothing : known_step (parent_type (T))
525+ known_step (T :: Type ) = is_forwarding_wrapper (T) ? known_step (parent_type (T)) : nothing
517526known_step (@nospecialize T:: Type{<:AbstractUnitRange} ) = 1
518527
519528"""
520529 is_splat_index(::Type{T}) -> Bool
521- Returns `static(true)` if `T` is a type that splats across multiple dimensions.
530+ Returns `static(true)` if `T` is a type that splats across multiple dimensions.
522531"""
523532is_splat_index (T:: Type ) = false
524533is_splat_index (@nospecialize (x)) = is_splat_index (typeof (x))
@@ -536,7 +545,7 @@ ndims_index(::Type{CartesianIndices{0,Tuple{}}}) = 1
536545ndims_index (@nospecialize T:: Type{<:AbstractArray{Bool}} ) = ndims (T)
537546ndims_index (@nospecialize T:: Type{<:AbstractArray} ) = ndims_index (eltype (T))
538547ndims_index (@nospecialize T:: Type{<:Base.LogicalIndex} ) = ndims (fieldtype (T, :mask ))
539- ndims_index (T:: DataType ) = 1
548+ ndims_index (T:: Type ) = 1
540549ndims_index (@nospecialize (i)) = ndims_index (typeof (i))
541550
542551"""
0 commit comments