Skip to content

Commit 6b1eaaa

Browse files
committed
Reapply repository changes to library files
1 parent 8f6ca19 commit 6b1eaaa

File tree

9 files changed

+188
-488
lines changed

9 files changed

+188
-488
lines changed

library.patch

-488
This file was deleted.

library/core/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ name = "corebenches"
2424
path = "benches/lib.rs"
2525
test = true
2626

27+
[dependencies]
28+
safety = {path = "../contracts/safety" }
29+
2730
[dev-dependencies]
2831
rand = { version = "0.8.5", default-features = false }
2932
rand_xorshift = { version = "0.3.0", default-features = false }

library/core/src/alloc/layout.rs

+23
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
// collections, resulting in having to optimize down excess IR multiple times.
55
// Your performance intuition is useless. Run perf.
66

7+
use safety::requires;
78
use crate::cmp;
89
use crate::error::Error;
910
use crate::fmt;
1011
use crate::mem;
1112
use crate::ptr::{Alignment, NonNull};
1213

14+
#[cfg(kani)]
15+
use crate::kani;
16+
1317
// While this function is used in one place and its implementation
1418
// could be inlined, the previous attempts to do so made rustc
1519
// slower:
@@ -117,6 +121,7 @@ impl Layout {
117121
#[must_use]
118122
#[inline]
119123
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
124+
#[requires(Layout::from_size_align(size, align).is_ok())]
120125
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
121126
// SAFETY: the caller is required to uphold the preconditions.
122127
unsafe { Layout { size, align: Alignment::new_unchecked(align) } }
@@ -492,3 +497,21 @@ impl fmt::Display for LayoutError {
492497
f.write_str("invalid parameters to Layout::from_size_align")
493498
}
494499
}
500+
501+
#[cfg(kani)]
502+
#[unstable(feature="kani", issue="none")]
503+
mod verify {
504+
use super::*;
505+
506+
#[kani::proof_for_contract(Layout::from_size_align_unchecked)]
507+
pub fn check_from_size_align_unchecked() {
508+
let s = kani::any::<usize>();
509+
let a = kani::any::<usize>();
510+
511+
unsafe {
512+
let layout = Layout::from_size_align_unchecked(s, a);
513+
assert_eq!(layout.size(), s);
514+
assert_eq!(layout.align(), a);
515+
}
516+
}
517+
}

library/core/src/intrinsics.rs

+44
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,16 @@
6363
)]
6464
#![allow(missing_docs)]
6565

66+
use safety::requires;
6667
use crate::marker::DiscriminantKind;
6768
use crate::marker::Tuple;
6869
use crate::mem::align_of;
6970
use crate::ptr;
7071
use crate::ub_checks;
7172

73+
#[cfg(kani)]
74+
use crate::kani;
75+
7276
pub mod mir;
7377
pub mod simd;
7478

@@ -2709,6 +2713,12 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
27092713
#[rustc_intrinsic]
27102714
// This has fallback `const fn` MIR, so shouldn't need stability, see #122652
27112715
#[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>()))]
27122722
pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) {
27132723
// SAFETY: The caller provided single non-overlapping items behind
27142724
// 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
31423152

31433153
const_eval_select((ptr, align), compiletime, runtime);
31443154
}
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+
}

library/core/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,9 @@ mod unit;
431431
#[stable(feature = "core_primitive", since = "1.43.0")]
432432
pub mod primitive;
433433

434+
#[cfg(kani)]
435+
kani_core::kani_lib!(core);
436+
434437
// Pull in the `core_arch` crate directly into core. The contents of
435438
// `core_arch` are in a different repository: rust-lang/stdarch.
436439
//

library/core/src/mem/mod.rs

+40
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ use crate::intrinsics;
1313
use crate::marker::DiscriminantKind;
1414
use crate::ptr;
1515

16+
#[cfg(kani)]
17+
use crate::kani;
18+
1619
mod manually_drop;
1720
#[stable(feature = "manually_drop", since = "1.20.0")]
1821
pub use manually_drop::ManuallyDrop;
@@ -725,6 +728,8 @@ pub unsafe fn uninitialized<T>() -> T {
725728
#[stable(feature = "rust1", since = "1.0.0")]
726729
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
727730
#[rustc_diagnostic_item = "mem_swap"]
731+
#[cfg_attr(kani, crate::kani::modifies(x))]
732+
#[cfg_attr(kani, crate::kani::modifies(y))]
728733
pub const fn swap<T>(x: &mut T, y: &mut T) {
729734
// SAFETY: `&mut` guarantees these are typed readable and writable
730735
// as well as non-overlapping.
@@ -1345,3 +1350,38 @@ pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) {
13451350
// The `{}` is for better error messages
13461351
{builtin # offset_of($Container, $($fields)+)}
13471352
}
1353+
1354+
#[cfg(kani)]
1355+
#[unstable(feature="kani", issue="none")]
1356+
mod verify {
1357+
use super::*;
1358+
use crate::kani;
1359+
1360+
/// Use this type to ensure that mem swap does not drop the value.
1361+
#[derive(kani::Arbitrary)]
1362+
struct CannotDrop<T: kani::Arbitrary> {
1363+
inner: T,
1364+
}
1365+
1366+
impl<T: kani::Arbitrary> Drop for CannotDrop<T> {
1367+
fn drop(&mut self) {
1368+
unreachable!("Cannot drop")
1369+
}
1370+
}
1371+
1372+
#[kani::proof_for_contract(swap)]
1373+
pub fn check_swap_primitive() {
1374+
let mut x: u8 = kani::any();
1375+
let mut y: u8 = kani::any();
1376+
swap(&mut x, &mut y)
1377+
}
1378+
1379+
#[kani::proof_for_contract(swap)]
1380+
pub fn check_swap_adt_no_drop() {
1381+
let mut x: CannotDrop<char> = kani::any();
1382+
let mut y: CannotDrop<char> = kani::any();
1383+
swap(&mut x, &mut y);
1384+
forget(x);
1385+
forget(y);
1386+
}
1387+
}

library/core/src/ptr/alignment.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
use safety::requires;
12
use crate::num::NonZero;
23
#[cfg(debug_assertions)]
34
use crate::ub_checks::assert_unsafe_precondition;
45
use crate::{cmp, fmt, hash, mem, num};
56

7+
#[cfg(kani)]
8+
use crate::kani;
9+
610
/// A type storing a `usize` which is a power of two, and thus
711
/// represents a possible alignment in the Rust abstract machine.
812
///
@@ -76,6 +80,8 @@ impl Alignment {
7680
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
7781
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
7882
#[inline]
83+
#[requires(align > 0)]
84+
#[requires((align & (align - 1)) == 0)]
7985
pub const unsafe fn new_unchecked(align: usize) -> Self {
8086
#[cfg(debug_assertions)]
8187
assert_unsafe_precondition!(

library/core/src/ptr/mod.rs

+21
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,8 @@ use crate::marker::FnPtr;
416416
use crate::ub_checks;
417417

418418
use crate::mem::{self, align_of, size_of, MaybeUninit};
419+
#[cfg(kani)]
420+
use crate::kani;
419421

420422
mod alignment;
421423
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
@@ -1687,6 +1689,7 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
16871689
#[stable(feature = "volatile", since = "1.9.0")]
16881690
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
16891691
#[rustc_diagnostic_item = "ptr_read_volatile"]
1692+
#[safety::requires(ub_checks::can_dereference(src))]
16901693
pub unsafe fn read_volatile<T>(src: *const T) -> T {
16911694
// SAFETY: the caller must uphold the safety contract for `volatile_load`.
16921695
unsafe {
@@ -1766,6 +1769,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
17661769
#[stable(feature = "volatile", since = "1.9.0")]
17671770
#[rustc_diagnostic_item = "ptr_write_volatile"]
17681771
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1772+
#[safety::requires(ub_checks::can_write(dst))]
17691773
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
17701774
// SAFETY: the caller must uphold the safety contract for `volatile_store`.
17711775
unsafe {
@@ -2290,3 +2294,20 @@ pub macro addr_of($place:expr) {
22902294
pub macro addr_of_mut($place:expr) {
22912295
&raw mut $place
22922296
}
2297+
2298+
#[cfg(kani)]
2299+
#[unstable(feature="kani", issue="none")]
2300+
mod verify {
2301+
use crate::fmt::Debug;
2302+
use super::*;
2303+
use crate::kani;
2304+
2305+
#[kani::proof_for_contract(read_volatile)]
2306+
pub fn check_read_u128() {
2307+
let val = kani::any::<u16>();
2308+
let ptr = &val as *const _;
2309+
let copy = unsafe { read_volatile(ptr) };
2310+
assert_eq!(val, copy);
2311+
}
2312+
}
2313+

library/core/src/ub_checks.rs

+48
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,51 @@ pub(crate) const fn is_nonoverlapping(
160160
// This is just for safety checks so we can const_eval_select.
161161
const_eval_select((src, dst, size, count), comptime, runtime)
162162
}
163+
164+
pub use predicates::*;
165+
166+
/// Provide a few predicates to be used in safety contracts.
167+
///
168+
/// At runtime, they are no-op, and always return true.
169+
#[cfg(not(kani))]
170+
mod predicates {
171+
/// Checks if a pointer can be dereferenced, ensuring:
172+
/// * `src` is valid for reads (see [`crate::ptr`] documentation).
173+
/// * `src` is properly aligned (use `read_unaligned` if not).
174+
/// * `src` points to a properly initialized value of type `T`.
175+
///
176+
/// [`crate::ptr`]: https://doc.rust-lang.org/std/ptr/index.html
177+
pub fn can_dereference<T>(src: *const T) -> bool {
178+
let _ = src;
179+
true
180+
}
181+
182+
/// Check if a pointer can be written to:
183+
/// * `dst` must be valid for writes.
184+
/// * `dst` must be properly aligned. Use `write_unaligned` if this is not the
185+
/// case.
186+
pub fn can_write<T>(dst: *mut T) -> bool {
187+
let _ = dst;
188+
true
189+
}
190+
191+
/// Check if a pointer can be the target of unaligned reads.
192+
/// * `src` must be valid for reads.
193+
/// * `src` must point to a properly initialized value of type `T`.
194+
pub fn can_read_unaligned<T>(src: *const T) -> bool {
195+
let _ = src;
196+
true
197+
}
198+
199+
/// Check if a pointer can be the target of unaligned writes.
200+
/// * `dst` must be valid for writes.
201+
pub fn can_write_unaligned<T>(dst: *mut T) -> bool {
202+
let _ = dst;
203+
true
204+
}
205+
}
206+
207+
#[cfg(kani)]
208+
mod predicates {
209+
pub use crate::kani::mem::{can_dereference, can_write, can_read_unaligned, can_write_unaligned};
210+
}

0 commit comments

Comments
 (0)