Skip to content

Commit

Permalink
More robust iteration over Vectors
Browse files Browse the repository at this point in the history
Currently, if a vector is resized in the midst of iteration, then `done` might "miss" the end of iteration. This trivially changes the definition to catch such a case. I am not sure what guarantees we make about mutating iterables during iteration, but this seems simple and easy to support.  Note, though, that it is somewhat tricky: until #13866 we used `i > length(a)`, but that foils vectorization due to the `typemax` case. This definition seems to get the best of both worlds. For a definition like `f` below, this new definition just requires one extra `add i64` operation in the preamble (before the loop). Everything else is identical to master.

```julia
function f(A)
    r = 0
    @inbounds for x in A
        r += x
    end
    r
end
```
  • Loading branch information
mbauman committed May 14, 2018
1 parent fcaa379 commit e2098ac
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
2 changes: 1 addition & 1 deletion base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ end
## Iteration ##
start(A::Array) = 1
next(a::Array,i) = (@_propagate_inbounds_meta; (a[i],i+1))
done(a::Array,i) = (@_inline_meta; i == length(a)+1)
done(a::Array,i) = (@_inline_meta; i >= length(a)+1)

## Indexing: getindex ##

Expand Down
19 changes: 19 additions & 0 deletions test/arrayops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2424,6 +2424,25 @@ end
@inferred hash([1,2,3])
end

function f27079()
X = rand(5)
for x in X
resize!(X, 0)
end
length(X)
end
function g27079(X)
r = 0
@inbounds for x in X
r += x
end
r
end
@testset "iteration over resized vector" begin
@test f27079() == 0
@test occursin("vector.body", sprint(code_llvm, g27079, Tuple{Vector{Int}}))
end

@testset "indices-related shape promotion errors" begin
@test_throws DimensionMismatch Base.promote_shape((2,), (3,))
@test_throws DimensionMismatch Base.promote_shape((2, 3), (2, 4))
Expand Down

0 comments on commit e2098ac

Please sign in to comment.