Description
After working a bit on #175, I feel that replace_storage
works well for arrays of primitive types, but it doesn't work well for wrapper array types.
Consider the following two array types:
struct MyVector{T, S} <: AbstractVector{T}
buffer::S
# potentially other fields
end
MyVector{T}(N) where T = MyVector{T, Vector{T}}(zeros(T, N))
struct ArrayOfMyVectors{T, N, S<:AbstractArray{T, N}, P} <: AbstractArray{P, N}
buffer::S
# inner constructor computes P correctly using Core.Compiler.return_type
end
For array types like ArrayOfMyVectors
, it is reasonable to want to return view into buffer
wrapped as a MyVector
. In other words,
x = ArrayOfMyVectors{T}(...)
typeof(x[1, 1]) == MyVector{T, SubArray{T, 1, S, ...}}
Now, suppose you have the following:
struct Foo{T}
bar::T
end
x = StructArray(Foo(MyVector{Int}(10)) for _ in 1:2, _ in 1:3)
replace_storage(x) do v
if v isa Array{<:MyVector}
return ArrayOfMyVectors{...}(...) # compute based on v
else
return v
end
end
This won't work, because the eltype(x.bar)
is originally MyVector{Int, Vector{Int}}
and the eltype
of the replaced storage is MyVector{Int, SubArray{...}}
. Note that unlike JuliaArrays/ArraysOfArrays.jl#2 the eltype
/getindex
are internally consistent for ArrayOfMyVectors
.
So, would it make sense to have a variant (different function or keyword arg) that behaved like replace_storage
but returned a StructArray
with a totally new eltype
? Am I just missing something completely here?