mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #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.
This commit is contained in:
commit
3521a2f2f3
@ -2485,6 +2485,7 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc_version",
|
||||
"smallvec",
|
||||
"tempfile",
|
||||
"ui_test 0.21.2",
|
||||
]
|
||||
|
||||
|
2
src/tools/miri/.github/workflows/ci.yml
vendored
2
src/tools/miri/.github/workflows/ci.yml
vendored
@ -187,7 +187,7 @@ jobs:
|
||||
run: RUSTFLAGS="--cap-lints warn" cargo +stable install josh-proxy --git https://github.com/josh-project/josh --tag r22.12.06
|
||||
- name: setup bot git name and email
|
||||
run: |
|
||||
git config --global user.name 'The Miri Conjob Bot'
|
||||
git config --global user.name 'The Miri Cronjob Bot'
|
||||
git config --global user.email 'miri@cron.bot'
|
||||
- name: get changes from rustc
|
||||
run: ./miri rustc-pull
|
||||
|
@ -497,6 +497,7 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc_version",
|
||||
"smallvec",
|
||||
"tempfile",
|
||||
"ui_test",
|
||||
]
|
||||
|
||||
|
@ -45,6 +45,7 @@ ui_test = "0.21.1"
|
||||
rustc_version = "0.4"
|
||||
regex = "1.5.5"
|
||||
lazy_static = "1.4.0"
|
||||
tempfile = "3"
|
||||
|
||||
[package.metadata.rust-analyzer]
|
||||
# This crate uses #[feature(rustc_private)].
|
||||
@ -52,7 +53,7 @@ lazy_static = "1.4.0"
|
||||
rustc_private = true
|
||||
|
||||
[[test]]
|
||||
name = "compiletest"
|
||||
name = "ui"
|
||||
harness = false
|
||||
|
||||
[features]
|
||||
|
@ -318,8 +318,8 @@ environment variable. We first document the most relevant and most commonly used
|
||||
and `warn-nobacktrace` are the supported actions. The default is to `abort`,
|
||||
which halts the machine. Some (but not all) operations also support continuing
|
||||
execution with a "permission denied" error being returned to the program.
|
||||
`warn` prints a full backtrace when that happens; `warn-nobacktrace` is less
|
||||
verbose. `hide` hides the warning entirely.
|
||||
`warn` prints a full backtrace each time that happens; `warn-nobacktrace` is less
|
||||
verbose and shown at most once per operation. `hide` hides the warning entirely.
|
||||
* `-Zmiri-num-cpus` states the number of available CPUs to be reported by miri. By default, the
|
||||
number of available CPUs is `1`. Note that this flag does not affect how miri handles threads in
|
||||
any way.
|
||||
@ -359,8 +359,6 @@ The remaining flags are for advanced use only, and more likely to change or be r
|
||||
Some of these are **unsound**, which means they can lead
|
||||
to Miri failing to detect cases of undefined behavior in a program.
|
||||
|
||||
* `-Zmiri-disable-abi-check` disables checking [function ABI]. Using this flag
|
||||
is **unsound**. This flag is **deprecated**.
|
||||
* `-Zmiri-disable-alignment-check` disables checking pointer alignment, so you
|
||||
can focus on other failures, but it means Miri can miss bugs in your program.
|
||||
Using this flag is **unsound**.
|
||||
@ -465,11 +463,7 @@ Moreover, Miri recognizes some environment variables:
|
||||
* `MIRI_LIB_SRC` defines the directory where Miri expects the sources of the
|
||||
standard library that it will build and use for interpretation. This directory
|
||||
must point to the `library` subdirectory of a `rust-lang/rust` repository
|
||||
checkout. Note that changing files in that directory does not automatically
|
||||
trigger a re-build of the standard library; you have to clear the Miri build
|
||||
cache with `cargo miri clean` or deleting it manually (on Linux, `rm -rf ~/.cache/miri`;
|
||||
on Windows, `rmdir /S "%LOCALAPPDATA%\rust-lang\miri\cache"`;
|
||||
and on macOS, `rm -rf ~/Library/Caches/org.rust-lang.miri`).
|
||||
checkout.
|
||||
* `MIRI_SYSROOT` (recognized by `cargo miri` and the Miri driver) indicates the sysroot to use. When
|
||||
using `cargo miri`, this skips the automatic setup -- only set this if you do not want to use the
|
||||
automatically created sysroot. For directly invoking the Miri driver, this variable (or a
|
||||
|
@ -12,7 +12,7 @@ PLATFORM_SUPPORT_FILE=$(rustc +miri --print sysroot)/share/doc/rust/html/rustc/p
|
||||
|
||||
for target in $(python3 ci/scrape-targets.py $PLATFORM_SUPPORT_FILE); do
|
||||
# Wipe the cache before every build to minimize disk usage
|
||||
rm -rf ~/.cache/miri
|
||||
cargo +miri miri clean
|
||||
if cargo +miri miri setup --target $target 2>&1 | tee failures/$target; then
|
||||
# If the build succeeds, delete its output. If we have output, a build failed.
|
||||
rm $FAILS_DIR/$target
|
||||
|
@ -510,11 +510,11 @@ impl Command {
|
||||
let miri_flags = flagsplit(&miri_flags);
|
||||
let toolchain = &e.toolchain;
|
||||
let extra_flags = &e.cargo_extra_flags;
|
||||
let edition_flags = (!have_edition).then_some("--edition=2021"); // keep in sync with `compiletest.rs`.`
|
||||
let edition_flags = (!have_edition).then_some("--edition=2021"); // keep in sync with `tests/ui.rs`.`
|
||||
if dep {
|
||||
cmd!(
|
||||
e.sh,
|
||||
"cargo +{toolchain} --quiet test --test compiletest {extra_flags...} --manifest-path {miri_manifest} -- --miri-run-dep-mode {miri_flags...} {edition_flags...} {flags...}"
|
||||
"cargo +{toolchain} --quiet test {extra_flags...} --manifest-path {miri_manifest} --test ui -- --miri-run-dep-mode {miri_flags...} {edition_flags...} {flags...}"
|
||||
).quiet().run()?;
|
||||
} else {
|
||||
cmd!(
|
||||
@ -526,37 +526,27 @@ impl Command {
|
||||
}
|
||||
|
||||
fn fmt(flags: Vec<OsString>) -> Result<()> {
|
||||
use itertools::Itertools;
|
||||
|
||||
let e = MiriEnv::new()?;
|
||||
let toolchain = &e.toolchain;
|
||||
let config_path = path!(e.miri_dir / "rustfmt.toml");
|
||||
|
||||
let mut cmd = cmd!(
|
||||
e.sh,
|
||||
"rustfmt +{toolchain} --edition=2021 --config-path {config_path} --unstable-features --skip-children {flags...}"
|
||||
);
|
||||
eprintln!("$ {cmd} ...");
|
||||
// Collect each rust file in the miri repo.
|
||||
let files = WalkDir::new(&e.miri_dir)
|
||||
.into_iter()
|
||||
.filter_entry(|entry| {
|
||||
let name = entry.file_name().to_string_lossy();
|
||||
let ty = entry.file_type();
|
||||
if ty.is_file() {
|
||||
name.ends_with(".rs")
|
||||
} else {
|
||||
// dir or symlink. skip `target` and `.git`.
|
||||
&name != "target" && &name != ".git"
|
||||
}
|
||||
})
|
||||
.filter_ok(|item| item.file_type().is_file())
|
||||
.map_ok(|item| item.into_path());
|
||||
|
||||
// Add all the filenames to the command.
|
||||
// FIXME: `rustfmt` will follow the `mod` statements in these files, so we get a bunch of
|
||||
// duplicate diffs.
|
||||
for item in WalkDir::new(&e.miri_dir).into_iter().filter_entry(|entry| {
|
||||
let name = entry.file_name().to_string_lossy();
|
||||
let ty = entry.file_type();
|
||||
if ty.is_file() {
|
||||
name.ends_with(".rs")
|
||||
} else {
|
||||
// dir or symlink. skip `target` and `.git`.
|
||||
&name != "target" && &name != ".git"
|
||||
}
|
||||
}) {
|
||||
let item = item?;
|
||||
if item.file_type().is_file() {
|
||||
cmd = cmd.arg(item.into_path());
|
||||
}
|
||||
}
|
||||
|
||||
// We want our own error message, repeating the command is too much.
|
||||
cmd.quiet().run().map_err(|_| anyhow!("`rustfmt` failed"))?;
|
||||
Ok(())
|
||||
e.format_files(files, &e.toolchain[..], &config_path, &flags[..])
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use dunce::canonicalize;
|
||||
use path_macro::path;
|
||||
use xshell::{cmd, Shell};
|
||||
@ -145,4 +145,48 @@ impl MiriEnv {
|
||||
.run()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Receives an iterator of files.
|
||||
/// Will format each file with the miri rustfmt config.
|
||||
/// Does not recursively format modules.
|
||||
pub fn format_files(
|
||||
&self,
|
||||
files: impl Iterator<Item = Result<PathBuf, walkdir::Error>>,
|
||||
toolchain: &str,
|
||||
config_path: &Path,
|
||||
flags: &[OsString],
|
||||
) -> anyhow::Result<()> {
|
||||
use itertools::Itertools;
|
||||
|
||||
let mut first = true;
|
||||
|
||||
// Format in batches as not all our files fit into Windows' command argument limit.
|
||||
for batch in &files.chunks(256) {
|
||||
// Build base command.
|
||||
let mut cmd = cmd!(
|
||||
self.sh,
|
||||
"rustfmt +{toolchain} --edition=2021 --config-path {config_path} --unstable-features --skip-children {flags...}"
|
||||
);
|
||||
if first {
|
||||
// Log an abbreviating command, and only once.
|
||||
eprintln!("$ {cmd} ...");
|
||||
first = false;
|
||||
}
|
||||
// Add files.
|
||||
for file in batch {
|
||||
// Make it a relative path so that on platforms with extremely tight argument
|
||||
// limits (like Windows), we become immune to someone cloning the repo
|
||||
// 50 directories deep.
|
||||
let file = file?;
|
||||
let file = file.strip_prefix(&self.miri_dir)?;
|
||||
cmd = cmd.arg(file);
|
||||
}
|
||||
|
||||
// Run rustfmt.
|
||||
// We want our own error message, repeating the command is too much.
|
||||
cmd.quiet().run().map_err(|_| anyhow!("`rustfmt` failed"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
1a1876c9790f168fb51afa335a7ba3e6fc267d75
|
||||
4d4bb491b65c300835442f6cb4f34fc9a5685c26
|
||||
|
@ -8,6 +8,11 @@
|
||||
rustc::untranslatable_diagnostic
|
||||
)]
|
||||
|
||||
// Some "regular" crates we want to share with rustc
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
// The rustc crates we need
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_hir;
|
||||
@ -16,8 +21,6 @@ extern crate rustc_log;
|
||||
extern crate rustc_metadata;
|
||||
extern crate rustc_middle;
|
||||
extern crate rustc_session;
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
use std::env::{self, VarError};
|
||||
use std::num::NonZero;
|
||||
@ -202,16 +205,12 @@ fn rustc_logger_config() -> rustc_log::LoggerConfig {
|
||||
// rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_const_eval::interpret=debug`.
|
||||
if tracing::Level::from_str(&var).is_ok() {
|
||||
cfg.filter = Ok(format!(
|
||||
"rustc_middle::mir::interpret={var},rustc_const_eval::interpret={var}"
|
||||
"rustc_middle::mir::interpret={var},rustc_const_eval::interpret={var},miri={var}"
|
||||
));
|
||||
} else {
|
||||
cfg.filter = Ok(var);
|
||||
}
|
||||
}
|
||||
// Enable verbose entry/exit logging by default if MIRI_LOG is set.
|
||||
if matches!(cfg.verbose_entry_exit, Err(VarError::NotPresent)) {
|
||||
cfg.verbose_entry_exit = Ok(format!("1"));
|
||||
}
|
||||
}
|
||||
|
||||
cfg
|
||||
@ -342,7 +341,8 @@ fn main() {
|
||||
// (`install_ice_hook` might change `RUST_BACKTRACE`.)
|
||||
let env_snapshot = env::vars_os().collect::<Vec<_>>();
|
||||
|
||||
let args = rustc_driver::args::raw_args(&early_dcx).unwrap_or_else(|_| std::process::exit(rustc_driver::EXIT_FAILURE));
|
||||
let args = rustc_driver::args::raw_args(&early_dcx)
|
||||
.unwrap_or_else(|_| std::process::exit(rustc_driver::EXIT_FAILURE));
|
||||
|
||||
// If the environment asks us to actually be rustc, then do that.
|
||||
if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") {
|
||||
@ -408,17 +408,11 @@ fn main() {
|
||||
miri_config.check_alignment = miri::AlignmentCheck::None;
|
||||
} else if arg == "-Zmiri-symbolic-alignment-check" {
|
||||
miri_config.check_alignment = miri::AlignmentCheck::Symbolic;
|
||||
} else if arg == "-Zmiri-check-number-validity" {
|
||||
eprintln!(
|
||||
"WARNING: the flag `-Zmiri-check-number-validity` no longer has any effect \
|
||||
since it is now enabled by default"
|
||||
);
|
||||
} else if arg == "-Zmiri-disable-abi-check" {
|
||||
eprintln!(
|
||||
"WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed.\n\
|
||||
If you have a use-case for it, please file an issue."
|
||||
"WARNING: the flag `-Zmiri-disable-abi-check` no longer has any effect; \
|
||||
ABI checks cannot be disabled any more"
|
||||
);
|
||||
miri_config.check_abi = false;
|
||||
} else if arg == "-Zmiri-disable-isolation" {
|
||||
if matches!(isolation_enabled, Some(true)) {
|
||||
show_error!(
|
||||
@ -459,8 +453,6 @@ fn main() {
|
||||
miri_config.collect_leak_backtraces = false;
|
||||
} else if arg == "-Zmiri-panic-on-unsupported" {
|
||||
miri_config.panic_on_unsupported = true;
|
||||
} else if arg == "-Zmiri-tag-raw-pointers" {
|
||||
eprintln!("WARNING: `-Zmiri-tag-raw-pointers` has no effect; it is enabled by default");
|
||||
} else if arg == "-Zmiri-strict-provenance" {
|
||||
miri_config.provenance_mode = ProvenanceMode::Strict;
|
||||
} else if arg == "-Zmiri-permissive-provenance" {
|
||||
@ -476,10 +468,6 @@ fn main() {
|
||||
"scalar" => RetagFields::OnlyScalar,
|
||||
_ => show_error!("`-Zmiri-retag-fields` can only be `all`, `none`, or `scalar`"),
|
||||
};
|
||||
} else if arg == "-Zmiri-track-raw-pointers" {
|
||||
eprintln!(
|
||||
"WARNING: `-Zmiri-track-raw-pointers` has no effect; it is enabled by default"
|
||||
);
|
||||
} else if let Some(param) = arg.strip_prefix("-Zmiri-seed=") {
|
||||
if miri_config.seed.is_some() {
|
||||
show_error!("Cannot specify -Zmiri-seed multiple times!");
|
||||
|
@ -445,10 +445,13 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
|
||||
|
||||
/// Set an active thread and return the id of the thread that was active before.
|
||||
fn set_active_thread_id(&mut self, id: ThreadId) -> ThreadId {
|
||||
let active_thread_id = self.active_thread;
|
||||
self.active_thread = id;
|
||||
assert!(self.active_thread.index() < self.threads.len());
|
||||
active_thread_id
|
||||
assert!(id.index() < self.threads.len());
|
||||
info!(
|
||||
"---------- Now executing on thread `{}` (previous: `{}`) ----------------------------------------",
|
||||
self.get_thread_display_name(id),
|
||||
self.get_thread_display_name(self.active_thread)
|
||||
);
|
||||
std::mem::replace(&mut self.active_thread, id)
|
||||
}
|
||||
|
||||
/// Get the id of the currently active thread.
|
||||
@ -735,6 +738,11 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
|
||||
for (id, thread) in threads {
|
||||
debug_assert_ne!(self.active_thread, id);
|
||||
if thread.state == ThreadState::Enabled {
|
||||
info!(
|
||||
"---------- Now executing on thread `{}` (previous: `{}`) ----------------------------------------",
|
||||
self.get_thread_display_name(id),
|
||||
self.get_thread_display_name(self.active_thread)
|
||||
);
|
||||
self.active_thread = id;
|
||||
break;
|
||||
}
|
||||
@ -882,7 +890,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
instance,
|
||||
start_abi,
|
||||
&[*func_arg],
|
||||
Some(&ret_place.into()),
|
||||
Some(&ret_place),
|
||||
StackPopCleanup::Root { cleanup: true },
|
||||
)?;
|
||||
|
||||
|
@ -94,8 +94,6 @@ pub struct MiriConfig {
|
||||
pub unique_is_unique: bool,
|
||||
/// Controls alignment checking.
|
||||
pub check_alignment: AlignmentCheck,
|
||||
/// Controls function [ABI](Abi) checking.
|
||||
pub check_abi: bool,
|
||||
/// Action for an op requiring communication with the host.
|
||||
pub isolated_op: IsolatedOp,
|
||||
/// Determines if memory leaks should be ignored.
|
||||
@ -162,7 +160,6 @@ impl Default for MiriConfig {
|
||||
borrow_tracker: Some(BorrowTrackerMethod::StackedBorrows),
|
||||
unique_is_unique: false,
|
||||
check_alignment: AlignmentCheck::Int,
|
||||
check_abi: true,
|
||||
isolated_op: IsolatedOp::Reject(RejectOpWith::Abort),
|
||||
ignore_leaks: false,
|
||||
forwarded_env_vars: vec![],
|
||||
@ -394,7 +391,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
|
||||
argv,
|
||||
Scalar::from_u8(sigpipe).into(),
|
||||
],
|
||||
Some(&ret_place.into()),
|
||||
Some(&ret_place),
|
||||
StackPopCleanup::Root { cleanup: true },
|
||||
)?;
|
||||
}
|
||||
@ -403,7 +400,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
|
||||
entry_instance,
|
||||
Abi::Rust,
|
||||
&[argc.into(), argv],
|
||||
Some(&ret_place.into()),
|
||||
Some(&ret_place),
|
||||
StackPopCleanup::Root { cleanup: true },
|
||||
)?;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use std::cmp;
|
||||
use std::collections::BTreeSet;
|
||||
use std::iter;
|
||||
use std::num::NonZero;
|
||||
use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
@ -387,7 +389,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let param_env = ty::ParamEnv::reveal_all(); // in Miri this is always the param_env we use... and this.param_env is private.
|
||||
let callee_abi = f.ty(*this.tcx, param_env).fn_sig(*this.tcx).abi();
|
||||
if this.machine.enforce_abi && callee_abi != caller_abi {
|
||||
if callee_abi != caller_abi {
|
||||
throw_ub_format!(
|
||||
"calling a function with ABI {} using caller ABI {}",
|
||||
callee_abi.name(),
|
||||
@ -399,7 +401,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let mir = this.load_mir(f.def, None)?;
|
||||
let dest = match dest {
|
||||
Some(dest) => dest.clone(),
|
||||
None => MPlaceTy::fake_alloc_zst(this.layout_of(mir.return_ty())?).into(),
|
||||
None => MPlaceTy::fake_alloc_zst(this.layout_of(mir.return_ty())?),
|
||||
};
|
||||
this.push_stack_frame(f, mir, &dest, stack_pop)?;
|
||||
|
||||
@ -603,9 +605,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
match reject_with {
|
||||
RejectOpWith::Abort => isolation_abort_error(op_name),
|
||||
RejectOpWith::WarningWithoutBacktrace => {
|
||||
this.tcx
|
||||
.dcx()
|
||||
.warn(format!("{op_name} was made to return an error due to isolation"));
|
||||
// This exists to reduce verbosity; make sure we emit the warning at most once per
|
||||
// operation.
|
||||
static EMITTED_WARNINGS: Mutex<BTreeSet<String>> = Mutex::new(BTreeSet::new());
|
||||
|
||||
let mut emitted_warnings = EMITTED_WARNINGS.lock().unwrap();
|
||||
if !emitted_warnings.contains(op_name) {
|
||||
// First time we are seeing this.
|
||||
emitted_warnings.insert(op_name.to_owned());
|
||||
this.tcx
|
||||
.dcx()
|
||||
.warn(format!("{op_name} was made to return an error due to isolation"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
RejectOpWith::Warning => {
|
||||
@ -945,7 +956,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
|
||||
/// Check that the ABI is what we expect.
|
||||
fn check_abi<'a>(&self, abi: Abi, exp_abi: Abi) -> InterpResult<'a, ()> {
|
||||
if self.eval_context_ref().machine.enforce_abi && abi != exp_abi {
|
||||
if abi != exp_abi {
|
||||
throw_ub_format!(
|
||||
"calling a function with ABI {} using caller ABI {}",
|
||||
exp_abi.name(),
|
||||
@ -1091,20 +1102,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let (val, status) = match src.layout.ty.kind() {
|
||||
// f32
|
||||
ty::Float(FloatTy::F32) =>
|
||||
let ty::Float(fty) = src.layout.ty.kind() else {
|
||||
bug!("float_to_int_checked: non-float input type {}", src.layout.ty)
|
||||
};
|
||||
|
||||
let (val, status) = match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F32 =>
|
||||
float_to_int_inner::<Single>(this, src.to_scalar().to_f32()?, cast_to, round),
|
||||
// f64
|
||||
ty::Float(FloatTy::F64) =>
|
||||
FloatTy::F64 =>
|
||||
float_to_int_inner::<Double>(this, src.to_scalar().to_f64()?, cast_to, round),
|
||||
// Nothing else
|
||||
_ =>
|
||||
span_bug!(
|
||||
this.cur_span(),
|
||||
"attempted float-to-int conversion with non-float input type {}",
|
||||
src.layout.ty,
|
||||
),
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
};
|
||||
|
||||
if status.intersects(
|
||||
|
@ -49,8 +49,12 @@
|
||||
// Needed for rustdoc from bootstrap (with `-Znormalize-docs`).
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
extern crate either; // the one from rustc
|
||||
// Some "regular" crates we want to share with rustc
|
||||
extern crate either;
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
// The rustc crates we need
|
||||
extern crate rustc_apfloat;
|
||||
extern crate rustc_ast;
|
||||
extern crate rustc_const_eval;
|
||||
@ -63,11 +67,8 @@ extern crate rustc_middle;
|
||||
extern crate rustc_session;
|
||||
extern crate rustc_span;
|
||||
extern crate rustc_target;
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
|
||||
// files.
|
||||
// Linking `rustc_driver` pulls in the required object code as the rest of the rustc crates are
|
||||
// shipped only as rmeta files.
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate rustc_driver;
|
||||
|
||||
@ -143,4 +144,7 @@ pub const MIRI_DEFAULT_ARGS: &[&str] = &[
|
||||
"-Zmir-keep-place-mention",
|
||||
"-Zmir-opt-level=0",
|
||||
"-Zmir-enable-passes=-CheckAlignment",
|
||||
// Deduplicating diagnostics means we miss events when tracking what happens during an
|
||||
// execution. Let's not do that.
|
||||
"-Zdeduplicate-diagnostics=no",
|
||||
];
|
||||
|
@ -462,9 +462,6 @@ pub struct MiriMachine<'mir, 'tcx> {
|
||||
/// Whether to enforce the validity invariant.
|
||||
pub(crate) validate: bool,
|
||||
|
||||
/// Whether to enforce [ABI](Abi) of function calls.
|
||||
pub(crate) enforce_abi: bool,
|
||||
|
||||
/// The table of file descriptors.
|
||||
pub(crate) file_handler: shims::unix::FileHandler,
|
||||
/// The table of directory descriptors.
|
||||
@ -643,7 +640,6 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
||||
tls: TlsData::default(),
|
||||
isolated_op: config.isolated_op,
|
||||
validate: config.validate,
|
||||
enforce_abi: config.check_abi,
|
||||
file_handler: FileHandler::new(config.mute_stdout_stderr),
|
||||
dir_handler: Default::default(),
|
||||
layouts,
|
||||
@ -786,7 +782,6 @@ impl VisitProvenance for MiriMachine<'_, '_> {
|
||||
tcx: _,
|
||||
isolated_op: _,
|
||||
validate: _,
|
||||
enforce_abi: _,
|
||||
clock: _,
|
||||
layouts: _,
|
||||
static_roots: _,
|
||||
@ -934,8 +929,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn enforce_abi(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
|
||||
ecx.machine.enforce_abi
|
||||
fn enforce_abi(_ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -1338,7 +1333,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
||||
// If we have a borrow tracker, we also have it set up protection so that all reads *and
|
||||
// writes* during this call are insta-UB.
|
||||
let protected_place = if ecx.machine.borrow_tracker.is_some() {
|
||||
ecx.protect_place(&place)?.into()
|
||||
ecx.protect_place(place)?
|
||||
} else {
|
||||
// No borrow tracker.
|
||||
place.clone()
|
||||
@ -1447,13 +1442,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
||||
if ecx.machine.borrow_tracker.is_some() {
|
||||
ecx.on_stack_pop(frame)?;
|
||||
}
|
||||
// tracing-tree can autoamtically annotate scope changes, but it gets very confused by our
|
||||
// concurrency and what it prints is just plain wrong. So we print our own information
|
||||
// instead. (Cc https://github.com/rust-lang/miri/issues/2266)
|
||||
info!("Leaving {}", ecx.frame().instance);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn after_stack_pop(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
mut frame: Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>,
|
||||
frame: Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>,
|
||||
unwinding: bool,
|
||||
) -> InterpResult<'tcx, StackPopJump> {
|
||||
if frame.extra.is_user_relevant {
|
||||
@ -1463,10 +1462,20 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
||||
// user-relevant frame and restore that here.)
|
||||
ecx.active_thread_mut().recompute_top_user_relevant_frame();
|
||||
}
|
||||
let timing = frame.extra.timing.take();
|
||||
let res = ecx.handle_stack_pop_unwind(frame.extra, unwinding);
|
||||
if let Some(profiler) = ecx.machine.profiler.as_ref() {
|
||||
profiler.finish_recording_interval_event(timing.unwrap());
|
||||
let res = {
|
||||
// Move `frame`` into a sub-scope so we control when it will be dropped.
|
||||
let mut frame = frame;
|
||||
let timing = frame.extra.timing.take();
|
||||
let res = ecx.handle_stack_pop_unwind(frame.extra, unwinding);
|
||||
if let Some(profiler) = ecx.machine.profiler.as_ref() {
|
||||
profiler.finish_recording_interval_event(timing.unwrap());
|
||||
}
|
||||
res
|
||||
};
|
||||
// Needs to be done after dropping frame to show up on the right nesting level.
|
||||
// (Cc https://github.com/rust-lang/miri/issues/2266)
|
||||
if !ecx.active_thread_stack().is_empty() {
|
||||
info!("Continuing in {}", ecx.frame().instance);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
@ -287,13 +287,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
_ => bug!(),
|
||||
};
|
||||
let float_finite = |x: &ImmTy<'tcx, _>| -> InterpResult<'tcx, bool> {
|
||||
Ok(match x.layout.ty.kind() {
|
||||
ty::Float(FloatTy::F32) => x.to_scalar().to_f32()?.is_finite(),
|
||||
ty::Float(FloatTy::F64) => x.to_scalar().to_f64()?.is_finite(),
|
||||
_ => bug!(
|
||||
"`{intrinsic_name}` called with non-float input type {ty:?}",
|
||||
ty = x.layout.ty,
|
||||
),
|
||||
let ty::Float(fty) = x.layout.ty.kind() else {
|
||||
bug!("float_finite: non-float input type {}", x.layout.ty)
|
||||
};
|
||||
Ok(match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F32 => x.to_scalar().to_f32()?.is_finite(),
|
||||
FloatTy::F64 => x.to_scalar().to_f64()?.is_finite(),
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
})
|
||||
};
|
||||
match (float_finite(&a)?, float_finite(&b)?) {
|
||||
|
@ -179,7 +179,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
|
||||
let id = this.init_once_get_id(init_once_op)?;
|
||||
let flags = this.read_scalar(flags_op)?.to_u32()?;
|
||||
let pending_place = this.deref_pointer(pending_op)?.into();
|
||||
let pending_place = this.deref_pointer(pending_op)?;
|
||||
let context = this.read_pointer(context_op)?;
|
||||
|
||||
if flags != 0 {
|
||||
|
@ -183,9 +183,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.10"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
|
||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
|
@ -1,29 +0,0 @@
|
||||
//@ignore-target-windows: No libc on Windows
|
||||
|
||||
//@compile-flags: -Zmiri-disable-abi-check
|
||||
|
||||
//! Unwinding past the top frame of a stack is Undefined Behavior.
|
||||
|
||||
#![feature(c_unwind)]
|
||||
|
||||
use std::{mem, ptr};
|
||||
|
||||
extern "C-unwind" fn thread_start(_null: *mut libc::c_void) -> *mut libc::c_void {
|
||||
//~^ ERROR: unwinding past the topmost frame of the stack
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let mut native: libc::pthread_t = mem::zeroed();
|
||||
let attr: libc::pthread_attr_t = mem::zeroed();
|
||||
// assert_eq!(libc::pthread_attr_init(&mut attr), 0); FIXME: this function is not yet implemented.
|
||||
// Cast to avoid inserting abort-on-unwind.
|
||||
let thread_start: extern "C-unwind" fn(*mut libc::c_void) -> *mut libc::c_void =
|
||||
thread_start;
|
||||
let thread_start: extern "C" fn(*mut libc::c_void) -> *mut libc::c_void =
|
||||
mem::transmute(thread_start);
|
||||
assert_eq!(libc::pthread_create(&mut native, &attr, thread_start, ptr::null_mut()), 0);
|
||||
assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0);
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed.
|
||||
If you have a use-case for it, please file an issue.
|
||||
thread '<unnamed>' panicked at $DIR/unwind_top_of_stack.rs:LL:CC:
|
||||
explicit panic
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
error: Undefined Behavior: unwinding past the topmost frame of the stack
|
||||
--> $DIR/unwind_top_of_stack.rs:LL:CC
|
||||
|
|
||||
LL | / extern "C-unwind" fn thread_start(_null: *mut libc::c_void) -> *mut libc::c_void {
|
||||
LL | |
|
||||
LL | | panic!()
|
||||
LL | | }
|
||||
| |_^ unwinding past the topmost frame of the stack
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE on thread `unnamed-ID`:
|
||||
= note: inside `thread_start` at $DIR/unwind_top_of_stack.rs:LL:CC
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -10,6 +10,14 @@ note: erroneous constant encountered
|
||||
LL | let _x = UNALIGNED_READ;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/const-ub-checks.rs:LL:CC
|
||||
|
|
||||
LL | let _x = UNALIGNED_READ;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
@ -10,6 +10,14 @@ note: erroneous constant encountered
|
||||
LL | println!("{}", FOO);
|
||||
| ^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/erroneous_const2.rs:LL:CC
|
||||
|
|
||||
LL | println!("{}", FOO);
|
||||
| ^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/erroneous_const2.rs:LL:CC
|
||||
|
|
||||
|
@ -19,7 +19,6 @@ fn main() {
|
||||
after_call = {
|
||||
Return()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ LL | | let _unit: ();
|
||||
LL | | {
|
||||
LL | | let non_copy = S(42);
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_____^
|
||||
help: <TAG> is this argument
|
||||
|
@ -16,7 +16,7 @@ LL | | let _unit: ();
|
||||
LL | | {
|
||||
LL | | let non_copy = S(42);
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_____^
|
||||
help: the protected tag <TAG> was created here, in the initial state Reserved
|
||||
|
@ -1,4 +1,3 @@
|
||||
//@compile-flags: -Zmiri-disable-abi-check
|
||||
#![feature(c_unwind)]
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -1,5 +1,3 @@
|
||||
WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed.
|
||||
If you have a use-case for it, please file an issue.
|
||||
thread 'main' panicked at $DIR/exported_symbol_bad_unwind1.rs:LL:CC:
|
||||
explicit panic
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
|
@ -1,12 +0,0 @@
|
||||
//@compile-flags: -Zmiri-disable-abi-check
|
||||
// This feature is required to trigger the error using the "C" ABI.
|
||||
#![feature(c_unwind)]
|
||||
|
||||
extern "C" {
|
||||
fn miri_start_unwind(payload: *mut u8) -> !;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe { miri_start_unwind(&mut 0) }
|
||||
//~^ ERROR: unwinding past a stack frame that does not allow unwinding
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed.
|
||||
If you have a use-case for it, please file an issue.
|
||||
error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding
|
||||
--> $DIR/bad_miri_start_unwind.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { miri_start_unwind(&mut 0) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unwinding past a stack frame that does not allow unwinding
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at $DIR/bad_miri_start_unwind.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -1,6 +1,9 @@
|
||||
#![feature(c_unwind)]
|
||||
|
||||
//! Unwinding when the caller ABI is "C" (without "-unwind") is UB.
|
||||
// The opposite version (callee does not allow unwinding) is impossible to
|
||||
// even write: MIR validation catches functions that have `UnwindContinue` but
|
||||
// are not allowed to unwind.
|
||||
|
||||
extern "C-unwind" fn unwind() {
|
||||
panic!();
|
||||
|
@ -219,6 +219,7 @@ fn wait_wake_bitset() {
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
// Crucial test which relies on the SeqCst fences in futex wait/wake.
|
||||
fn concurrent_wait_wake() {
|
||||
const FREE: i32 = 0;
|
||||
const HELD: i32 = 1;
|
||||
|
@ -7,6 +7,10 @@ use std::sync::{Arc, Barrier, Condvar, Mutex, Once, RwLock};
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
// We are expecting to sleep for 10ms. How long of a sleep we are accepting?
|
||||
// Even with 1000ms we still see this test fail on macOS runners.
|
||||
const MAX_SLEEP_TIME_MS: u64 = 2000;
|
||||
|
||||
// Check if Rust barriers are working.
|
||||
|
||||
/// This test is taken from the Rust documentation.
|
||||
@ -66,7 +70,7 @@ fn check_conditional_variables_timed_wait_timeout() {
|
||||
let (_guard, timeout) = cvar.wait_timeout(guard, Duration::from_millis(10)).unwrap();
|
||||
assert!(timeout.timed_out());
|
||||
let elapsed_time = now.elapsed().as_millis();
|
||||
assert!(10 <= elapsed_time && elapsed_time <= 1000);
|
||||
assert!(10 <= elapsed_time && elapsed_time <= MAX_SLEEP_TIME_MS.into());
|
||||
}
|
||||
|
||||
/// Test that signaling a conditional variable when waiting with a timeout works
|
||||
@ -84,7 +88,8 @@ fn check_conditional_variables_timed_wait_notimeout() {
|
||||
cvar.notify_one();
|
||||
});
|
||||
|
||||
let (_guard, timeout) = cvar.wait_timeout(guard, Duration::from_millis(1000)).unwrap();
|
||||
let (_guard, timeout) =
|
||||
cvar.wait_timeout(guard, Duration::from_millis(MAX_SLEEP_TIME_MS)).unwrap();
|
||||
assert!(!timeout.timed_out());
|
||||
handle.join().unwrap();
|
||||
}
|
||||
@ -213,20 +218,21 @@ fn check_once() {
|
||||
fn park_timeout() {
|
||||
let start = Instant::now();
|
||||
|
||||
thread::park_timeout(Duration::from_millis(200));
|
||||
thread::park_timeout(Duration::from_millis(10));
|
||||
// Normally, waiting in park/park_timeout may spuriously wake up early, but we
|
||||
// know Miri's timed synchronization primitives do not do that.
|
||||
// We allow much longer sleeps as well since the macOS GHA runners seem very oversubscribed
|
||||
// and sometimes just pause for 1 second or more.
|
||||
let elapsed = start.elapsed();
|
||||
assert!((200..2000).contains(&elapsed.as_millis()), "bad sleep time: {elapsed:?}");
|
||||
assert!(
|
||||
(10..MAX_SLEEP_TIME_MS.into()).contains(&elapsed.as_millis()),
|
||||
"bad sleep time: {elapsed:?}"
|
||||
);
|
||||
}
|
||||
|
||||
fn park_unpark() {
|
||||
let t1 = thread::current();
|
||||
let t2 = thread::spawn(move || {
|
||||
thread::park();
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
thread::sleep(Duration::from_millis(10));
|
||||
t1.unpark();
|
||||
});
|
||||
|
||||
@ -236,10 +242,11 @@ fn park_unpark() {
|
||||
thread::park();
|
||||
// Normally, waiting in park/park_timeout may spuriously wake up early, but we
|
||||
// know Miri's timed synchronization primitives do not do that.
|
||||
// We allow much longer sleeps as well since the macOS GHA runners seem very oversubscribed
|
||||
// and sometimes just pause for 1 second or more.
|
||||
let elapsed = start.elapsed();
|
||||
assert!((200..2000).contains(&elapsed.as_millis()), "bad sleep time: {elapsed:?}");
|
||||
assert!(
|
||||
(10..MAX_SLEEP_TIME_MS.into()).contains(&elapsed.as_millis()),
|
||||
"bad sleep time: {elapsed:?}"
|
||||
);
|
||||
|
||||
t2.join().unwrap();
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
//@compile-flags: -Zmiri-disable-abi-check
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
fn main() {
|
||||
fn foo() {}
|
||||
|
||||
extern "C" fn try_fn(ptr: *mut u8) {
|
||||
assert!(ptr.is_null());
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
fn malloc(size: usize) -> *mut std::ffi::c_void;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let _ = malloc(0);
|
||||
std::mem::transmute::<fn(), extern "C" fn()>(foo)();
|
||||
std::intrinsics::catch_unwind(
|
||||
std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
|
||||
std::ptr::null_mut(),
|
||||
|_, _| unreachable!(),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed.
|
||||
If you have a use-case for it, please file an issue.
|
@ -295,7 +295,7 @@ fn test_canonicalize() {
|
||||
drop(File::create(&path).unwrap());
|
||||
|
||||
let p = canonicalize(format!("{}/./test_file", dir_path.to_string_lossy())).unwrap();
|
||||
assert_eq!(p.to_string_lossy().find('.'), None);
|
||||
assert_eq!(p.to_string_lossy().find("/./"), None);
|
||||
|
||||
remove_dir_all(&dir_path).unwrap();
|
||||
}
|
||||
|
@ -79,13 +79,6 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
|
||||
program.args.push(flag);
|
||||
}
|
||||
|
||||
// Add a test env var to do environment communication tests.
|
||||
program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into())));
|
||||
|
||||
// Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
|
||||
let miri_temp = env::var_os("MIRI_TEMP").unwrap_or_else(|| env::temp_dir().into());
|
||||
program.envs.push(("MIRI_TEMP".into(), Some(miri_temp)));
|
||||
|
||||
let mut config = Config {
|
||||
target: Some(target.to_owned()),
|
||||
stderr_filters: STDERR.clone(),
|
||||
@ -116,9 +109,21 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
|
||||
config
|
||||
}
|
||||
|
||||
fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> Result<()> {
|
||||
fn run_tests(
|
||||
mode: Mode,
|
||||
path: &str,
|
||||
target: &str,
|
||||
with_dependencies: bool,
|
||||
tmpdir: &Path,
|
||||
) -> Result<()> {
|
||||
let mut config = test_config(target, path, mode, with_dependencies);
|
||||
|
||||
// Add a test env var to do environment communication tests.
|
||||
config.program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into())));
|
||||
|
||||
// Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
|
||||
config.program.envs.push(("MIRI_TEMP".into(), Some(tmpdir.to_owned().into())));
|
||||
|
||||
// Handle command-line arguments.
|
||||
let args = ui_test::Args::test()?;
|
||||
let default_bless = env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
|
||||
@ -211,7 +216,13 @@ enum Dependencies {
|
||||
|
||||
use Dependencies::*;
|
||||
|
||||
fn ui(mode: Mode, path: &str, target: &str, with_dependencies: Dependencies) -> Result<()> {
|
||||
fn ui(
|
||||
mode: Mode,
|
||||
path: &str,
|
||||
target: &str,
|
||||
with_dependencies: Dependencies,
|
||||
tmpdir: &Path,
|
||||
) -> Result<()> {
|
||||
let msg = format!("## Running ui tests in {path} against miri for {target}");
|
||||
eprintln!("{}", msg.green().bold());
|
||||
|
||||
@ -219,7 +230,7 @@ fn ui(mode: Mode, path: &str, target: &str, with_dependencies: Dependencies) ->
|
||||
WithDependencies => true,
|
||||
WithoutDependencies => false,
|
||||
};
|
||||
run_tests(mode, path, target, with_dependencies)
|
||||
run_tests(mode, path, target, with_dependencies, tmpdir)
|
||||
}
|
||||
|
||||
fn get_target() -> String {
|
||||
@ -230,6 +241,7 @@ fn main() -> Result<()> {
|
||||
ui_test::color_eyre::install()?;
|
||||
|
||||
let target = get_target();
|
||||
let tmpdir = tempfile::Builder::new().prefix("miri-uitest-").tempdir()?;
|
||||
|
||||
let mut args = std::env::args_os();
|
||||
|
||||
@ -240,28 +252,31 @@ fn main() -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
ui(Mode::Pass, "tests/pass", &target, WithoutDependencies)?;
|
||||
ui(Mode::Pass, "tests/pass-dep", &target, WithDependencies)?;
|
||||
ui(Mode::Panic, "tests/panic", &target, WithDependencies)?;
|
||||
ui(Mode::Pass, "tests/pass", &target, WithoutDependencies, tmpdir.path())?;
|
||||
ui(Mode::Pass, "tests/pass-dep", &target, WithDependencies, tmpdir.path())?;
|
||||
ui(Mode::Panic, "tests/panic", &target, WithDependencies, tmpdir.path())?;
|
||||
ui(
|
||||
Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled },
|
||||
"tests/fail",
|
||||
&target,
|
||||
WithoutDependencies,
|
||||
tmpdir.path(),
|
||||
)?;
|
||||
ui(
|
||||
Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled },
|
||||
"tests/fail-dep",
|
||||
&target,
|
||||
WithDependencies,
|
||||
tmpdir.path(),
|
||||
)?;
|
||||
if cfg!(target_os = "linux") {
|
||||
ui(Mode::Pass, "tests/extern-so/pass", &target, WithoutDependencies)?;
|
||||
ui(Mode::Pass, "tests/extern-so/pass", &target, WithoutDependencies, tmpdir.path())?;
|
||||
ui(
|
||||
Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled },
|
||||
"tests/extern-so/fail",
|
||||
&target,
|
||||
WithoutDependencies,
|
||||
tmpdir.path(),
|
||||
)?;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user