You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add push! implementation for AbstractArray depending only on resize! (JuliaLang#55470)
FixJuliaLang#55459
In Julia 1.10, `push!` and `append!` would be functional for
`AbstractVector` implementations
if `resize!` and `setindex!` were defined.
As of JuliaLang#51903 by @vtjnash as in Julia 1.11.0-rc2, `append!` now depends
on an implementation of
`sizehint!` and `push!`. Since `push!` also depends on `append!`, a
stack
overflow situation can easily be created.
To avoid this, this pull request defines the following
* Add generic versions of `push!(a::AbstractVector, x)` which do not
depend on `append!`
* Add default implementation of `sizehint!` that is a no-op
The implementation of `push!(a::AbstractVector, x)` is a generic version
based on the implementation
of `push!(a::Vector, x)` without depending on internals.
# Example for SimpleArray
Consider the `SimpleArray` example from test/abstractarray.jl:
```julia
mutable struct SimpleArray{T} <: AbstractVector{T}
els::Vector{T}
end
Base.size(sa::SimpleArray) = size(sa.els)
Base.getindex(sa::SimpleArray, idx...) = getindex(sa.els, idx...)
Base.setindex!(sa::SimpleArray, v, idx...) = setindex!(sa.els, v, idx...)
Base.resize!(sa::SimpleArray, n) = resize!(sa.els, n)
Base.copy(sa::SimpleArray) = SimpleArray(copy(sa.els))
```
Note that `setindex!` and `resize!` are implemented for `SimpleArray`.
## Julia 1.10.4: push! is functional
On Julia 1.10.4, `push!` has a functional implementation for
`SimpleArray`
```julia-repl
julia> push!(SimpleArray{Int}(zeros(Int,5)), 6)
6-element SimpleArray{Int64}:
0
0
0
0
0
6
```
## Julia 1.11.0-rc2 and nightly: push! requires sizehint! and is prone
to stack overflow
Before this pull request, on Julia 1.11.0-rc2 and nightly, `push!` fails
for want of `sizehint!`.
```julia-repl
julia> push!(SimpleArray{Int}(zeros(Int,5)), 6)
ERROR: MethodError: no method matching sizehint!(::SimpleArray{Int64}, ::Int64)
The function `sizehint!` exists, but no method is defined for this combination of argument types.
...
```
After implementing `sizehint!`, `push!` still fails with a stack
overflow.
```julia-repl
julia> Base.sizehint!(a::SimpleArray, x) = a
julia> push!(SimpleArray{Int}(zeros(Int, 5)), 6)
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
ERROR: StackOverflowError:
Stacktrace:
[1] _append!
@ ./array.jl:1344 [inlined]
[2] append!
@ ./array.jl:1335 [inlined]
[3] push!(a::SimpleArray{Int64}, iter::Int64)
@ Base ./array.jl:1336
--- the above 3 lines are repeated 79982 more times ---
[239950] _append!
@ ./array.jl:1344 [inlined]
[239951] append!
@ ./array.jl:1335 [inlined]
```
This is because the new implementation of `append!` depends on `push!`.
## After this pull request, push! is functional.
After this pull request, there is a functional `push!` for `SimpleArray`
again as in Julia 1.10.4:
```julia-repl
julia> push!(SimpleArray{Int}(zeros(Int, 5), 6)
6-element SimpleArray{Int64}:
0
0
0
0
0
6
```
0 commit comments