You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
so every nondeterministic Rc/Arc value observably has strong_count == 1 and weak_count == 0. This is also what the autoharness smart-pointer models (any_rc/any_arc, #4698) produce, since they call kani::any::<T>() inside a fresh Rc::new/Arc::new.
Why this matters
A function that observes reference-count state can be "proved" for a state a real caller can violate. For example:
fnf(a: std::sync::Arc<u32>){assert_eq!(std::sync::Arc::strong_count(&a),1);// "verified", but a caller may pass a clone}
An autoharness (or a manual harness using kani::any::<Arc<u32>>()) only ever sees strong_count == 1, so this passes — even though let x = Arc::new(0); let _y = x.clone(); f(x); would trip the assertion at runtime. The same applies to Arc::weak_count, Arc::get_mut, Arc::try_unwrap, Rc::make_mut, etc.
Scope / notes
This is a property of the Arbitrary impls themselves, not specific to autoharness: it affects any harness that uses kani::any::<Arc<T>>()/kani::any::<Rc<T>>().
Box<T> is unaffected: it is uniquely owned and has no observable aliasing/refcount state, so Box<T> genuinely covers exactly the values of T.
Possible directions
Model a nondeterministic reference-count state (e.g. leak additional clones/weak refs so strong_count/weak_count are nondeterministic), and report such values as bounded where a finite bound is used.
Document the limitation explicitly for Rc/ArcArbitrary.
Summary
Kani's
Arbitraryimplementations forRc<T>andArc<T>(added in #4697) construct a fresh allocation:so every nondeterministic
Rc/Arcvalue observably hasstrong_count == 1andweak_count == 0. This is also what the autoharness smart-pointer models (any_rc/any_arc, #4698) produce, since they callkani::any::<T>()inside a freshRc::new/Arc::new.Why this matters
A function that observes reference-count state can be "proved" for a state a real caller can violate. For example:
An autoharness (or a manual harness using
kani::any::<Arc<u32>>()) only ever seesstrong_count == 1, so this passes — even thoughlet x = Arc::new(0); let _y = x.clone(); f(x);would trip the assertion at runtime. The same applies toArc::weak_count,Arc::get_mut,Arc::try_unwrap,Rc::make_mut, etc.Scope / notes
Arbitraryimpls themselves, not specific to autoharness: it affects any harness that useskani::any::<Arc<T>>()/kani::any::<Rc<T>>().Arbitrarysemantics to compiler-derivable pointees but does not change refcount behavior.Box<T>is unaffected: it is uniquely owned and has no observable aliasing/refcount state, soBox<T>genuinely covers exactly the values ofT.Possible directions
strong_count/weak_countare nondeterministic), and report such values as bounded where a finite bound is used.Rc/ArcArbitrary.Surfaced during review of #4698 (Copilot).