JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.15k stars 5.45k forks source link

Problem with `similar` called for view-types such as `SubArray`, `ReshapedArray` or `ReinterpretArray` #54849

Open RainerHeintzmann opened 1 month ago

RainerHeintzmann commented 1 month ago

There is a problem with the type based similar method, applied to a view (SubArray), a reshaped array (Base.ReshapedArray) or a reinterpreted array (Base.ReinterpretArray), since these array modifications doe not have constructors, which can directly be called. Here is an example (Julia 1.10.4):

julia> A = @view ones(10,10)[1:20];

julia> similar(typeof(A), axes(A));
ERROR: MethodError: no method matching SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}(::UndefInitializer, ::Tuple{Int64})

Closest candidates are:
  SubArray{T, N, P, I, L}(::Any, ::Any, ::Any, ::Any) where {T, N, P, I, L}
   @ Base subarray.jl:19

Stacktrace:
 [1] similar(::Type{SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}}, dims::Tuple{Int64})
   @ Base .\abstractarray.jl:877

I suggest the following fix in base/abstractarray.jl:

Base.similar(::Type{TA}, dims::Dims) where {T,N,P,TA<:SubArray{T,N,P}} = similar(P, dims)
Base.similar(::Type{TA}, dims::Dims) where {T,N,P,TA<:Base.ReshapedArray{T,N,P}} = similar(P, dims)
Base.similar(::Type{TA}, dims::Dims) where {T,N,O,P,TA<:Base.ReinterpretArray{T,N,O,P}} = similar(P, dims)

This should then unravel nested version of these array views. The exact Version details:

julia> versioninfo()
Julia Version 1.10.4
Commit 48d4fd4843 (2024-06-04 10:41 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 16 × 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, tigerlake)
Threads: 16 default, 0 interactive, 8 GC (on 16 virtual cores)
Environment:
  JULIA_NUM_THREADS = auto
  JULIA_EDITOR = code
mbauman commented 1 month ago

This seems like a good idea!

RainerHeintzmann commented 1 month ago

Should I make a pull request?