fix(acir): guard empty vector pop/remove on the semantic length - #13501
Open
asterite wants to merge 1 commit into
Open
fix(acir): guard empty vector pop/remove on the semantic length#13501asterite wants to merge 1 commit into
asterite wants to merge 1 commit into
Conversation
asterite
force-pushed
the
ab/fix-empty-vector-pop-remove-acir
branch
from
August 10, 2026 20:39
cea0420 to
d1e1318
Compare
`convert_vector_pop_back`, `convert_vector_pop_front` and `convert_vector_remove` decided whether the vector was empty with `has_zero_length`, which inspects the backing store. A slice's backing store can be non-empty while its semantic length is zero: merging branch arms of unequal length pads the shorter arm. In that state the empty arm was skipped and `length - 1` was computed as `0 - 1 = p - 1` in the field, which `convert_vector_push_back` then aborted on in `to_u128`. The zero length is not always visible in the SSA: an empty-vector assertion can collapse the side-effects predicate to a constant zero during ACIR generation, and that folds a live vector's length to zero via the predicate multiplication while the SSA value stays dynamic. So the new `vector_length_is_known_zero` checks both the SSA constant and the folded ACIR expression, and the three converters take the empty arm when either the backing store or the semantic length is known to be zero. The regression program `vector_ops_collapsed_predicate` exercises the predicate-collapse route end to end: it panicked the compiler before this change and now compiles and executes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
asterite
force-pushed
the
ab/fix-empty-vector-pop-remove-acir
branch
from
August 10, 2026 20:56
d1e1318 to
ce6f9be
Compare
asterite
marked this pull request as ready for review
August 11, 2026 12:13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a compiler crash (and latent miscompilation) when a
pop_back/pop_front/removeintrinsic is applied to a vector whose semantic length is zero but whose backing store is not.acir_gen decided emptiness with
has_zero_length, which inspects the backing store. But a slice's backing store can be non-empty while its semantic length is zero — merging two branch arms of unequal length pads the shorter arm. In that state the empty-vector arm was skipped and the new length was computed as0 - 1 = p - 1in the field;convert_vector_push_backthen aborted the compiler inFieldElement::to_u128("field element too large for u128").The zero length is not always visible in the SSA. An empty-vector assertion can collapse the side-effects predicate to a constant zero during ACIR generation, and the predicate multiplication then folds a live vector's length to zero while its SSA value stays dynamic — so no SSA pass can see it. The new
vector_length_is_known_zerohelper checks both the SSA constant and the folded ACIR expression, and the three converters take the empty arm when either the backing store or the semantic length is known to be zero.Changes
convert_vector_pop_back/convert_vector_pop_front/convert_vector_removenow key their empty check on the semantic length as well as the backing store, via the newvector_length_is_known_zerohelper.Testing
vector_ops_collapsed_predicatereproduces the predicate-collapse crash end to end; it panicked the compiler before this change and now compiles and executes across the ACIR, Brillig, and interpreter variants.Failed assertionrather than returning padding — soundness preserved.noirc_evaluatorvector tests pass;acir_vs_brillig,min_vs_full,orig_vs_morph, andcomptime_vs_brillig_nargoAST-fuzzer targets pass.Status
Draft: opening for review of the approach. The Brillig
update_vector_lengthwrapping-Suband the SSA interpreter'svector_removeguard are related but separate surfaces (source programs reach them only through their own ssa_gen checks); this PR scopes to the ACIR generation path.🤖 Generated with Claude Code