Skip to content

Commit 3521a2f

Browse files
committedMar 10, 2024
Auto merge of rust-lang#122246 - RalfJung:miri, r=RalfJung
Miri subtree update r? `@ghost` `@WaffleLapkin` when this lands, setting `MIRI_TEMP` should not be needed any more on the dev desktops.
2 parents 094a620 + 9a308d4 commit 3521a2f

36 files changed

+239
-260
lines changed
 

‎Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -2485,6 +2485,7 @@ dependencies = [
24852485
"regex",
24862486
"rustc_version",
24872487
"smallvec",
2488+
"tempfile",
24882489
"ui_test 0.21.2",
24892490
]
24902491

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ jobs:
187187
run: RUSTFLAGS="--cap-lints warn" cargo +stable install josh-proxy --git https://github.com/josh-project/josh --tag r22.12.06
188188
- name: setup bot git name and email
189189
run: |
190-
git config --global user.name 'The Miri Conjob Bot'
190+
git config --global user.name 'The Miri Cronjob Bot'
191191
git config --global user.email 'miri@cron.bot'
192192
- name: get changes from rustc
193193
run: ./miri rustc-pull

‎src/tools/miri/Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ dependencies = [
497497
"regex",
498498
"rustc_version",
499499
"smallvec",
500+
"tempfile",
500501
"ui_test",
501502
]
502503

‎src/tools/miri/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,15 @@ ui_test = "0.21.1"
4545
rustc_version = "0.4"
4646
regex = "1.5.5"
4747
lazy_static = "1.4.0"
48+
tempfile = "3"
4849

4950
[package.metadata.rust-analyzer]
5051
# This crate uses #[feature(rustc_private)].
5152
# See https://github.com/rust-analyzer/rust-analyzer/pull/7891
5253
rustc_private = true
5354

5455
[[test]]
55-
name = "compiletest"
56+
name = "ui"
5657
harness = false
5758

5859
[features]

‎src/tools/miri/README.md

+3-9
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,8 @@ environment variable. We first document the most relevant and most commonly used
318318
and `warn-nobacktrace` are the supported actions. The default is to `abort`,
319319
which halts the machine. Some (but not all) operations also support continuing
320320
execution with a "permission denied" error being returned to the program.
321-
`warn` prints a full backtrace when that happens; `warn-nobacktrace` is less
322-
verbose. `hide` hides the warning entirely.
321+
`warn` prints a full backtrace each time that happens; `warn-nobacktrace` is less
322+
verbose and shown at most once per operation. `hide` hides the warning entirely.
323323
* `-Zmiri-num-cpus` states the number of available CPUs to be reported by miri. By default, the
324324
number of available CPUs is `1`. Note that this flag does not affect how miri handles threads in
325325
any way.
@@ -359,8 +359,6 @@ The remaining flags are for advanced use only, and more likely to change or be r
359359
Some of these are **unsound**, which means they can lead
360360
to Miri failing to detect cases of undefined behavior in a program.
361361

362-
* `-Zmiri-disable-abi-check` disables checking [function ABI]. Using this flag
363-
is **unsound**. This flag is **deprecated**.
364362
* `-Zmiri-disable-alignment-check` disables checking pointer alignment, so you
365363
can focus on other failures, but it means Miri can miss bugs in your program.
366364
Using this flag is **unsound**.
@@ -465,11 +463,7 @@ Moreover, Miri recognizes some environment variables:
465463
* `MIRI_LIB_SRC` defines the directory where Miri expects the sources of the
466464
standard library that it will build and use for interpretation. This directory
467465
must point to the `library` subdirectory of a `rust-lang/rust` repository
468-
checkout. Note that changing files in that directory does not automatically
469-
trigger a re-build of the standard library; you have to clear the Miri build
470-
cache with `cargo miri clean` or deleting it manually (on Linux, `rm -rf ~/.cache/miri`;
471-
on Windows, `rmdir /S "%LOCALAPPDATA%\rust-lang\miri\cache"`;
472-
and on macOS, `rm -rf ~/Library/Caches/org.rust-lang.miri`).
466+
checkout.
473467
* `MIRI_SYSROOT` (recognized by `cargo miri` and the Miri driver) indicates the sysroot to use. When
474468
using `cargo miri`, this skips the automatic setup -- only set this if you do not want to use the
475469
automatically created sysroot. For directly invoking the Miri driver, this variable (or a

‎src/tools/miri/ci/build-all-targets.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ PLATFORM_SUPPORT_FILE=$(rustc +miri --print sysroot)/share/doc/rust/html/rustc/p
1212

1313
for target in $(python3 ci/scrape-targets.py $PLATFORM_SUPPORT_FILE); do
1414
# Wipe the cache before every build to minimize disk usage
15-
rm -rf ~/.cache/miri
15+
cargo +miri miri clean
1616
if cargo +miri miri setup --target $target 2>&1 | tee failures/$target; then
1717
# If the build succeeds, delete its output. If we have output, a build failed.
1818
rm $FAILS_DIR/$target

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

+20-30
Original file line numberDiff line numberDiff line change
@@ -510,11 +510,11 @@ impl Command {
510510
let miri_flags = flagsplit(&miri_flags);
511511
let toolchain = &e.toolchain;
512512
let extra_flags = &e.cargo_extra_flags;
513-
let edition_flags = (!have_edition).then_some("--edition=2021"); // keep in sync with `compiletest.rs`.`
513+
let edition_flags = (!have_edition).then_some("--edition=2021"); // keep in sync with `tests/ui.rs`.`
514514
if dep {
515515
cmd!(
516516
e.sh,
517-
"cargo +{toolchain} --quiet test --test compiletest {extra_flags...} --manifest-path {miri_manifest} -- --miri-run-dep-mode {miri_flags...} {edition_flags...} {flags...}"
517+
"cargo +{toolchain} --quiet test {extra_flags...} --manifest-path {miri_manifest} --test ui -- --miri-run-dep-mode {miri_flags...} {edition_flags...} {flags...}"
518518
).quiet().run()?;
519519
} else {
520520
cmd!(
@@ -526,37 +526,27 @@ impl Command {
526526
}
527527

528528
fn fmt(flags: Vec<OsString>) -> Result<()> {
529+
use itertools::Itertools;
530+
529531
let e = MiriEnv::new()?;
530-
let toolchain = &e.toolchain;
531532
let config_path = path!(e.miri_dir / "rustfmt.toml");
532533

533-
let mut cmd = cmd!(
534-
e.sh,
535-
"rustfmt +{toolchain} --edition=2021 --config-path {config_path} --unstable-features --skip-children {flags...}"
536-
);
537-
eprintln!("$ {cmd} ...");
538-
539-
// Add all the filenames to the command.
540-
// FIXME: `rustfmt` will follow the `mod` statements in these files, so we get a bunch of
541-
// duplicate diffs.
542-
for item in WalkDir::new(&e.miri_dir).into_iter().filter_entry(|entry| {
543-
let name = entry.file_name().to_string_lossy();
544-
let ty = entry.file_type();
545-
if ty.is_file() {
546-
name.ends_with(".rs")
547-
} else {
548-
// dir or symlink. skip `target` and `.git`.
549-
&name != "target" && &name != ".git"
550-
}
551-
}) {
552-
let item = item?;
553-
if item.file_type().is_file() {
554-
cmd = cmd.arg(item.into_path());
555-
}
556-
}
534+
// Collect each rust file in the miri repo.
535+
let files = WalkDir::new(&e.miri_dir)
536+
.into_iter()
537+
.filter_entry(|entry| {
538+
let name = entry.file_name().to_string_lossy();
539+
let ty = entry.file_type();
540+
if ty.is_file() {
541+
name.ends_with(".rs")
542+
} else {
543+
// dir or symlink. skip `target` and `.git`.
544+
&name != "target" && &name != ".git"
545+
}
546+
})
547+
.filter_ok(|item| item.file_type().is_file())
548+
.map_ok(|item| item.into_path());
557549

558-
// We want our own error message, repeating the command is too much.
559-
cmd.quiet().run().map_err(|_| anyhow!("`rustfmt` failed"))?;
560-
Ok(())
550+
e.format_files(files, &e.toolchain[..], &config_path, &flags[..])
561551
}
562552
}

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

+46-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::ffi::{OsStr, OsString};
2-
use std::path::PathBuf;
2+
use std::path::{Path, PathBuf};
33

4-
use anyhow::{Context, Result};
4+
use anyhow::{anyhow, Context, Result};
55
use dunce::canonicalize;
66
use path_macro::path;
77
use xshell::{cmd, Shell};
@@ -145,4 +145,48 @@ impl MiriEnv {
145145
.run()?;
146146
Ok(())
147147
}
148+
149+
/// Receives an iterator of files.
150+
/// Will format each file with the miri rustfmt config.
151+
/// Does not recursively format modules.
152+
pub fn format_files(
153+
&self,
154+
files: impl Iterator<Item = Result<PathBuf, walkdir::Error>>,
155+
toolchain: &str,
156+
config_path: &Path,
157+
flags: &[OsString],
158+
) -> anyhow::Result<()> {
159+
use itertools::Itertools;
160+
161+
let mut first = true;
162+
163+
// Format in batches as not all our files fit into Windows' command argument limit.
164+
for batch in &files.chunks(256) {
165+
// Build base command.
166+
let mut cmd = cmd!(
167+
self.sh,
168+
"rustfmt +{toolchain} --edition=2021 --config-path {config_path} --unstable-features --skip-children {flags...}"
169+
);
170+
if first {
171+
// Log an abbreviating command, and only once.
172+
eprintln!("$ {cmd} ...");
173+
first = false;
174+
}
175+
// Add files.
176+
for file in batch {
177+
// Make it a relative path so that on platforms with extremely tight argument
178+
// limits (like Windows), we become immune to someone cloning the repo
179+
// 50 directories deep.
180+
let file = file?;
181+
let file = file.strip_prefix(&self.miri_dir)?;
182+
cmd = cmd.arg(file);
183+
}
184+
185+
// Run rustfmt.
186+
// We want our own error message, repeating the command is too much.
187+
cmd.quiet().run().map_err(|_| anyhow!("`rustfmt` failed"))?;
188+
}
189+
190+
Ok(())
191+
}
148192
}

‎src/tools/miri/rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1a1876c9790f168fb51afa335a7ba3e6fc267d75
1+
4d4bb491b65c300835442f6cb4f34fc9a5685c26

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

+10-22
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
rustc::untranslatable_diagnostic
99
)]
1010

11+
// Some "regular" crates we want to share with rustc
12+
#[macro_use]
13+
extern crate tracing;
14+
15+
// The rustc crates we need
1116
extern crate rustc_data_structures;
1217
extern crate rustc_driver;
1318
extern crate rustc_hir;
@@ -16,8 +21,6 @@ extern crate rustc_log;
1621
extern crate rustc_metadata;
1722
extern crate rustc_middle;
1823
extern crate rustc_session;
19-
#[macro_use]
20-
extern crate tracing;
2124

2225
use std::env::{self, VarError};
2326
use std::num::NonZero;
@@ -202,16 +205,12 @@ fn rustc_logger_config() -> rustc_log::LoggerConfig {
202205
// rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_const_eval::interpret=debug`.
203206
if tracing::Level::from_str(&var).is_ok() {
204207
cfg.filter = Ok(format!(
205-
"rustc_middle::mir::interpret={var},rustc_const_eval::interpret={var}"
208+
"rustc_middle::mir::interpret={var},rustc_const_eval::interpret={var},miri={var}"
206209
));
207210
} else {
208211
cfg.filter = Ok(var);
209212
}
210213
}
211-
// Enable verbose entry/exit logging by default if MIRI_LOG is set.
212-
if matches!(cfg.verbose_entry_exit, Err(VarError::NotPresent)) {
213-
cfg.verbose_entry_exit = Ok(format!("1"));
214-
}
215214
}
216215

217216
cfg
@@ -342,7 +341,8 @@ fn main() {
342341
// (`install_ice_hook` might change `RUST_BACKTRACE`.)
343342
let env_snapshot = env::vars_os().collect::<Vec<_>>();
344343

345-
let args = rustc_driver::args::raw_args(&early_dcx).unwrap_or_else(|_| std::process::exit(rustc_driver::EXIT_FAILURE));
344+
let args = rustc_driver::args::raw_args(&early_dcx)
345+
.unwrap_or_else(|_| std::process::exit(rustc_driver::EXIT_FAILURE));
346346

347347
// If the environment asks us to actually be rustc, then do that.
348348
if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") {
@@ -408,17 +408,11 @@ fn main() {
408408
miri_config.check_alignment = miri::AlignmentCheck::None;
409409
} else if arg == "-Zmiri-symbolic-alignment-check" {
410410
miri_config.check_alignment = miri::AlignmentCheck::Symbolic;
411-
} else if arg == "-Zmiri-check-number-validity" {
412-
eprintln!(
413-
"WARNING: the flag `-Zmiri-check-number-validity` no longer has any effect \
414-
since it is now enabled by default"
415-
);
416411
} else if arg == "-Zmiri-disable-abi-check" {
417412
eprintln!(
418-
"WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed.\n\
419-
If you have a use-case for it, please file an issue."
413+
"WARNING: the flag `-Zmiri-disable-abi-check` no longer has any effect; \
414+
ABI checks cannot be disabled any more"
420415
);
421-
miri_config.check_abi = false;
422416
} else if arg == "-Zmiri-disable-isolation" {
423417
if matches!(isolation_enabled, Some(true)) {
424418
show_error!(
@@ -459,8 +453,6 @@ fn main() {
459453
miri_config.collect_leak_backtraces = false;
460454
} else if arg == "-Zmiri-panic-on-unsupported" {
461455
miri_config.panic_on_unsupported = true;
462-
} else if arg == "-Zmiri-tag-raw-pointers" {
463-
eprintln!("WARNING: `-Zmiri-tag-raw-pointers` has no effect; it is enabled by default");
464456
} else if arg == "-Zmiri-strict-provenance" {
465457
miri_config.provenance_mode = ProvenanceMode::Strict;
466458
} else if arg == "-Zmiri-permissive-provenance" {
@@ -476,10 +468,6 @@ fn main() {
476468
"scalar" => RetagFields::OnlyScalar,
477469
_ => show_error!("`-Zmiri-retag-fields` can only be `all`, `none`, or `scalar`"),
478470
};
479-
} else if arg == "-Zmiri-track-raw-pointers" {
480-
eprintln!(
481-
"WARNING: `-Zmiri-track-raw-pointers` has no effect; it is enabled by default"
482-
);
483471
} else if let Some(param) = arg.strip_prefix("-Zmiri-seed=") {
484472
if miri_config.seed.is_some() {
485473
show_error!("Cannot specify -Zmiri-seed multiple times!");

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

+13-5
Original file line numberDiff line numberDiff line change
@@ -445,10 +445,13 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
445445

446446
/// Set an active thread and return the id of the thread that was active before.
447447
fn set_active_thread_id(&mut self, id: ThreadId) -> ThreadId {
448-
let active_thread_id = self.active_thread;
449-
self.active_thread = id;
450-
assert!(self.active_thread.index() < self.threads.len());
451-
active_thread_id
448+
assert!(id.index() < self.threads.len());
449+
info!(
450+
"---------- Now executing on thread `{}` (previous: `{}`) ----------------------------------------",
451+
self.get_thread_display_name(id),
452+
self.get_thread_display_name(self.active_thread)
453+
);
454+
std::mem::replace(&mut self.active_thread, id)
452455
}
453456

454457
/// Get the id of the currently active thread.
@@ -735,6 +738,11 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
735738
for (id, thread) in threads {
736739
debug_assert_ne!(self.active_thread, id);
737740
if thread.state == ThreadState::Enabled {
741+
info!(
742+
"---------- Now executing on thread `{}` (previous: `{}`) ----------------------------------------",
743+
self.get_thread_display_name(id),
744+
self.get_thread_display_name(self.active_thread)
745+
);
738746
self.active_thread = id;
739747
break;
740748
}
@@ -882,7 +890,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
882890
instance,
883891
start_abi,
884892
&[*func_arg],
885-
Some(&ret_place.into()),
893+
Some(&ret_place),
886894
StackPopCleanup::Root { cleanup: true },
887895
)?;
888896

‎src/tools/miri/src/eval.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,6 @@ pub struct MiriConfig {
9494
pub unique_is_unique: bool,
9595
/// Controls alignment checking.
9696
pub check_alignment: AlignmentCheck,
97-
/// Controls function [ABI](Abi) checking.
98-
pub check_abi: bool,
9997
/// Action for an op requiring communication with the host.
10098
pub isolated_op: IsolatedOp,
10199
/// Determines if memory leaks should be ignored.
@@ -162,7 +160,6 @@ impl Default for MiriConfig {
162160
borrow_tracker: Some(BorrowTrackerMethod::StackedBorrows),
163161
unique_is_unique: false,
164162
check_alignment: AlignmentCheck::Int,
165-
check_abi: true,
166163
isolated_op: IsolatedOp::Reject(RejectOpWith::Abort),
167164
ignore_leaks: false,
168165
forwarded_env_vars: vec![],
@@ -394,7 +391,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
394391
argv,
395392
Scalar::from_u8(sigpipe).into(),
396393
],
397-
Some(&ret_place.into()),
394+
Some(&ret_place),
398395
StackPopCleanup::Root { cleanup: true },
399396
)?;
400397
}
@@ -403,7 +400,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
403400
entry_instance,
404401
Abi::Rust,
405402
&[argc.into(), argv],
406-
Some(&ret_place.into()),
403+
Some(&ret_place),
407404
StackPopCleanup::Root { cleanup: true },
408405
)?;
409406
}

‎src/tools/miri/src/helpers.rs

+26-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use std::cmp;
2+
use std::collections::BTreeSet;
23
use std::iter;
34
use std::num::NonZero;
5+
use std::sync::Mutex;
46
use std::time::Duration;
57

68
use rustc_apfloat::ieee::{Double, Single};
@@ -387,7 +389,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
387389
let this = self.eval_context_mut();
388390
let param_env = ty::ParamEnv::reveal_all(); // in Miri this is always the param_env we use... and this.param_env is private.
389391
let callee_abi = f.ty(*this.tcx, param_env).fn_sig(*this.tcx).abi();
390-
if this.machine.enforce_abi && callee_abi != caller_abi {
392+
if callee_abi != caller_abi {
391393
throw_ub_format!(
392394
"calling a function with ABI {} using caller ABI {}",
393395
callee_abi.name(),
@@ -399,7 +401,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
399401
let mir = this.load_mir(f.def, None)?;
400402
let dest = match dest {
401403
Some(dest) => dest.clone(),
402-
None => MPlaceTy::fake_alloc_zst(this.layout_of(mir.return_ty())?).into(),
404+
None => MPlaceTy::fake_alloc_zst(this.layout_of(mir.return_ty())?),
403405
};
404406
this.push_stack_frame(f, mir, &dest, stack_pop)?;
405407

@@ -603,9 +605,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
603605
match reject_with {
604606
RejectOpWith::Abort => isolation_abort_error(op_name),
605607
RejectOpWith::WarningWithoutBacktrace => {
606-
this.tcx
607-
.dcx()
608-
.warn(format!("{op_name} was made to return an error due to isolation"));
608+
// This exists to reduce verbosity; make sure we emit the warning at most once per
609+
// operation.
610+
static EMITTED_WARNINGS: Mutex<BTreeSet<String>> = Mutex::new(BTreeSet::new());
611+
612+
let mut emitted_warnings = EMITTED_WARNINGS.lock().unwrap();
613+
if !emitted_warnings.contains(op_name) {
614+
// First time we are seeing this.
615+
emitted_warnings.insert(op_name.to_owned());
616+
this.tcx
617+
.dcx()
618+
.warn(format!("{op_name} was made to return an error due to isolation"));
619+
}
609620
Ok(())
610621
}
611622
RejectOpWith::Warning => {
@@ -945,7 +956,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
945956

946957
/// Check that the ABI is what we expect.
947958
fn check_abi<'a>(&self, abi: Abi, exp_abi: Abi) -> InterpResult<'a, ()> {
948-
if self.eval_context_ref().machine.enforce_abi && abi != exp_abi {
959+
if abi != exp_abi {
949960
throw_ub_format!(
950961
"calling a function with ABI {} using caller ABI {}",
951962
exp_abi.name(),
@@ -1091,20 +1102,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
10911102
}
10921103
}
10931104

1094-
let (val, status) = match src.layout.ty.kind() {
1095-
// f32
1096-
ty::Float(FloatTy::F32) =>
1105+
let ty::Float(fty) = src.layout.ty.kind() else {
1106+
bug!("float_to_int_checked: non-float input type {}", src.layout.ty)
1107+
};
1108+
1109+
let (val, status) = match fty {
1110+
FloatTy::F16 => unimplemented!("f16_f128"),
1111+
FloatTy::F32 =>
10971112
float_to_int_inner::<Single>(this, src.to_scalar().to_f32()?, cast_to, round),
1098-
// f64
1099-
ty::Float(FloatTy::F64) =>
1113+
FloatTy::F64 =>
11001114
float_to_int_inner::<Double>(this, src.to_scalar().to_f64()?, cast_to, round),
1101-
// Nothing else
1102-
_ =>
1103-
span_bug!(
1104-
this.cur_span(),
1105-
"attempted float-to-int conversion with non-float input type {}",
1106-
src.layout.ty,
1107-
),
1115+
FloatTy::F128 => unimplemented!("f16_f128"),
11081116
};
11091117

11101118
if status.intersects(

‎src/tools/miri/src/lib.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,12 @@
4949
// Needed for rustdoc from bootstrap (with `-Znormalize-docs`).
5050
#![recursion_limit = "256"]
5151

52-
extern crate either; // the one from rustc
52+
// Some "regular" crates we want to share with rustc
53+
extern crate either;
54+
#[macro_use]
55+
extern crate tracing;
5356

57+
// The rustc crates we need
5458
extern crate rustc_apfloat;
5559
extern crate rustc_ast;
5660
extern crate rustc_const_eval;
@@ -63,11 +67,8 @@ extern crate rustc_middle;
6367
extern crate rustc_session;
6468
extern crate rustc_span;
6569
extern crate rustc_target;
66-
#[macro_use]
67-
extern crate tracing;
68-
69-
// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
70-
// files.
70+
// Linking `rustc_driver` pulls in the required object code as the rest of the rustc crates are
71+
// shipped only as rmeta files.
7172
#[allow(unused_extern_crates)]
7273
extern crate rustc_driver;
7374

@@ -143,4 +144,7 @@ pub const MIRI_DEFAULT_ARGS: &[&str] = &[
143144
"-Zmir-keep-place-mention",
144145
"-Zmir-opt-level=0",
145146
"-Zmir-enable-passes=-CheckAlignment",
147+
// Deduplicating diagnostics means we miss events when tracking what happens during an
148+
// execution. Let's not do that.
149+
"-Zdeduplicate-diagnostics=no",
146150
];

‎src/tools/miri/src/machine.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -462,9 +462,6 @@ pub struct MiriMachine<'mir, 'tcx> {
462462
/// Whether to enforce the validity invariant.
463463
pub(crate) validate: bool,
464464

465-
/// Whether to enforce [ABI](Abi) of function calls.
466-
pub(crate) enforce_abi: bool,
467-
468465
/// The table of file descriptors.
469466
pub(crate) file_handler: shims::unix::FileHandler,
470467
/// The table of directory descriptors.
@@ -643,7 +640,6 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
643640
tls: TlsData::default(),
644641
isolated_op: config.isolated_op,
645642
validate: config.validate,
646-
enforce_abi: config.check_abi,
647643
file_handler: FileHandler::new(config.mute_stdout_stderr),
648644
dir_handler: Default::default(),
649645
layouts,
@@ -786,7 +782,6 @@ impl VisitProvenance for MiriMachine<'_, '_> {
786782
tcx: _,
787783
isolated_op: _,
788784
validate: _,
789-
enforce_abi: _,
790785
clock: _,
791786
layouts: _,
792787
static_roots: _,
@@ -934,8 +929,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
934929
}
935930

936931
#[inline(always)]
937-
fn enforce_abi(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
938-
ecx.machine.enforce_abi
932+
fn enforce_abi(_ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
933+
true
939934
}
940935

941936
#[inline(always)]
@@ -1338,7 +1333,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
13381333
// If we have a borrow tracker, we also have it set up protection so that all reads *and
13391334
// writes* during this call are insta-UB.
13401335
let protected_place = if ecx.machine.borrow_tracker.is_some() {
1341-
ecx.protect_place(&place)?.into()
1336+
ecx.protect_place(place)?
13421337
} else {
13431338
// No borrow tracker.
13441339
place.clone()
@@ -1447,13 +1442,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
14471442
if ecx.machine.borrow_tracker.is_some() {
14481443
ecx.on_stack_pop(frame)?;
14491444
}
1445+
// tracing-tree can autoamtically annotate scope changes, but it gets very confused by our
1446+
// concurrency and what it prints is just plain wrong. So we print our own information
1447+
// instead. (Cc https://github.com/rust-lang/miri/issues/2266)
1448+
info!("Leaving {}", ecx.frame().instance);
14501449
Ok(())
14511450
}
14521451

14531452
#[inline(always)]
14541453
fn after_stack_pop(
14551454
ecx: &mut InterpCx<'mir, 'tcx, Self>,
1456-
mut frame: Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>,
1455+
frame: Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>,
14571456
unwinding: bool,
14581457
) -> InterpResult<'tcx, StackPopJump> {
14591458
if frame.extra.is_user_relevant {
@@ -1463,10 +1462,20 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
14631462
// user-relevant frame and restore that here.)
14641463
ecx.active_thread_mut().recompute_top_user_relevant_frame();
14651464
}
1466-
let timing = frame.extra.timing.take();
1467-
let res = ecx.handle_stack_pop_unwind(frame.extra, unwinding);
1468-
if let Some(profiler) = ecx.machine.profiler.as_ref() {
1469-
profiler.finish_recording_interval_event(timing.unwrap());
1465+
let res = {
1466+
// Move `frame`` into a sub-scope so we control when it will be dropped.
1467+
let mut frame = frame;
1468+
let timing = frame.extra.timing.take();
1469+
let res = ecx.handle_stack_pop_unwind(frame.extra, unwinding);
1470+
if let Some(profiler) = ecx.machine.profiler.as_ref() {
1471+
profiler.finish_recording_interval_event(timing.unwrap());
1472+
}
1473+
res
1474+
};
1475+
// Needs to be done after dropping frame to show up on the right nesting level.
1476+
// (Cc https://github.com/rust-lang/miri/issues/2266)
1477+
if !ecx.active_thread_stack().is_empty() {
1478+
info!("Continuing in {}", ecx.frame().instance);
14701479
}
14711480
res
14721481
}

‎src/tools/miri/src/shims/intrinsics/mod.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -287,13 +287,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
287287
_ => bug!(),
288288
};
289289
let float_finite = |x: &ImmTy<'tcx, _>| -> InterpResult<'tcx, bool> {
290-
Ok(match x.layout.ty.kind() {
291-
ty::Float(FloatTy::F32) => x.to_scalar().to_f32()?.is_finite(),
292-
ty::Float(FloatTy::F64) => x.to_scalar().to_f64()?.is_finite(),
293-
_ => bug!(
294-
"`{intrinsic_name}` called with non-float input type {ty:?}",
295-
ty = x.layout.ty,
296-
),
290+
let ty::Float(fty) = x.layout.ty.kind() else {
291+
bug!("float_finite: non-float input type {}", x.layout.ty)
292+
};
293+
Ok(match fty {
294+
FloatTy::F16 => unimplemented!("f16_f128"),
295+
FloatTy::F32 => x.to_scalar().to_f32()?.is_finite(),
296+
FloatTy::F64 => x.to_scalar().to_f64()?.is_finite(),
297+
FloatTy::F128 => unimplemented!("f16_f128"),
297298
})
298299
};
299300
match (float_finite(&a)?, float_finite(&b)?) {

‎src/tools/miri/src/shims/windows/sync.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
179179

180180
let id = this.init_once_get_id(init_once_op)?;
181181
let flags = this.read_scalar(flags_op)?.to_u32()?;
182-
let pending_place = this.deref_pointer(pending_op)?.into();
182+
let pending_place = this.deref_pointer(pending_op)?;
183183
let context = this.read_pointer(context_op)?;
184184

185185
if flags != 0 {

‎src/tools/miri/test_dependencies/Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change

‎src/tools/miri/tests/fail-dep/concurrency/unwind_top_of_stack.rs

-29
This file was deleted.

‎src/tools/miri/tests/fail-dep/concurrency/unwind_top_of_stack.stderr

-21
This file was deleted.

‎src/tools/miri/tests/fail/const-ub-checks.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ note: erroneous constant encountered
1010
LL | let _x = UNALIGNED_READ;
1111
| ^^^^^^^^^^^^^^
1212

13+
note: erroneous constant encountered
14+
--> $DIR/const-ub-checks.rs:LL:CC
15+
|
16+
LL | let _x = UNALIGNED_READ;
17+
| ^^^^^^^^^^^^^^
18+
|
19+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
20+
1321
error: aborting due to 1 previous error
1422

1523
For more information about this error, try `rustc --explain E0080`.

‎src/tools/miri/tests/fail/erroneous_const2.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ note: erroneous constant encountered
1010
LL | println!("{}", FOO);
1111
| ^^^
1212

13+
note: erroneous constant encountered
14+
--> $DIR/erroneous_const2.rs:LL:CC
15+
|
16+
LL | println!("{}", FOO);
17+
| ^^^
18+
|
19+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
20+
1321
note: erroneous constant encountered
1422
--> $DIR/erroneous_const2.rs:LL:CC
1523
|

‎src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs

-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ fn main() {
1919
after_call = {
2020
Return()
2121
}
22-
2322
}
2423
}
2524

‎src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ LL | | let _unit: ();
1414
LL | | {
1515
LL | | let non_copy = S(42);
1616
... |
17-
LL | |
17+
LL | | }
1818
LL | | }
1919
| |_____^
2020
help: <TAG> is this argument

‎src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ LL | | let _unit: ();
1616
LL | | {
1717
LL | | let non_copy = S(42);
1818
... |
19-
LL | |
19+
LL | | }
2020
LL | | }
2121
| |_____^
2222
help: the protected tag <TAG> was created here, in the initial state Reserved

‎src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
//@compile-flags: -Zmiri-disable-abi-check
21
#![feature(c_unwind)]
32

43
#[no_mangle]

‎src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed.
2-
If you have a use-case for it, please file an issue.
31
thread 'main' panicked at $DIR/exported_symbol_bad_unwind1.rs:LL:CC:
42
explicit panic
53
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

‎src/tools/miri/tests/fail/panic/bad_miri_start_unwind.rs

-12
This file was deleted.

‎src/tools/miri/tests/fail/panic/bad_miri_start_unwind.stderr

-17
This file was deleted.

‎src/tools/miri/tests/fail/panic/bad_unwind.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#![feature(c_unwind)]
22

33
//! Unwinding when the caller ABI is "C" (without "-unwind") is UB.
4+
// The opposite version (callee does not allow unwinding) is impossible to
5+
// even write: MIR validation catches functions that have `UnwindContinue` but
6+
// are not allowed to unwind.
47

58
extern "C-unwind" fn unwind() {
69
panic!();

‎src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs

+1
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ fn wait_wake_bitset() {
219219
t.join().unwrap();
220220
}
221221

222+
// Crucial test which relies on the SeqCst fences in futex wait/wake.
222223
fn concurrent_wait_wake() {
223224
const FREE: i32 = 0;
224225
const HELD: i32 = 1;

‎src/tools/miri/tests/pass/concurrency/sync.rs

+17-10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ use std::sync::{Arc, Barrier, Condvar, Mutex, Once, RwLock};
77
use std::thread;
88
use std::time::{Duration, Instant};
99

10+
// We are expecting to sleep for 10ms. How long of a sleep we are accepting?
11+
// Even with 1000ms we still see this test fail on macOS runners.
12+
const MAX_SLEEP_TIME_MS: u64 = 2000;
13+
1014
// Check if Rust barriers are working.
1115

1216
/// This test is taken from the Rust documentation.
@@ -66,7 +70,7 @@ fn check_conditional_variables_timed_wait_timeout() {
6670
let (_guard, timeout) = cvar.wait_timeout(guard, Duration::from_millis(10)).unwrap();
6771
assert!(timeout.timed_out());
6872
let elapsed_time = now.elapsed().as_millis();
69-
assert!(10 <= elapsed_time && elapsed_time <= 1000);
73+
assert!(10 <= elapsed_time && elapsed_time <= MAX_SLEEP_TIME_MS.into());
7074
}
7175

7276
/// Test that signaling a conditional variable when waiting with a timeout works
@@ -84,7 +88,8 @@ fn check_conditional_variables_timed_wait_notimeout() {
8488
cvar.notify_one();
8589
});
8690

87-
let (_guard, timeout) = cvar.wait_timeout(guard, Duration::from_millis(1000)).unwrap();
91+
let (_guard, timeout) =
92+
cvar.wait_timeout(guard, Duration::from_millis(MAX_SLEEP_TIME_MS)).unwrap();
8893
assert!(!timeout.timed_out());
8994
handle.join().unwrap();
9095
}
@@ -213,20 +218,21 @@ fn check_once() {
213218
fn park_timeout() {
214219
let start = Instant::now();
215220

216-
thread::park_timeout(Duration::from_millis(200));
221+
thread::park_timeout(Duration::from_millis(10));
217222
// Normally, waiting in park/park_timeout may spuriously wake up early, but we
218223
// know Miri's timed synchronization primitives do not do that.
219-
// We allow much longer sleeps as well since the macOS GHA runners seem very oversubscribed
220-
// and sometimes just pause for 1 second or more.
221224
let elapsed = start.elapsed();
222-
assert!((200..2000).contains(&elapsed.as_millis()), "bad sleep time: {elapsed:?}");
225+
assert!(
226+
(10..MAX_SLEEP_TIME_MS.into()).contains(&elapsed.as_millis()),
227+
"bad sleep time: {elapsed:?}"
228+
);
223229
}
224230

225231
fn park_unpark() {
226232
let t1 = thread::current();
227233
let t2 = thread::spawn(move || {
228234
thread::park();
229-
thread::sleep(Duration::from_millis(200));
235+
thread::sleep(Duration::from_millis(10));
230236
t1.unpark();
231237
});
232238

@@ -236,10 +242,11 @@ fn park_unpark() {
236242
thread::park();
237243
// Normally, waiting in park/park_timeout may spuriously wake up early, but we
238244
// know Miri's timed synchronization primitives do not do that.
239-
// We allow much longer sleeps as well since the macOS GHA runners seem very oversubscribed
240-
// and sometimes just pause for 1 second or more.
241245
let elapsed = start.elapsed();
242-
assert!((200..2000).contains(&elapsed.as_millis()), "bad sleep time: {elapsed:?}");
246+
assert!(
247+
(10..MAX_SLEEP_TIME_MS.into()).contains(&elapsed.as_millis()),
248+
"bad sleep time: {elapsed:?}"
249+
);
243250

244251
t2.join().unwrap();
245252
}

‎src/tools/miri/tests/pass/function_calls/disable_abi_check.rs

-24
This file was deleted.

‎src/tools/miri/tests/pass/function_calls/disable_abi_check.stderr

-2
This file was deleted.

‎src/tools/miri/tests/pass/shims/fs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ fn test_canonicalize() {
295295
drop(File::create(&path).unwrap());
296296

297297
let p = canonicalize(format!("{}/./test_file", dir_path.to_string_lossy())).unwrap();
298-
assert_eq!(p.to_string_lossy().find('.'), None);
298+
assert_eq!(p.to_string_lossy().find("/./"), None);
299299

300300
remove_dir_all(&dir_path).unwrap();
301301
}

‎src/tools/miri/tests/compiletest.rs ‎src/tools/miri/tests/ui.rs

+29-14
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,6 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
7979
program.args.push(flag);
8080
}
8181

82-
// Add a test env var to do environment communication tests.
83-
program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into())));
84-
85-
// Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
86-
let miri_temp = env::var_os("MIRI_TEMP").unwrap_or_else(|| env::temp_dir().into());
87-
program.envs.push(("MIRI_TEMP".into(), Some(miri_temp)));
88-
8982
let mut config = Config {
9083
target: Some(target.to_owned()),
9184
stderr_filters: STDERR.clone(),
@@ -116,9 +109,21 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
116109
config
117110
}
118111

119-
fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> Result<()> {
112+
fn run_tests(
113+
mode: Mode,
114+
path: &str,
115+
target: &str,
116+
with_dependencies: bool,
117+
tmpdir: &Path,
118+
) -> Result<()> {
120119
let mut config = test_config(target, path, mode, with_dependencies);
121120

121+
// Add a test env var to do environment communication tests.
122+
config.program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into())));
123+
124+
// Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
125+
config.program.envs.push(("MIRI_TEMP".into(), Some(tmpdir.to_owned().into())));
126+
122127
// Handle command-line arguments.
123128
let args = ui_test::Args::test()?;
124129
let default_bless = env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
@@ -211,15 +216,21 @@ enum Dependencies {
211216

212217
use Dependencies::*;
213218

214-
fn ui(mode: Mode, path: &str, target: &str, with_dependencies: Dependencies) -> Result<()> {
219+
fn ui(
220+
mode: Mode,
221+
path: &str,
222+
target: &str,
223+
with_dependencies: Dependencies,
224+
tmpdir: &Path,
225+
) -> Result<()> {
215226
let msg = format!("## Running ui tests in {path} against miri for {target}");
216227
eprintln!("{}", msg.green().bold());
217228

218229
let with_dependencies = match with_dependencies {
219230
WithDependencies => true,
220231
WithoutDependencies => false,
221232
};
222-
run_tests(mode, path, target, with_dependencies)
233+
run_tests(mode, path, target, with_dependencies, tmpdir)
223234
}
224235

225236
fn get_target() -> String {
@@ -230,6 +241,7 @@ fn main() -> Result<()> {
230241
ui_test::color_eyre::install()?;
231242

232243
let target = get_target();
244+
let tmpdir = tempfile::Builder::new().prefix("miri-uitest-").tempdir()?;
233245

234246
let mut args = std::env::args_os();
235247

@@ -240,28 +252,31 @@ fn main() -> Result<()> {
240252
}
241253
}
242254

243-
ui(Mode::Pass, "tests/pass", &target, WithoutDependencies)?;
244-
ui(Mode::Pass, "tests/pass-dep", &target, WithDependencies)?;
245-
ui(Mode::Panic, "tests/panic", &target, WithDependencies)?;
255+
ui(Mode::Pass, "tests/pass", &target, WithoutDependencies, tmpdir.path())?;
256+
ui(Mode::Pass, "tests/pass-dep", &target, WithDependencies, tmpdir.path())?;
257+
ui(Mode::Panic, "tests/panic", &target, WithDependencies, tmpdir.path())?;
246258
ui(
247259
Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled },
248260
"tests/fail",
249261
&target,
250262
WithoutDependencies,
263+
tmpdir.path(),
251264
)?;
252265
ui(
253266
Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled },
254267
"tests/fail-dep",
255268
&target,
256269
WithDependencies,
270+
tmpdir.path(),
257271
)?;
258272
if cfg!(target_os = "linux") {
259-
ui(Mode::Pass, "tests/extern-so/pass", &target, WithoutDependencies)?;
273+
ui(Mode::Pass, "tests/extern-so/pass", &target, WithoutDependencies, tmpdir.path())?;
260274
ui(
261275
Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled },
262276
"tests/extern-so/fail",
263277
&target,
264278
WithoutDependencies,
279+
tmpdir.path(),
265280
)?;
266281
}
267282

0 commit comments

Comments
 (0)
Please sign in to comment.