Skip to content

Commit fdbde32

Browse files
committed
Auto merge of #123041 - RalfJung:miri, r=RalfJung
Miri subtree update r? `@ghost`
2 parents 415e29b + c941fcd commit fdbde32

File tree

14 files changed

+141
-27
lines changed

14 files changed

+141
-27
lines changed

Diff for: .github/workflows/ci.yml

+9-4
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,16 @@ jobs:
3030
host_target: i686-pc-windows-msvc
3131
runs-on: ${{ matrix.os }}
3232
env:
33-
RUST_BACKTRACE: 1
3433
HOST_TARGET: ${{ matrix.host_target }}
3534
steps:
3635
- uses: actions/checkout@v3
3736

37+
- name: Show Rust version (stable toolchain)
38+
run: |
39+
rustup show
40+
rustc -Vv
41+
cargo -V
42+
3843
# Cache the global cargo directory, but NOT the local `target` directory which
3944
# we cannot reuse anyway when the nightly changes (and it grows quite large
4045
# over time).
@@ -58,21 +63,21 @@ jobs:
5863
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
5964
run: cargo install -f rustup-toolchain-install-master
6065

61-
- name: Install "master" toolchain
66+
- name: Install miri toolchain
6267
run: |
6368
if [[ ${{ github.event_name }} == 'schedule' ]]; then
6469
echo "Building against latest rustc git version"
6570
git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1 > rust-version
6671
fi
6772
./miri toolchain --host ${{ matrix.host_target }}
6873
69-
- name: Show Rust version
74+
- name: Show Rust version (miri toolchain)
7075
run: |
7176
rustup show
7277
rustc -Vv
7378
cargo -V
7479
75-
- name: Test
80+
- name: Test Miri
7681
run: ./ci/ci.sh
7782

7883
style:

Diff for: CONTRIBUTING.md

+10-5
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,22 @@ For example, you can (cross-)run the driver on a particular file by doing
6464
./miri run tests/pass/hello.rs --target i686-unknown-linux-gnu
6565
```
6666

67-
and you can (cross-)run the entire test suite using:
67+
Tests in ``pass-dep`` need to be run using ``./miri run --dep <filename>``.
68+
For example:
69+
```sh
70+
./miri run --dep tests/pass-dep/shims/libc-fs.rs
71+
```
72+
73+
You can (cross-)run the entire test suite using:
6874

6975
```
7076
./miri test
7177
MIRI_TEST_TARGET=i686-unknown-linux-gnu ./miri test
7278
```
7379

74-
If your target doesn't support libstd that should usually just work. However, if you are using a
75-
custom target file, you might have to set `MIRI_NO_STD=1`.
76-
7780
`./miri test FILTER` only runs those tests that contain `FILTER` in their filename (including the
7881
base directory, e.g. `./miri test fail` will run all compile-fail tests). These filters are passed
79-
to `cargo test`, so for multiple filers you need to use `./miri test -- FILTER1 FILTER2`.
82+
to `cargo test`, so for multiple filters you need to use `./miri test -- FILTER1 FILTER2`.
8083

8184
#### Fine grained logging
8285

@@ -178,6 +181,7 @@ to `.vscode/settings.json` in your local Miri clone:
178181
"cargo",
179182
"clippy", // make this `check` when working with a locally built rustc
180183
"--message-format=json",
184+
"--all-targets",
181185
],
182186
// Contrary to what the name suggests, this also affects proc macros.
183187
"rust-analyzer.cargo.buildScripts.overrideCommand": [
@@ -187,6 +191,7 @@ to `.vscode/settings.json` in your local Miri clone:
187191
"cargo",
188192
"check",
189193
"--message-format=json",
194+
"--all-targets",
190195
],
191196
}
192197
```

Diff for: cargo-miri/src/main.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,18 @@ use std::{env, iter};
1111

1212
use crate::phases::*;
1313

14+
/// Returns `true` if our flags look like they may be for rustdoc, i.e., this is cargo calling us to
15+
/// be rustdoc. It's hard to be sure as cargo does not have a RUSTDOC_WRAPPER or an env var that
16+
/// would let us get a clear signal.
17+
fn looks_like_rustdoc() -> bool {
18+
// The `--test-run-directory` flag only exists for rustdoc and cargo always passes it. Perfect!
19+
env::args().any(|arg| arg == "--test-run-directory")
20+
}
21+
1422
fn main() {
1523
// Rustc does not support non-UTF-8 arguments so we make no attempt either.
1624
// (We do support non-UTF-8 environment variables though.)
17-
let mut args = std::env::args();
25+
let mut args = env::args();
1826
// Skip binary name.
1927
args.next().unwrap();
2028

@@ -91,10 +99,16 @@ fn main() {
9199
// (see https://github.com/rust-lang/cargo/issues/10886).
92100
phase_rustc(args, RustcPhase::Build)
93101
}
94-
_ => {
95-
// Everything else must be rustdoc. But we need to get `first` "back onto the iterator",
102+
_ if looks_like_rustdoc() => {
103+
// This is probably rustdoc. But we need to get `first` "back onto the iterator",
96104
// it is some part of the rustdoc invocation.
97105
phase_rustdoc(iter::once(first).chain(args));
98106
}
107+
_ => {
108+
show_error!(
109+
"`cargo-miri` failed to recognize which phase of the build process this is, please report a bug.\nThe command-line arguments were: {:#?}",
110+
Vec::from_iter(env::args()),
111+
);
112+
}
99113
}
100114
}

Diff for: cargo-miri/src/phases.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
620620

621621
// The `--test-builder` and `--runtool` arguments are unstable rustdoc features,
622622
// which are disabled by default. We first need to enable them explicitly:
623-
cmd.arg("-Z").arg("unstable-options");
623+
cmd.arg("-Zunstable-options");
624624

625625
// rustdoc needs to know the right sysroot.
626626
cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());

Diff for: ci/ci.sh

+12-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ function endgroup {
1313

1414
begingroup "Building Miri"
1515

16+
# Special Windows hacks
17+
if [ "$HOST_TARGET" = i686-pc-windows-msvc ]; then
18+
# The $BASH variable is `/bin/bash` here, but that path does not actually work. There are some
19+
# hacks in place somewhere to try to paper over this, but the hacks dont work either (see
20+
# <https://github.com/rust-lang/miri/pull/3402>). So we hard-code the correct location for Github
21+
# CI instead.
22+
BASH="C:/Program Files/Git/usr/bin/bash"
23+
fi
24+
1625
# Determine configuration for installed build
1726
echo "Installing release version of Miri"
1827
export RUSTFLAGS="-D warnings"
@@ -58,12 +67,13 @@ function run_tests {
5867
MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
5968

6069
# Also run some many-seeds tests. 64 seeds means this takes around a minute per test.
70+
# (Need to invoke via explicit `bash -c` for Windows.)
6171
for FILE in tests/many-seeds/*.rs; do
62-
MIRI_SEEDS=64 ./miri many-seeds ./miri run "$FILE"
72+
MIRI_SEEDS=64 ./miri many-seeds "$BASH" -c "./miri run '$FILE'"
6373
done
6474

6575
# Check that the benchmarks build and run, but without actually benchmarking.
66-
HYPERFINE="bash -c" ./miri bench
76+
HYPERFINE="'$BASH' -c" ./miri bench
6777
fi
6878

6979
## test-cargo-miri

Diff for: miri

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ 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 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
77
"$MIRI_SCRIPT_TARGET_DIR"/debug/miri-script "$@"

Diff for: miri-script/src/commands.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ impl Command {
178178
.context("Please install rustup-toolchain-install-master by running 'cargo install rustup-toolchain-install-master'")?;
179179
let sh = Shell::new()?;
180180
sh.change_dir(miri_dir()?);
181-
let new_commit = Some(sh.read_file("rust-version")?.trim().to_owned());
181+
let new_commit = sh.read_file("rust-version")?.trim().to_owned();
182182
let current_commit = {
183183
let rustc_info = cmd!(sh, "rustc +miri --version -v").read();
184184
if rustc_info.is_err() {
@@ -193,7 +193,7 @@ impl Command {
193193
}
194194
};
195195
// Check if we already are at that commit.
196-
if current_commit == new_commit {
196+
if current_commit.as_ref() == Some(&new_commit) {
197197
if active_toolchain()? != "miri" {
198198
cmd!(sh, "rustup override set miri").run()?;
199199
}
@@ -202,7 +202,7 @@ impl Command {
202202
// Install and setup new toolchain.
203203
cmd!(sh, "rustup toolchain uninstall miri").run()?;
204204

205-
cmd!(sh, "rustup-toolchain-install-master -n miri -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy {flags...} -- {new_commit...}").run()?;
205+
cmd!(sh, "rustup-toolchain-install-master -n miri -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy {flags...} -- {new_commit}").run()?;
206206
cmd!(sh, "rustup override set miri").run()?;
207207
// Cleanup.
208208
cmd!(sh, "cargo clean").run()?;
@@ -380,9 +380,9 @@ impl Command {
380380
.env("MIRIFLAGS", miriflags)
381381
.quiet()
382382
.run();
383-
if status.is_err() {
383+
if let Err(err) = status {
384384
println!("Failing seed: {seed}");
385-
break;
385+
return Err(err.into());
386386
}
387387
}
388388
Ok(())

Diff for: miri.bat

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ 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 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 || exit /b
99

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

Diff for: rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
c3b05c6e5b5b59613350b8c2875b0add67ed74df
1+
cb7c63606e53715f94f3ba04d38e50772e4cd23d

Diff for: src/bin/miri.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ fn run_compiler(
276276
// If no `--sysroot` is given, the `MIRI_SYSROOT` env var is consulted to find where
277277
// that sysroot lives, and that is passed to rustc.
278278
let sysroot_flag = "--sysroot";
279-
if !args.iter().any(|e| e == sysroot_flag) {
279+
if !args.iter().any(|e| e.starts_with(sysroot_flag)) {
280280
// Using the built-in default here would be plain wrong, so we *require*
281281
// the env var to make sure things make sense.
282282
let miri_sysroot = env::var("MIRI_SYSROOT").unwrap_or_else(|_| {

Diff for: test-cargo-miri/Cargo.lock

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: test-cargo-miri/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ issue_rust_86261 = { path = "issue-rust-86261" }
2222
byteorder_2 = { package = "byteorder", version = "0.5" } # to test dev-dependencies behave as expected, with renaming
2323
# Not actually used, but exercises some unique code path (`--extern` .so file).
2424
serde_derive = "1.0.185"
25+
# Not actually used, but uses a custom build probe so let's make sure that works.
26+
# (Ideally we'd check if the probe was successful, but that's not easily possible.)
27+
anyhow = "1.0"
2528

2629
[build-dependencies]
2730
autocfg = "1"

Diff for: tests/pass-dep/shims/libc-fs.rs

+63
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ mod utils;
1616
fn main() {
1717
test_dup_stdout_stderr();
1818
test_canonicalize_too_long();
19+
test_rename();
20+
test_ftruncate::<libc::off_t>(libc::ftruncate);
21+
#[cfg(target_os = "linux")]
22+
test_ftruncate::<libc::off64_t>(libc::ftruncate64);
1923
test_readlink();
2024
test_file_open_unix_allow_two_args();
2125
test_file_open_unix_needs_three_args();
@@ -133,6 +137,65 @@ fn test_readlink() {
133137
assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
134138
}
135139

140+
fn test_rename() {
141+
let path1 = prepare("miri_test_libc_fs_source.txt");
142+
let path2 = prepare("miri_test_libc_fs_rename_destination.txt");
143+
144+
let file = File::create(&path1).unwrap();
145+
drop(file);
146+
147+
let c_path1 = CString::new(path1.as_os_str().as_bytes()).expect("CString::new failed");
148+
let c_path2 = CString::new(path2.as_os_str().as_bytes()).expect("CString::new failed");
149+
150+
// Renaming should succeed
151+
unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) };
152+
// Check that old file path isn't present
153+
assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind());
154+
// Check that the file has moved successfully
155+
assert!(path2.metadata().unwrap().is_file());
156+
157+
// Renaming a nonexistent file should fail
158+
let res = unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) };
159+
assert_eq!(res, -1);
160+
assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
161+
162+
remove_file(&path2).unwrap();
163+
}
164+
165+
fn test_ftruncate<T: From<i32>>(
166+
ftruncate: unsafe extern "C" fn(fd: libc::c_int, length: T) -> libc::c_int,
167+
) {
168+
// libc::off_t is i32 in target i686-unknown-linux-gnu
169+
// https://docs.rs/libc/latest/i686-unknown-linux-gnu/libc/type.off_t.html
170+
171+
let bytes = b"hello";
172+
let path = prepare("miri_test_libc_fs_ftruncate.txt");
173+
let mut file = File::create(&path).unwrap();
174+
file.write(bytes).unwrap();
175+
file.sync_all().unwrap();
176+
assert_eq!(file.metadata().unwrap().len(), 5);
177+
178+
let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed");
179+
let fd = unsafe { libc::open(c_path.as_ptr(), libc::O_RDWR) };
180+
181+
// Truncate to a bigger size
182+
let mut res = unsafe { ftruncate(fd, T::from(10)) };
183+
assert_eq!(res, 0);
184+
assert_eq!(file.metadata().unwrap().len(), 10);
185+
186+
// Write after truncate
187+
file.write(b"dup").unwrap();
188+
file.sync_all().unwrap();
189+
assert_eq!(file.metadata().unwrap().len(), 10);
190+
191+
// Truncate to smaller size
192+
res = unsafe { ftruncate(fd, T::from(2)) };
193+
assert_eq!(res, 0);
194+
assert_eq!(file.metadata().unwrap().len(), 2);
195+
196+
remove_file(&path).unwrap();
197+
}
198+
136199
#[cfg(target_os = "linux")]
137200
fn test_o_tmpfile_flag() {
138201
use std::fs::{create_dir, OpenOptions};

Diff for: tests/ui.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ use std::ffi::OsString;
44
use std::num::NonZeroUsize;
55
use std::path::{Path, PathBuf};
66
use std::{env, process::Command};
7-
use ui_test::{color_eyre::Result, Config, Match, Mode, OutputConflictHandling};
8-
use ui_test::{status_emitter, CommandBuilder, Format, RustfixMode};
7+
use ui_test::color_eyre::eyre::{Context, Result};
8+
use ui_test::{
9+
status_emitter, CommandBuilder, Config, Format, Match, Mode, OutputConflictHandling,
10+
RustfixMode,
11+
};
912

1013
fn miri_path() -> PathBuf {
1114
PathBuf::from(option_env!("MIRI").unwrap_or(env!("CARGO_BIN_EXE_miri")))
@@ -124,6 +127,9 @@ fn run_tests(
124127
// Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
125128
config.program.envs.push(("MIRI_TEMP".into(), Some(tmpdir.to_owned().into())));
126129

130+
// If a test ICEs, we want to see a backtrace.
131+
config.program.envs.push(("RUST_BACKTRACE".into(), Some("1".into())));
132+
127133
// Handle command-line arguments.
128134
let args = ui_test::Args::test()?;
129135
let default_bless = env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
@@ -223,14 +229,15 @@ fn ui(
223229
with_dependencies: Dependencies,
224230
tmpdir: &Path,
225231
) -> Result<()> {
226-
let msg = format!("## Running ui tests in {path} against miri for {target}");
232+
let msg = format!("## Running ui tests in {path} for {target}");
227233
eprintln!("{}", msg.green().bold());
228234

229235
let with_dependencies = match with_dependencies {
230236
WithDependencies => true,
231237
WithoutDependencies => false,
232238
};
233239
run_tests(mode, path, target, with_dependencies, tmpdir)
240+
.with_context(|| format!("ui tests in {path} for {target} failed"))
234241
}
235242

236243
fn get_target() -> String {

0 commit comments

Comments
 (0)