diff --git a/library/kani/src/arbitrary.rs b/library/kani/src/arbitrary.rs index f16f06165d29..0b3fb5084091 100644 --- a/library/kani/src/arbitrary.rs +++ b/library/kani/src/arbitrary.rs @@ -15,6 +15,24 @@ where } } +impl Arbitrary for std::rc::Rc +where + T: Arbitrary, +{ + fn any() -> Self { + std::rc::Rc::new(T::any()) + } +} + +impl Arbitrary for std::sync::Arc +where + T: Arbitrary, +{ + fn any() -> Self { + std::sync::Arc::new(T::any()) + } +} + impl Arbitrary for std::time::Duration { fn any() -> Self { const NANOS_PER_SEC: u32 = 1_000_000_000; diff --git a/tests/kani/Arbitrary/rc_arc.rs b/tests/kani/Arbitrary/rc_arc.rs new file mode 100644 index 000000000000..8dee0066ee52 --- /dev/null +++ b/tests/kani/Arbitrary/rc_arc.rs @@ -0,0 +1,33 @@ +// Copyright Kani Contributors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +// Check that Rc and Arc implement Arbitrary (like Box), producing an +// unconstrained value of the pointee type behind shared-ownership indirection. + +use std::rc::Rc; +use std::sync::Arc; + +#[derive(kani::Arbitrary)] +struct Point { + x: u8, + y: u8, +} + +#[kani::proof] +fn check_rc() { + let p: Rc = kani::any(); + kani::cover!(p.x == 255 && p.y == 0, "extreme values are generated"); +} + +#[kani::proof] +fn check_arc() { + let v: Arc = kani::any(); + kani::cover!(*v == i32::MIN, "extreme values are generated"); + kani::cover!(*v == 42, "specific values are generated"); +} + +#[kani::proof] +fn check_nested() { + let v: Rc> = kani::any(); + kani::cover!(**v == 7, "nested smart pointers are generated"); +}