|
63 | 63 | )]
|
64 | 64 | #![allow(missing_docs)]
|
65 | 65 |
|
| 66 | +use safety::requires; |
66 | 67 | use crate::marker::DiscriminantKind;
|
67 | 68 | use crate::marker::Tuple;
|
68 | 69 | use crate::mem::align_of;
|
69 | 70 | use crate::ptr;
|
70 | 71 | use crate::ub_checks;
|
71 | 72 |
|
| 73 | +#[cfg(kani)] |
| 74 | +use crate::kani; |
| 75 | + |
72 | 76 | pub mod mir;
|
73 | 77 | pub mod simd;
|
74 | 78 |
|
@@ -2709,6 +2713,12 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
|
2709 | 2713 | #[rustc_intrinsic]
|
2710 | 2714 | // This has fallback `const fn` MIR, so shouldn't need stability, see #122652
|
2711 | 2715 | #[rustc_const_unstable(feature = "const_typed_swap", issue = "none")]
|
| 2716 | +#[cfg_attr(kani, kani::modifies(x))] |
| 2717 | +#[cfg_attr(kani, kani::modifies(y))] |
| 2718 | +#[requires(ub_checks::can_dereference(x) && ub_checks::can_write(x))] |
| 2719 | +#[requires(ub_checks::can_dereference(y) && ub_checks::can_write(y))] |
| 2720 | +#[requires(x.addr() != y.addr() || core::mem::size_of::<T>() == 0)] |
| 2721 | +#[requires((x.addr() >= y.addr() + core::mem::size_of::<T>()) || (y.addr() >= x.addr() + core::mem::size_of::<T>()))] |
2712 | 2722 | pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) {
|
2713 | 2723 | // SAFETY: The caller provided single non-overlapping items behind
|
2714 | 2724 | // pointers, so swapping them with `count: 1` is fine.
|
@@ -3142,3 +3152,37 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
|
3142 | 3152 |
|
3143 | 3153 | const_eval_select((ptr, align), compiletime, runtime);
|
3144 | 3154 | }
|
| 3155 | + |
| 3156 | +#[cfg(kani)] |
| 3157 | +#[unstable(feature="kani", issue="none")] |
| 3158 | +mod verify { |
| 3159 | + use core::{cmp, fmt}; |
| 3160 | + use super::*; |
| 3161 | + use crate::kani; |
| 3162 | + |
| 3163 | + #[kani::proof_for_contract(typed_swap)] |
| 3164 | + pub fn check_typed_swap_u8() { |
| 3165 | + check_swap::<u8>() |
| 3166 | + } |
| 3167 | + |
| 3168 | + #[kani::proof_for_contract(typed_swap)] |
| 3169 | + pub fn check_typed_swap_char() { |
| 3170 | + check_swap::<char>() |
| 3171 | + } |
| 3172 | + |
| 3173 | + #[kani::proof_for_contract(typed_swap)] |
| 3174 | + pub fn check_typed_swap_non_zero() { |
| 3175 | + check_swap::<core::num::NonZeroI32>() |
| 3176 | + } |
| 3177 | + |
| 3178 | + pub fn check_swap<T: kani::Arbitrary + Copy + cmp::PartialEq + fmt::Debug>() { |
| 3179 | + let mut x = kani::any::<T>(); |
| 3180 | + let old_x = x; |
| 3181 | + let mut y = kani::any::<T>(); |
| 3182 | + let old_y = y; |
| 3183 | + |
| 3184 | + unsafe { typed_swap(&mut x, &mut y) }; |
| 3185 | + assert_eq!(y, old_x); |
| 3186 | + assert_eq!(x, old_y); |
| 3187 | + } |
| 3188 | +} |
0 commit comments