From 059ae4d6cb2a0a0bc7091b46af54687ccb0e4404 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Fri, 24 Oct 2025 07:18:44 -0400 Subject: [PATCH] Fix recursivefill! failure with immutable StaticArrays (issue #461) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit fixes a bug where `recursivefill!` would fail when called on a `VectorOfArray` containing immutable `StaticArray` types like `SVector`. ## Problem The `Base.fill!` method for `AbstractVectorOfArray` attempted to call `fill!` on each element array, which fails for immutable arrays that don't support in-place modification via `setindex!`. ## Solution Modified `Base.fill!` to check if each element is mutable before attempting to fill it. For immutable arrays, we now create a new filled array using `StaticArraysCore.similar_type` and assign it, following the same pattern used in the existing `copyto!` implementation. ## Changes - Updated `Base.fill!` in `src/vector_of_array.jl` to handle both mutable and immutable arrays correctly - Added comprehensive tests in `test/utils_test.jl` to cover: - `VectorOfArray` with only immutable `SVector`s - `VectorOfArray` with mixed immutable and mutable `StaticArray`s - Both `recursivefill!` and `fill!` methods All existing tests continue to pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/vector_of_array.jl | 7 ++++++- test/utils_test.jl | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/vector_of_array.jl b/src/vector_of_array.jl index 98af2ddd..11029149 100644 --- a/src/vector_of_array.jl +++ b/src/vector_of_array.jl @@ -826,7 +826,12 @@ end function Base.fill!(VA::AbstractVectorOfArray, x) for i in 1:length(VA.u) if VA[:, i] isa AbstractArray - fill!(VA[:, i], x) + if ArrayInterface.ismutable(VA.u[i]) || VA.u[i] isa AbstractVectorOfArray + fill!(VA[:, i], x) + else + # For immutable arrays like SVector, create a new filled array + VA.u[i] = fill(x, StaticArraysCore.similar_type(VA.u[i])) + end else VA[:, i] = x end diff --git a/test/utils_test.jl b/test/utils_test.jl index 63f78238..9b9dbded 100644 --- a/test/utils_test.jl +++ b/test/utils_test.jl @@ -139,6 +139,35 @@ end @test u1.u[2] isa SVector end +# Test recursivefill! with immutable StaticArrays (issue #461) +@testset "recursivefill! with immutable StaticArrays (issue #461)" begin + # Test with only immutable SVectors + x = VectorOfArray([SVector{2}(ones(2)), SVector{2}(ones(2))]) + recursivefill!(x, 0.0) + @test all(x.u[i] == SVector{2}(zeros(2)) for i in 1:2) + @test all(x.u[i] isa SVector for i in 1:2) + + # Test with mixed immutable and mutable StaticArrays + x = VectorOfArray([SVector{2}(ones(2)), MVector{2}(ones(2))]) + recursivefill!(x, 0.0) + @test all(x.u[i] == [0.0, 0.0] for i in 1:2) + @test x.u[1] isa SVector + @test x.u[2] isa MVector + + # Test fill! on VectorOfArray with immutable SVectors + x = VectorOfArray([SVector{2}(ones(2)), SVector{2}(ones(2))]) + fill!(x, 0.0) + @test all(x.u[i] == SVector{2}(zeros(2)) for i in 1:2) + @test all(x.u[i] isa SVector for i in 1:2) + + # Test fill! on VectorOfArray with mixed types + x = VectorOfArray([SVector{2}(ones(2)), MVector{2}(ones(2))]) + fill!(x, 0.0) + @test all(x.u[i] == [0.0, 0.0] for i in 1:2) + @test x.u[1] isa SVector + @test x.u[2] isa MVector +end + import KernelAbstractions: get_backend @testset "KernelAbstractions" begin v = VectorOfArray([randn(2) for i in 1:10])