diff --git a/src/vector_of_array.jl b/src/vector_of_array.jl index af4da6e9..95777e05 100644 --- a/src/vector_of_array.jl +++ b/src/vector_of_array.jl @@ -1167,16 +1167,21 @@ end # fill! # For DiffEqArray it ignores ts and fills only u function Base.fill!(VA::AbstractVectorOfArray, x) - for i in 1:length(VA.u) - if VA[:, i] isa Union{AbstractArray, AbstractVectorOfArray} - if ArrayInterface.ismutable(VA.u[i]) || VA.u[i] isa AbstractVectorOfArray - fill!(VA[:, i], x) + for i in eachindex(VA.u) + # Fill the inner array directly instead of through `VA[:, i]`, which + # for a ragged inner array builds and returns a zero-padded *copy* — + # filling that copy does not touch (and silently drops writes to) the + # real storage. + ui = VA.u[i] + if ui isa Union{AbstractArray, AbstractVectorOfArray} + if ArrayInterface.ismutable(ui) || ui isa AbstractVectorOfArray + fill!(ui, x) else # For immutable arrays like SVector, create a new filled array - VA.u[i] = fill(x, StaticArraysCore.similar_type(VA.u[i])) + VA.u[i] = fill(x, StaticArraysCore.similar_type(ui)) end else - VA[:, i] = x + VA.u[i] = x end end return VA diff --git a/test/Core/interface_tests.jl b/test/Core/interface_tests.jl index c4aa6ae8..59f45857 100644 --- a/test/Core/interface_tests.jl +++ b/test/Core/interface_tests.jl @@ -248,6 +248,14 @@ testda = DiffEqArray(recursivecopy(testva.u), testts) fill!(testda, testval) @test all(x -> (x == testval), testda) +# fill! on a ragged VectorOfArray must fill every inner array, not just the +# longest one. `VA[:, i]` zero-pads a shorter inner array into a throwaway +# copy, so filling through it (instead of through `VA.u[i]` directly) would +# silently drop the write for every inner array shorter than the max. +ragged_fill = VectorOfArray([[1.0, 2.0], [3.0], [4.0, 5.0, 6.0]]) +fill!(ragged_fill, 9.0) +@test ragged_fill.u == [[9.0, 9.0], [9.0], [9.0, 9.0, 9.0]] + # copyto! testva = VectorOfArray(collect(0.1:0.1:1.0)) arr = 0.2:0.2:2.0