Skip to content

Commit f845335

Browse files
committed
Auto merge of #127119 - RalfJung:miri-sync, r=RalfJung
Miri subtree update r? `@ghost`
2 parents be99243 + 9d920ed commit f845335

Some content is hidden

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

63 files changed

+906
-417
lines changed

src/tools/miri/.github/workflows/ci.yml

+2-85
Original file line numberDiff line numberDiff line change
@@ -33,50 +33,7 @@ jobs:
3333
HOST_TARGET: ${{ matrix.host_target }}
3434
steps:
3535
- uses: actions/checkout@v4
36-
37-
- name: Show Rust version (stable toolchain)
38-
run: |
39-
rustup show
40-
rustc -Vv
41-
cargo -V
42-
43-
# Cache the global cargo directory, but NOT the local `target` directory which
44-
# we cannot reuse anyway when the nightly changes (and it grows quite large
45-
# over time).
46-
- name: Add cache for cargo
47-
id: cache
48-
uses: actions/cache@v4
49-
with:
50-
path: |
51-
# Taken from <https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci>.
52-
# Cache package/registry information
53-
~/.cargo/registry/index
54-
~/.cargo/registry/cache
55-
~/.cargo/git/db
56-
# Cache installed binaries
57-
~/.cargo/bin
58-
~/.cargo/.crates.toml
59-
~/.cargo/.crates2.json
60-
key: cargo-${{ runner.os }}-reset20240425-${{ hashFiles('**/Cargo.lock') }}
61-
restore-keys: cargo-${{ runner.os }}-reset20240425
62-
63-
- name: Install tools
64-
if: steps.cache.outputs.cache-hit != 'true'
65-
run: cargo install -f rustup-toolchain-install-master hyperfine
66-
67-
- name: Install miri toolchain
68-
run: |
69-
if [[ ${{ github.event_name }} == 'schedule' ]]; then
70-
echo "Building against latest rustc git version"
71-
git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1 > rust-version
72-
fi
73-
./miri toolchain --host ${{ matrix.host_target }}
74-
75-
- name: Show Rust version (miri toolchain)
76-
run: |
77-
rustup show
78-
rustc -Vv
79-
cargo -V
36+
- uses: ./.github/workflows/setup
8037

8138
# The `style` job only runs on Linux; this makes sure the Windows-host-specific
8239
# code is also covered by clippy.
@@ -92,47 +49,7 @@ jobs:
9249
runs-on: ubuntu-latest
9350
steps:
9451
- uses: actions/checkout@v4
95-
96-
# This is exactly duplicated from above. GHA is pretty terrible when it comes
97-
# to avoiding code duplication.
98-
99-
# Cache the global cargo directory, but NOT the local `target` directory which
100-
# we cannot reuse anyway when the nightly changes (and it grows quite large
101-
# over time).
102-
- name: Add cache for cargo
103-
id: cache
104-
uses: actions/cache@v4
105-
with:
106-
path: |
107-
# Taken from <https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci>.
108-
# Cache package/registry information
109-
~/.cargo/registry/index
110-
~/.cargo/registry/cache
111-
~/.cargo/git/db
112-
# Cache installed binaries
113-
~/.cargo/bin
114-
~/.cargo/.crates.toml
115-
~/.cargo/.crates2.json
116-
key: cargo-${{ runner.os }}-reset20240331-${{ hashFiles('**/Cargo.lock') }}
117-
restore-keys: cargo-${{ runner.os }}-reset20240331
118-
119-
- name: Install rustup-toolchain-install-master
120-
if: steps.cache.outputs.cache-hit != 'true'
121-
run: cargo install -f rustup-toolchain-install-master
122-
123-
- name: Install "master" toolchain
124-
run: |
125-
if [[ ${{ github.event_name }} == 'schedule' ]]; then
126-
echo "Building against latest rustc git version"
127-
git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1 > rust-version
128-
fi
129-
./miri toolchain
130-
131-
- name: Show Rust version
132-
run: |
133-
rustup show
134-
rustc -Vv
135-
cargo -V
52+
- uses: ./.github/workflows/setup
13653

13754
- name: rustfmt
13855
run: ./miri fmt --check
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: "Miri CI setup"
2+
description: "Sets up Miri CI"
3+
runs:
4+
using: "composite"
5+
steps:
6+
- name: Show Rust version (stable toolchain)
7+
run: |
8+
rustup show
9+
rustc -Vv
10+
cargo -V
11+
shell: bash
12+
13+
# Cache the global cargo directory, but NOT the local `target` directory which
14+
# we cannot reuse anyway when the nightly changes (and it grows quite large
15+
# over time).
16+
- name: Add cache for cargo
17+
id: cache
18+
uses: actions/cache@v4
19+
with:
20+
path: |
21+
# Taken from <https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci>.
22+
# Cache package/registry information
23+
~/.cargo/registry/index
24+
~/.cargo/registry/cache
25+
~/.cargo/git/db
26+
# Cache installed binaries
27+
~/.cargo/bin
28+
~/.cargo/.crates.toml
29+
~/.cargo/.crates2.json
30+
key: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock', '.github/workflows/**/*.yml') }}
31+
restore-keys: cargo-${{ runner.os }}
32+
33+
- name: Install rustup-toolchain-install-master
34+
if: steps.cache.outputs.cache-hit != 'true'
35+
run: cargo install -f rustup-toolchain-install-master hyperfine
36+
shell: bash
37+
38+
- name: Install "master" toolchain
39+
run: |
40+
if [[ ${{ github.event_name }} == 'schedule' ]]; then
41+
echo "Building against latest rustc git version"
42+
git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1 > rust-version
43+
fi
44+
./miri toolchain
45+
shell: bash
46+
47+
- name: Show Rust version (miri toolchain)
48+
run: |
49+
rustup show
50+
rustc -Vv
51+
cargo -V
52+
shell: bash

src/tools/miri/README.md

+12-6
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,13 @@ Further caveats that Miri users should be aware of:
7272
when `SeqCst` fences are used that are not actually permitted by the Rust memory model, and it
7373
cannot produce all behaviors possibly observable on real hardware.
7474

75-
Moreover, Miri fundamentally cannot tell you whether your code is *sound*. [Soundness] is the property
76-
of never causing undefined behavior when invoked from arbitrary safe code, even in combination with
75+
Moreover, Miri fundamentally cannot ensure that your code is *sound*. [Soundness] is the property of
76+
never causing undefined behavior when invoked from arbitrary safe code, even in combination with
7777
other sound code. In contrast, Miri can just tell you if *a particular way of interacting with your
78-
code* (e.g., a test suite) causes any undefined behavior. It is up to you to ensure sufficient
79-
coverage.
78+
code* (e.g., a test suite) causes any undefined behavior *in a particular execution* (of which there
79+
may be many, e.g. when concurrency or other forms of non-determinism are involved). When Miri finds
80+
UB, your code is definitely unsound, but when Miri does not find UB, then you may just have to test
81+
more inputs or more possible non-deterministic choices.
8082

8183
[rust]: https://www.rust-lang.org/
8284
[mir]: https://github.com/rust-lang/rfcs/blob/master/text/1211-mir.md
@@ -425,8 +427,12 @@ to Miri failing to detect cases of undefined behavior in a program.
425427
value from a load. This can help diagnose problems that disappear under
426428
`-Zmiri-disable-weak-memory-emulation`.
427429
* `-Zmiri-tree-borrows` replaces [Stacked Borrows] with the [Tree Borrows] rules.
428-
The soundness rules are already experimental without this flag, but even more
429-
so with this flag.
430+
Tree Borrows is even more experimental than Stacked Borrows. While Tree Borrows
431+
is still sound in the sense of catching all aliasing violations that current versions
432+
of the compiler might exploit, it is likely that the eventual final aliasing model
433+
of Rust will be stricter than Tree Borrows. In other words, if you use Tree Borrows,
434+
even if your code is accepted today, it might be declared UB in the future.
435+
This is much less likely with Stacked Borrows.
430436
* `-Zmiri-force-page-size=<num>` overrides the default page size for an architecture, in multiples of 1k.
431437
`4` is default for most targets. This value should always be a power of 2 and nonzero.
432438
* `-Zmiri-unique-is-unique` performs additional aliasing checks for `core::ptr::Unique` to ensure

src/tools/miri/build.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
fn main() {
22
// Don't rebuild miri when nothing changed.
33
println!("cargo:rerun-if-changed=build.rs");
4-
// Re-export the TARGET environment variable so it can
5-
// be accessed by miri.
4+
// Re-export the TARGET environment variable so it can be accessed by miri. Needed to know the
5+
// "host" triple inside Miri.
66
let target = std::env::var("TARGET").unwrap();
77
println!("cargo:rustc-env=TARGET={target}");
8+
// Allow some cfgs.
9+
println!("cargo::rustc-check-cfg=cfg(bootstrap)");
810
}

src/tools/miri/cargo-miri/src/phases.rs

+6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ Subcommands:
2323
clean Clean the Miri cache & target directory
2424
2525
The cargo options are exactly the same as for `cargo run` and `cargo test`, respectively.
26+
Furthermore, the following extra flags and environment variables are recognized for `run` and `test`:
27+
28+
--many-seeds[=from..to] Run the program/tests many times with different seeds in the given range.
29+
The range defaults to `0..64`.
30+
31+
MIRIFLAGS Extra flags to pass to the Miri driver. Use this to pass `-Zmiri-...` flags.
2632
2733
Examples:
2834
cargo miri run

src/tools/miri/miri

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ set -e
33
# Instead of doing just `cargo run --manifest-path .. $@`, we invoke miri-script binary directly. Invoking `cargo run` goes through
44
# rustup (that sets it's own environmental variables), which is undesirable.
55
MIRI_SCRIPT_TARGET_DIR="$(dirname "$0")"/miri-script/target
6-
cargo +stable build $CARGO_EXTRA_FLAGS -q --target-dir "$MIRI_SCRIPT_TARGET_DIR" --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml
6+
cargo +stable build $CARGO_EXTRA_FLAGS -q --target-dir "$MIRI_SCRIPT_TARGET_DIR" --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml || \
7+
( echo "Failed to build miri-script. Is the 'stable' toolchain installed?"; exit 1 )
78
"$MIRI_SCRIPT_TARGET_DIR"/debug/miri-script "$@"

src/tools/miri/miri-script/src/commands.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -252,12 +252,11 @@ impl Command {
252252
// Fetch given rustc commit.
253253
cmd!(sh, "git fetch http://localhost:{JOSH_PORT}/rust-lang/rust.git@{commit}{JOSH_FILTER}.git")
254254
.run()
255-
.map_err(|e| {
255+
.inspect_err(|_| {
256256
// Try to un-do the previous `git commit`, to leave the repo in the state we found it.
257257
cmd!(sh, "git reset --hard HEAD^")
258258
.run()
259259
.expect("FAILED to clean up again after failed `git fetch`, sorry for that");
260-
e
261260
})
262261
.context("FAILED to fetch new commits, something went wrong (committing the rust-version file has been undone)")?;
263262

@@ -545,9 +544,8 @@ impl Command {
545544
if let Some(seed_range) = many_seeds {
546545
e.run_many_times(seed_range, |sh, seed| {
547546
eprintln!("Trying seed: {seed}");
548-
run_miri(sh, Some(format!("-Zmiri-seed={seed}"))).map_err(|err| {
547+
run_miri(sh, Some(format!("-Zmiri-seed={seed}"))).inspect_err(|_| {
549548
eprintln!("FAILING SEED: {seed}");
550-
err
551549
})
552550
})?;
553551
} else {

src/tools/miri/miri-script/src/util.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,9 @@ impl MiriEnv {
219219
break;
220220
}
221221
// Run the command with this seed.
222-
run(&local_shell, cur).map_err(|err| {
222+
run(&local_shell, cur).inspect_err(|_| {
223223
// If we failed, tell everyone about this.
224224
failed.store(true, Ordering::Relaxed);
225-
err
226225
})?;
227226
// Check if some other command failed (in which case we'll stop as well).
228227
if failed.load(Ordering::Relaxed) {

src/tools/miri/miri.bat

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ set MIRI_SCRIPT_TARGET_DIR=%0\..\miri-script\target
55

66
:: If any other steps are added, the "|| exit /b" must be appended to early
77
:: return from the script. If not, it will continue execution.
8-
cargo +stable build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml || exit /b
8+
cargo +stable build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml ^
9+
|| (echo Failed to build miri-script. Is the 'stable' toolchain installed? & exit /b)
910

1011
:: Forwards all arguments to this file to the executable.
1112
:: We invoke the binary directly to avoid going through rustup, which would set some extra

src/tools/miri/rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
f6b4b71ef10307201b52c17b0f9dcf9557cd90ba
1+
9ed2ab3790ff41bf741dd690befd6a1c1e2b23ca

src/tools/miri/src/alloc_addresses/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl GlobalStateInner {
9797
fn align_addr(addr: u64, align: u64) -> u64 {
9898
match addr % align {
9999
0 => addr,
100-
rem => addr.checked_add(align).unwrap() - rem,
100+
rem => addr.strict_add(align) - rem,
101101
}
102102
}
103103

src/tools/miri/src/alloc_bytes.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,19 @@ impl MiriAllocBytes {
6464
/// If `size == 0` we allocate using a different `alloc_layout` with `size = 1`, to ensure each allocation has a unique address.
6565
/// Returns `Err(alloc_layout)` if the allocation function returns a `ptr` where `ptr.is_null()`.
6666
fn alloc_with(
67-
size: usize,
68-
align: usize,
67+
size: u64,
68+
align: u64,
6969
alloc_fn: impl FnOnce(Layout) -> *mut u8,
70-
) -> Result<MiriAllocBytes, Layout> {
71-
let layout = Layout::from_size_align(size, align).unwrap();
70+
) -> Result<MiriAllocBytes, ()> {
71+
let size = usize::try_from(size).map_err(|_| ())?;
72+
let align = usize::try_from(align).map_err(|_| ())?;
73+
let layout = Layout::from_size_align(size, align).map_err(|_| ())?;
7274
// When size is 0 we allocate 1 byte anyway, to ensure each allocation has a unique address.
7375
let alloc_layout =
7476
if size == 0 { Layout::from_size_align(1, align).unwrap() } else { layout };
7577
let ptr = alloc_fn(alloc_layout);
7678
if ptr.is_null() {
77-
Err(alloc_layout)
79+
Err(())
7880
} else {
7981
// SAFETY: All `MiriAllocBytes` invariants are fulfilled.
8082
Ok(Self { ptr, layout })
@@ -86,20 +88,22 @@ impl AllocBytes for MiriAllocBytes {
8688
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align) -> Self {
8789
let slice = slice.into();
8890
let size = slice.len();
89-
let align = align.bytes_usize();
91+
let align = align.bytes();
9092
// SAFETY: `alloc_fn` will only be used with `size != 0`.
9193
let alloc_fn = |layout| unsafe { alloc::alloc(layout) };
92-
let alloc_bytes = MiriAllocBytes::alloc_with(size, align, alloc_fn)
93-
.unwrap_or_else(|layout| alloc::handle_alloc_error(layout));
94+
let alloc_bytes = MiriAllocBytes::alloc_with(size.try_into().unwrap(), align, alloc_fn)
95+
.unwrap_or_else(|()| {
96+
panic!("Miri ran out of memory: cannot create allocation of {size} bytes")
97+
});
9498
// SAFETY: `alloc_bytes.ptr` and `slice.as_ptr()` are non-null, properly aligned
9599
// and valid for the `size`-many bytes to be copied.
96100
unsafe { alloc_bytes.ptr.copy_from(slice.as_ptr(), size) };
97101
alloc_bytes
98102
}
99103

100104
fn zeroed(size: Size, align: Align) -> Option<Self> {
101-
let size = size.bytes_usize();
102-
let align = align.bytes_usize();
105+
let size = size.bytes();
106+
let align = align.bytes();
103107
// SAFETY: `alloc_fn` will only be used with `size != 0`.
104108
let alloc_fn = |layout| unsafe { alloc::alloc_zeroed(layout) };
105109
MiriAllocBytes::alloc_with(size, align, alloc_fn).ok()

src/tools/miri/src/bin/miri.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,9 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
9898
}
9999

100100
if tcx.sess.opts.optimize != OptLevel::No {
101-
tcx.dcx().warn("Miri does not support optimizations. If you have enabled optimizations \
102-
by selecting a Cargo profile (such as --release) which changes other profile settings \
103-
such as whether debug assertions and overflow checks are enabled, those settings are \
104-
still applied.");
101+
tcx.dcx().warn("Miri does not support optimizations: the opt-level is ignored. The only effect \
102+
of selecting a Cargo profile that enables optimizations (such as --release) is to apply \
103+
its remaining settings, such as whether debug assertions and overflow checks are enabled.");
105104
}
106105
if tcx.sess.mir_opt_level() > 0 {
107106
tcx.dcx().warn("You have explicitly enabled MIR optimizations, overriding Miri's default \

src/tools/miri/src/concurrency/thread.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,7 @@ impl<'tcx> ThreadManager<'tcx> {
643643
if !self.threads[joined_thread_id].state.is_terminated() {
644644
trace!(
645645
"{:?} blocked on {:?} when trying to join",
646-
self.active_thread,
647-
joined_thread_id
646+
self.active_thread, joined_thread_id
648647
);
649648
// The joined thread is still running, we need to wait for it.
650649
// Unce we get unblocked, perform the appropriate synchronization.

0 commit comments

Comments
 (0)