Conversation
These tests were compiled with -C debug-assertions=off because their programs can overflow, which the overflow checks that come with debug assertions turn into verification failures. Each now bounds the values it does arithmetic on, and no longer passes the flag: - rand() promises a result in a small range - functions and closures require their arguments in a small range - loops stop before their counters leave a small range - Double gains a can_double predicate that double requires Integer values carry no range facts yet, so a bound is given on both sides even where the operation can only overflow in one direction. Each fail file keeps the same bounds as its pass file. loop_invariant_nested narrows its invariant with the bounds on both sides, and the fail side still drops the clauses on y. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PzcoivHkYESNWJykaKpAmR
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Now that annotations can name associated consts, the bounds are the type limits instead of an arbitrary 1000: - values from rand() are guarded by an if in the code that uses them, and rand() keeps ensures(true) - requires state that the operation fits the type, e.g. i64::MIN <= x + x && x + x <= i64::MAX - loops stop at i64::MAX, or at HALF_MAX when they add two counters A guard in code compares only against constants. Integer values carry no range facts yet, so arithmetic in the guard itself, such as i32::MAX - x, can overflow in the model. Thrust does not handle integer division in code, so i64::MAX / 2 is written as a const item. Where a fail file added arithmetic that the new bounds let overflow, it now breaks the property without overflowing: - annot_exists, annot_exists_formula_fn, annot_preds: x + x + 1 in place of x + x + x - annot_exists_formula_fn_mut: requires x >= 0 in place of *m -= x - recursive: asserts y != x in place of y == x + 1 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PzcoivHkYESNWJykaKpAmR
This branch has not been deployed
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.
This is the next step toward dropping
-C debug-assertions=offfrom the UI tests, after #291.With debug assertions on, rustc checks for overflow on
+,-and*. Since #280, Thrust verifies those checks. Many test programs use arithmetic that can really overflow, for examplex + 1withrequires(true), or a counter in a loop with no bound. These tests fail withUnsatonce the flag is gone.This PR bounds the arithmetic in each of those tests by the integer type limits, using the associated consts from #296. It drops the flag from the 32 tests that then pass.
Changes
rand()are guarded by anifin the code that uses them, e.g.if i64::MIN <= a && a < i64::MAX && ....rand()itself keepsensures(true).requiresstates that the operation fits the type, e.g.i64::MIN <= x + x && x + x <= i64::MAX. This applies toannot_forall,annot_preds,annot_raw_command*,annot_*formula_fn_mut,closure_*andclosure_no_capture_fn_param.i64::MAX, or atHALF_MAXwhen they add two counters.loop_invariant_nestedalso puts the bounds in its inner invariant, because an explicit invariant does not carry the outer guard's bound onx.loop_invariant_trait_selfresets the counter to0when it is out of range, in place of*= -1.annot_preds_trait*:Doublegains acan_doublepredicate, anddoublerequires it. A trait-levelrequirescannot name the implementor's fields.loopnow uses PCSat. Z3 times out on it once the bound is added.Integer values carry no range facts yet, which shapes the bounds in three ways:
annot_foralldoes not pass with onlyrequires(x < i32::MAX).i32::MAX - x, can overflow in the model.i64::MAX / 2is written as a const item (HALF_MAX,HALF_MIN).Each fail file keeps the same bounds as its pass file. Where a fail file added arithmetic that the new bounds would let overflow, it now breaks the property without overflowing:
annot_exists,annot_exists_formula_fn,annot_preds:x + x + 1in place ofx + x + x.annot_exists_formula_fn_mut:requires(x >= 0 && ...)in place of*m -= x.recursive:assert!(y != x)in place ofy == x + 1.loop_invariant_nested: keeps the new bounds onxand still drops the clauses ony.Tests
cargo testpasses on all 384 UI tests, run locally with Z3 5.0.0 and the pinned PCSat binary.Not covered
These tests still need
-C debug-assertions=off:mut_recursive(Z3 and PCSat);closure_receiver_mut_model,closure_receiver_mut_model_byval; the fail side ofoption_map.loop_invariant_fn_param_closure. This is not investigated.fn_poly_annot_2(x * 1),fn_poly_annot_recursive,mod_invariant,iterators/annot_range_*,slice_split_first_loop*,loop_invariant_fn_param_at_entry.slice_index_mut: checked compound assignment to a slice element panics inelaborate_place_for_borrow.ghost_field,ghost_self: once overflow checks split the block, a ghost parameter is no longer live.iterators/fixed_filter_loop_nonetimes out.🤖 Generated with Claude Code
https://claude.ai/code/session_01PzcoivHkYESNWJykaKpAmR