Skip to content

Commit c2b6288

Browse files
Merge branch 'main' into clone-transformer
2 parents 7dfac5a + 6c2c4f0 commit c2b6288

File tree

72 files changed

+1725
-400
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+1725
-400
lines changed

Cargo.lock

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -249,25 +249,25 @@ dependencies = [
249249

250250
[[package]]
251251
name = "cargo-util-schemas"
252-
version = "0.2.0"
252+
version = "0.8.2"
253253
source = "registry+https://github.com/rust-lang/crates.io-index"
254-
checksum = "e63d2780ac94487eb9f1fea7b0d56300abc9eb488800854ca217f102f5caccca"
254+
checksum = "7dc1a6f7b5651af85774ae5a34b4e8be397d9cf4bc063b7e6dbd99a841837830"
255255
dependencies = [
256256
"semver",
257257
"serde",
258258
"serde-untagged",
259259
"serde-value",
260-
"thiserror 1.0.69",
260+
"thiserror 2.0.12",
261261
"toml",
262262
"unicode-xid",
263263
"url",
264264
]
265265

266266
[[package]]
267267
name = "cargo_metadata"
268-
version = "0.20.0"
268+
version = "0.21.0"
269269
source = "registry+https://github.com/rust-lang/crates.io-index"
270-
checksum = "4f7835cfc6135093070e95eb2b53e5d9b5c403dc3a6be6040ee026270aa82502"
270+
checksum = "5cfca2aaa699835ba88faf58a06342a314a950d2b9686165e038286c30316868"
271271
dependencies = [
272272
"camino",
273273
"cargo-platform",
@@ -280,9 +280,9 @@ dependencies = [
280280

281281
[[package]]
282282
name = "cc"
283-
version = "1.2.30"
283+
version = "1.2.31"
284284
source = "registry+https://github.com/rust-lang/crates.io-index"
285-
checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
285+
checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2"
286286
dependencies = [
287287
"shlex",
288288
]
@@ -344,19 +344,19 @@ dependencies = [
344344

345345
[[package]]
346346
name = "clap"
347-
version = "4.5.41"
347+
version = "4.5.42"
348348
source = "registry+https://github.com/rust-lang/crates.io-index"
349-
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
349+
checksum = "ed87a9d530bb41a67537289bafcac159cb3ee28460e0a4571123d2a778a6a882"
350350
dependencies = [
351351
"clap_builder",
352352
"clap_derive",
353353
]
354354

355355
[[package]]
356356
name = "clap_builder"
357-
version = "4.5.41"
357+
version = "4.5.42"
358358
source = "registry+https://github.com/rust-lang/crates.io-index"
359-
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
359+
checksum = "64f4f3f3c77c94aff3c7e9aac9a2ca1974a5adf392a8bb751e827d6d127ab966"
360360
dependencies = [
361361
"anstream",
362362
"anstyle",
@@ -436,15 +436,15 @@ dependencies = [
436436

437437
[[package]]
438438
name = "console"
439-
version = "0.15.11"
439+
version = "0.16.0"
440440
source = "registry+https://github.com/rust-lang/crates.io-index"
441-
checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"
441+
checksum = "2e09ced7ebbccb63b4c65413d821f2e00ce54c5ca4514ddc6b3c892fdbcbc69d"
442442
dependencies = [
443443
"encode_unicode",
444444
"libc",
445445
"once_cell",
446446
"unicode-width",
447-
"windows-sys 0.59.0",
447+
"windows-sys 0.60.2",
448448
]
449449

450450
[[package]]
@@ -1187,6 +1187,8 @@ dependencies = [
11871187
"proc-macro-error2",
11881188
"proc-macro2",
11891189
"quote",
1190+
"strum",
1191+
"strum_macros",
11901192
"syn",
11911193
]
11921194

@@ -1666,9 +1668,9 @@ dependencies = [
16661668

16671669
[[package]]
16681670
name = "quick-xml"
1669-
version = "0.38.0"
1671+
version = "0.38.1"
16701672
source = "registry+https://github.com/rust-lang/crates.io-index"
1671-
checksum = "8927b0664f5c5a98265138b7e3f90aa19a6b21353182469ace36d4ac527b7b1b"
1673+
checksum = "9845d9dccf565065824e69f9f235fafba1587031eda353c1f1561cd6a6be78f4"
16721674
dependencies = [
16731675
"memchr",
16741676
]
@@ -1710,9 +1712,9 @@ dependencies = [
17101712

17111713
[[package]]
17121714
name = "redox_syscall"
1713-
version = "0.5.16"
1715+
version = "0.5.17"
17141716
source = "registry+https://github.com/rust-lang/crates.io-index"
1715-
checksum = "7251471db004e509f4e75a62cca9435365b5ec7bcdff530d612ac7c87c44a792"
1717+
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
17161718
dependencies = [
17171719
"bitflags",
17181720
]
@@ -1902,9 +1904,9 @@ dependencies = [
19021904

19031905
[[package]]
19041906
name = "serde_json"
1905-
version = "1.0.141"
1907+
version = "1.0.142"
19061908
source = "registry+https://github.com/rust-lang/crates.io-index"
1907-
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
1909+
checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
19081910
dependencies = [
19091911
"indexmap",
19101912
"itoa",
@@ -1971,9 +1973,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
19711973

19721974
[[package]]
19731975
name = "signal-hook-registry"
1974-
version = "1.4.5"
1976+
version = "1.4.6"
19751977
source = "registry+https://github.com/rust-lang/crates.io-index"
1976-
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
1978+
checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
19771979
dependencies = [
19781980
"libc",
19791981
]
@@ -2206,9 +2208,9 @@ dependencies = [
22062208

22072209
[[package]]
22082210
name = "tokio"
2209-
version = "1.47.0"
2211+
version = "1.47.1"
22102212
source = "registry+https://github.com/rust-lang/crates.io-index"
2211-
checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35"
2213+
checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
22122214
dependencies = [
22132215
"backtrace",
22142216
"bytes",
@@ -2691,7 +2693,7 @@ version = "0.60.2"
26912693
source = "registry+https://github.com/rust-lang/crates.io-index"
26922694
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
26932695
dependencies = [
2694-
"windows-targets 0.53.2",
2696+
"windows-targets 0.53.3",
26952697
]
26962698

26972699
[[package]]
@@ -2712,10 +2714,11 @@ dependencies = [
27122714

27132715
[[package]]
27142716
name = "windows-targets"
2715-
version = "0.53.2"
2717+
version = "0.53.3"
27162718
source = "registry+https://github.com/rust-lang/crates.io-index"
2717-
checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
2719+
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
27182720
dependencies = [
2721+
"windows-link",
27192722
"windows_aarch64_gnullvm 0.53.0",
27202723
"windows_aarch64_msvc 0.53.0",
27212724
"windows_i686_gnu 0.53.0",

cprover_bindings/src/cbmc_string.rs

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// Copyright Kani Contributors
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33

4-
use lazy_static::lazy_static;
5-
use std::sync::Mutex;
4+
use std::cell::RefCell;
65
use string_interner::StringInterner;
76
use string_interner::backend::StringBackend;
87
use string_interner::symbol::SymbolU32;
@@ -23,10 +22,11 @@ use string_interner::symbol::SymbolU32;
2322
#[derive(Clone, Hash, Copy, PartialEq, Eq, PartialOrd, Ord)]
2423
pub struct InternedString(SymbolU32);
2524

26-
// Use a `Mutex` to make this thread safe.
27-
lazy_static! {
28-
static ref INTERNER: Mutex<StringInterner<StringBackend>> =
29-
Mutex::new(StringInterner::default());
25+
// This [StringInterner] is a thread local, letting us get away with less synchronization.
26+
// See the `sync` module below for a full explanation of this choice's consequences.
27+
thread_local! {
28+
static INTERNER: RefCell<StringInterner<StringBackend>> =
29+
RefCell::new(StringInterner::default());
3030
}
3131

3232
impl InternedString {
@@ -42,7 +42,7 @@ impl InternedString {
4242
/// Needed because exporting the &str backing the InternedString is blocked by lifetime rules.
4343
/// Instead, this allows users to operate on the &str when needed.
4444
pub fn map<T, F: FnOnce(&str) -> T>(&self, f: F) -> T {
45-
f(INTERNER.lock().unwrap().resolve(self.0).unwrap())
45+
INTERNER.with_borrow(|i| f(i.resolve(self.0).unwrap()))
4646
}
4747

4848
pub fn starts_with(&self, pattern: &str) -> bool {
@@ -52,13 +52,13 @@ impl InternedString {
5252

5353
impl std::fmt::Display for InternedString {
5454
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
55-
write!(fmt, "{}", INTERNER.lock().unwrap().resolve(self.0).unwrap())
55+
INTERNER.with_borrow(|i| write!(fmt, "{}", i.resolve(self.0).unwrap()))
5656
}
5757
}
5858
/// Custom-implement Debug, so our debug logging contains meaningful strings, not numbers
5959
impl std::fmt::Debug for InternedString {
6060
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
61-
write!(fmt, "{:?}", INTERNER.lock().unwrap().resolve(self.0).unwrap())
61+
INTERNER.with_borrow(|i| write!(fmt, "{:?}", i.resolve(self.0).unwrap()))
6262
}
6363
}
6464

@@ -67,7 +67,7 @@ where
6767
T: AsRef<str>,
6868
{
6969
fn from(s: T) -> InternedString {
70-
InternedString(INTERNER.lock().unwrap().get_or_intern(s))
70+
InternedString(INTERNER.with_borrow_mut(|i| i.get_or_intern(s)))
7171
}
7272
}
7373

@@ -76,7 +76,7 @@ where
7676
T: AsRef<str>,
7777
{
7878
fn eq(&self, other: &T) -> bool {
79-
INTERNER.lock().unwrap().resolve(self.0).unwrap() == other.as_ref()
79+
INTERNER.with_borrow(|i| i.resolve(self.0).unwrap() == other.as_ref())
8080
}
8181
}
8282

@@ -105,6 +105,68 @@ where
105105
}
106106
}
107107

108+
/// At a high level, the key design choice here is to keep our [StringInterner]s as thread locals.
109+
/// This works because whichever thread is generating `SymbolTable`s will be updating the interner in a way that
110+
/// affects serialization, but the serialization doesn't affect the interner in a way that affects generating
111+
/// `SymbolTable`s.
112+
///
113+
/// Thus, it makes a lot of sense to have threads each maintain their own copy of a [StringInterner]. Then, when the main
114+
/// codegen thread wants to tell another thread to write a new `SymbolTable` to disk, it can just send along
115+
/// its master copy of the [StringInterner] that they can use to update theirs.
116+
///
117+
/// To enforce this, [InternedString] is marked `!Send`--preventing them from being sent between threads
118+
/// unless they're wrapped in a [WithInterner](sync::WithInterner) type that will ensure the recieving thread updates
119+
/// its local interner to match the sending thread's.
120+
pub(crate) mod sync {
121+
use string_interner::{StringInterner, backend::StringBackend};
122+
123+
use crate::{InternedString, cbmc_string::INTERNER};
124+
125+
/// The value of an [InternedString] is defined based on a thread local [INTERNER] so they cannot safely
126+
/// be sent between threads.
127+
impl !Send for InternedString {}
128+
129+
/// A type that is only `!Send` because it contains types specific to a thread local [INTERNER]
130+
/// (e.g. [InternedString]s). This forces users to annotate that the types they want to wrap in [WithInterner]
131+
/// are `!Send` just for that specific reason rather than using it to make arbitrary types `Send`.
132+
///
133+
/// # Safety
134+
///
135+
/// Should only be implemented for types which are `!Send` **solely** because they contain information specific
136+
/// to their thread local [INTERNER] (e.g. by containing [InternedString]s).
137+
pub unsafe trait InternerSpecific {}
138+
139+
/// Since [WithInterner<T>] guarantees that the inner `T` cannot be accessed without updating the
140+
/// thread local [INTERNER] to a copy of what was used to generate `T`, it is safe to send between threads,
141+
/// even if the inner `T` contains [InternedString]s which are not [Send] on their own.
142+
unsafe impl<T: InternerSpecific> Send for WithInterner<T> {}
143+
144+
/// A type `T` bundled with the [StringInterner] that was used to generate it.
145+
///
146+
/// The only way to access the inner `T` is by calling `into_inner()`, which will automatically
147+
/// update the current thread's interner to the interner used the generate `T`,
148+
/// ensuring interner coherence between the sending & receiving threads.
149+
pub struct WithInterner<T> {
150+
interner: StringInterner<StringBackend>,
151+
inner: T,
152+
}
153+
154+
impl<T> WithInterner<T> {
155+
/// Create a new wrapper of `inner` with a clone of the current thread local [INTERNER].
156+
pub fn new_with_current(inner: T) -> Self {
157+
let interner = INTERNER.with_borrow(|i| i.clone());
158+
WithInterner { interner, inner }
159+
}
160+
161+
/// Get the inner wrapped `T` and implicitly update the current thread local [INTERNER] with a
162+
/// copy of the one used to generate `T`.
163+
pub fn into_inner(self) -> T {
164+
INTERNER.with_borrow_mut(|i| *i = self.interner);
165+
self.inner
166+
}
167+
}
168+
}
169+
108170
#[cfg(test)]
109171
mod tests {
110172
use crate::cbmc_string::InternedString;

cprover_bindings/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
3232
#![feature(f128)]
3333
#![feature(f16)]
34+
#![feature(negative_impls)]
3435

3536
mod env;
3637
pub use env::global_dead_object;
@@ -41,4 +42,5 @@ pub mod utils;
4142
pub use irep::serialize;
4243
pub use machine_model::{MachineModel, RoundingMode};
4344
mod cbmc_string;
45+
pub use cbmc_string::sync::{InternerSpecific, WithInterner};
4446
pub use cbmc_string::{InternString, InternStringOption, InternedString};

docs/src/reference/experimental/autoharness.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ please add them to [this GitHub issue](https://github.com/model-checking/kani/is
104104
## Limitations
105105
### Arguments Implementing Arbitrary
106106
Kani will only generate an automatic harness for a function if it can represent each of its arguments nondeterministically, without bounds.
107-
In technical terms, each of the arguments needs to implement the `Arbitrary` trait or be capable of deriving it.
107+
In technical terms, each of the arguments needs to implement the `Arbitrary`
108+
trait or be capable of deriving it, or be a reference (mutable or immutable)
109+
where any of the prior requirements is fulfilled by the referenced type.
108110
Kani will detect if a struct or enum could implement `Arbitrary` and derive it automatically.
109111
Note that this automatic derivation feature is only available for autoharness.
110112

0 commit comments

Comments
 (0)