Skip to content

Commit a91dcad

Browse files
committed
Merge remote-tracking branch 'origin/main' into align-harness
2 parents 7fdbc77 + 0be79d6 commit a91dcad

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

library/core/src/ascii/ascii_char.rs

+26
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33
//! suggestions from rustc if you get anything slightly wrong in here, and overall
44
//! helps with clarity as we're also referring to `char` intentionally in here.
55
6+
use safety::{ensures, requires};
67
use crate::fmt::{self, Write};
78
use crate::mem::transmute;
89

10+
#[cfg(kani)]
11+
use crate::kani;
12+
913
/// One of the 128 Unicode characters from U+0000 through U+007F,
1014
/// often known as the [ASCII] subset.
1115
///
@@ -449,6 +453,7 @@ impl AsciiChar {
449453
/// or returns `None` if it's too large.
450454
#[unstable(feature = "ascii_char", issue = "110998")]
451455
#[inline]
456+
#[ensures(|result| (b <= 127) == (result.is_some() && result.unwrap() as u8 == b))]
452457
pub const fn from_u8(b: u8) -> Option<Self> {
453458
if b <= 127 {
454459
// SAFETY: Just checked that `b` is in-range
@@ -466,6 +471,8 @@ impl AsciiChar {
466471
/// `b` must be in `0..=127`, or else this is UB.
467472
#[unstable(feature = "ascii_char", issue = "110998")]
468473
#[inline]
474+
#[requires(b <= 127)]
475+
#[ensures(|result| *result as u8 == b)]
469476
pub const unsafe fn from_u8_unchecked(b: u8) -> Self {
470477
// SAFETY: Our safety precondition is that `b` is in-range.
471478
unsafe { transmute(b) }
@@ -616,3 +623,22 @@ impl fmt::Debug for AsciiChar {
616623
f.write_char('\'')
617624
}
618625
}
626+
627+
#[cfg(kani)]
628+
#[unstable(feature="kani", issue="none")]
629+
mod verify {
630+
use super::*;
631+
use AsciiChar;
632+
633+
#[kani::proof_for_contract(AsciiChar::from_u8)]
634+
fn check_from_u8() {
635+
let b: u8 = kani::any();
636+
AsciiChar::from_u8(b);
637+
}
638+
639+
#[kani::proof_for_contract(AsciiChar::from_u8_unchecked)]
640+
fn check_from_u8_unchecked() {
641+
let b: u8 = kani::any();
642+
unsafe { AsciiChar::from_u8_unchecked(b) };
643+
}
644+
}

library/core/src/char/convert.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
//! Character conversions.
22
3+
use safety::{requires, ensures};
34
use crate::char::TryFromCharError;
45
use crate::error::Error;
56
use crate::fmt;
67
use crate::mem::transmute;
78
use crate::str::FromStr;
89
use crate::ub_checks::assert_unsafe_precondition;
910

11+
#[cfg(kani)]
12+
use crate::kani;
13+
1014
/// Converts a `u32` to a `char`. See [`char::from_u32`].
1115
#[must_use]
1216
#[inline]
@@ -21,6 +25,8 @@ pub(super) const fn from_u32(i: u32) -> Option<char> {
2125
/// Converts a `u32` to a `char`, ignoring validity. See [`char::from_u32_unchecked`].
2226
#[inline]
2327
#[must_use]
28+
#[requires(char_try_from_u32(i).is_ok())]
29+
#[ensures(|result| *result as u32 == i)]
2430
pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char {
2531
// SAFETY: the caller must guarantee that `i` is a valid char value.
2632
unsafe {
@@ -290,3 +296,15 @@ pub(super) const fn from_digit(num: u32, radix: u32) -> Option<char> {
290296
None
291297
}
292298
}
299+
300+
#[cfg(kani)]
301+
#[unstable(feature="kani", issue="none")]
302+
mod verify {
303+
use super::*;
304+
305+
#[kani::proof_for_contract(from_u32_unchecked)]
306+
fn check_from_u32_unchecked() {
307+
let i: u32 = kani::any();
308+
unsafe { from_u32_unchecked(i) };
309+
}
310+
}

library/core/src/char/methods.rs

+27
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ use crate::str::from_utf8_unchecked_mut;
55
use crate::unicode::printable::is_printable;
66
use crate::unicode::{self, conversions};
77

8+
#[cfg(kani)]
9+
use crate::kani;
10+
811
use super::*;
912

1013
impl char {
@@ -1836,3 +1839,27 @@ pub fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] {
18361839
}
18371840
}
18381841
}
1842+
1843+
#[cfg(kani)]
1844+
#[unstable(feature="kani", issue="none")]
1845+
mod verify {
1846+
use super::*;
1847+
use safety::ensures;
1848+
1849+
#[ensures(|result| c.is_ascii() == (result.is_some() && (result.unwrap() as u8 as char == *c)))]
1850+
fn as_ascii_clone(c: &char) -> Option<ascii::Char> {
1851+
c.as_ascii()
1852+
}
1853+
1854+
#[kani::proof_for_contract(as_ascii_clone)]
1855+
fn check_as_ascii_ascii_char() {
1856+
let ascii: char = kani::any_where(|c : &char| c.is_ascii());
1857+
as_ascii_clone(&ascii);
1858+
}
1859+
1860+
#[kani::proof_for_contract(as_ascii_clone)]
1861+
fn check_as_ascii_non_ascii_char() {
1862+
let non_ascii: char = kani::any_where(|c: &char| !c.is_ascii());
1863+
as_ascii_clone(&non_ascii);
1864+
}
1865+
}

0 commit comments

Comments
 (0)