Conversation
Harnesses for all 36 listed functions in alloc::vec::mod, exercising the real shipped bodies (no cfg(kani) rewrites, no assume(false)). Allocation and growth functions verify over a symbolic, unbounded capacity; content functions over a symbolic length; a small disclosed minority is bounded or fixed-shape for measured tractability. Includes safety-crate contracts with proof_for_contract on the raw-parts and set_len family, a real-body loop contract on retain_mut, failure-arm coverage, assume/cover pairing throughout, and element-type shape coverage (drop glue, over-alignment, ZST). Generic-T uses representative shapes (committee question, disclosed). Runtime logic unchanged: all annotations are Kani-inert attributes.
Author
|
Pre-verified on
The upstream-only jobs the fork CI cannot run — |
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.
Towards #284. Solves Challenge 23: Verify the safety of
Vecfunctions part 1: Kani harnesses for all 36 listed publicVecfunctions inalloc::vec::mod, each exercising the function's real shipped body — nocfg(kani)substitution, noassume(false). Allocation and growth paths are verified over a symbolic, unbounded capacity; content and shift paths over a symbolic length. All 48 harnesses invec::verify(the 47 added plus the pre-existingverify_swap_remove) pass viascripts/run-kani.sh.Changes
vec/mod.rsmod verify;safety::{requires,ensures}contracts onfrom_raw_parts,from_parts, andset_len; a realsafety::loop_invariant+loop_modifiesonretain_mut's in-place looplib.rsproc_macro_hygienemade an unconditional feature, mirroringcore:retain_mutcarries a statement-position#[safety::…]attribute in every build, so the gate cannot becfg(kani)-onlyVerification
Every harness runs the shipped body and asserts the observable effect. By approach:
push,push_within_capacity,spare_capacity_mut,split_at_spare_mut(_with_len),into_boxed_slice,from_parts_in,into_raw_parts_with_alloc,append_elements,extend_trusted,extend_desugaredgrow pathVec::with_capacity(cap),capfree in1..=isize::MAX/4, no length constant. Reallocation and growth run at symbolic capacity, not a fixed bufferfrom_raw_parts,from_parts,set_lensafety::{requires,ensures}verified withproof_for_contract(modifies(self)onset_len). The provenance/initialization obligations that are not expressible as predicates are documented at each contract; the proofs build genuinely-valid parts and pre-initialize the spare region rather than assuming theminsert,remove,truncate,retain,drain,extract_if, and the other content/shift functionscopy_nonoverlapping(thekani::vec::any_vecidiom);insert/removesnapshot a symbolic element and assert its post-shift positionretain_mutloop_invariant+loop_modifieson the in-place critical-section loop. Loop contracts on the other in-place loops (extend_with,dedup_by) were measured non-convergent within CI at this pin, so those functions are bounded insteadpush_within_capacity,set_len,swap_removepush_within_capacityresults,set_len's growth direction (spare region initialized first), andswap_remove's out-of-bounds panic as#[kani::should_panic]insert,remove,truncate,swap_remove,retain,drain#[repr(align(16))]), aDroptype, and the ZST arm (Vec<()>)Wherever a harness restricts inputs with
kani::assume, akani::coverconfirms the restriction is satisfiable — 46 covers against 29 assumes — so no proof passes while checking nothing.Scope
Allocation capacity is genuinely unbounded — the allocation and growth paths run at a free symbolic capacity, not a fixed buffer. Two notes on the mandatory criteria:
loop_modifiesregion, an unbounded region overflows CBMC's write-set machinery and the shift/copy cost grows superlinearly, so each such harness takes the largest length that completes within CI resource limits: most content functions at0..=64, the shift-heavy and loop-bearing ones lower (to0..=4), each bound justified in-code. A symbolic insert/copy offset is likewise CBMC-prohibitive for a few harnesses, which fix the shape and keep the values symbolic.T(no monomorphization). A Kani harness is necessarily monomorphic, so this clause is not expressible in Kani; it is deferred to the committee. The harnesses instead span the element-type axes that matter for these functions: size (u8), zero-size (Vec<()>), over-alignment (#[repr(align(16))]), and drop glue (aDroptype).Every changed line is additive (+842/−0); the only annotations on shipped code are Kani-inert attributes. The spec's
from_nonnull/from_nonnull_inarefrom_parts/from_parts_inin the current source.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.