Skip to content

Commit

Permalink
Auto merge of #124026 - matthiaskrgr:rollup-an6s6gq, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 10 pull requests

Successful merges:

 - #122632 (fetch submodule before checking llvm stamp)
 - #123355 (Support type '/' to search)
 - #123501 (Stabilize checking of cfgs at compile-time: `--check-cfg` option)
 - #123535 (Match ergonomics 2024: `mut` doesn't reset binding mode)
 - #123711 (drop `changelog-seen`)
 - #123969 (The new solver ignores `DefineOpaqueTypes`, so switch it to `Yes`)
 - #124007 (Miri subtree update)
 - #124017 (Change a diagnostics-path-only `DefineOpaqueTypes` to `Yes`.)
 - #124018 (interpret: pass MemoryKind to before_memory_deallocation)
 - #124024 (interpret: remove outdated comment)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Apr 16, 2024
2 parents c17e292 + 1430604 commit 10b6685
Show file tree
Hide file tree
Showing 22 changed files with 364 additions and 161 deletions.
38 changes: 17 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -451,36 +451,32 @@ Some native rustc `-Z` flags are also very relevant for Miri:
* `-Zmir-emit-retag` controls whether `Retag` statements are emitted. Miri
enables this per default because it is needed for [Stacked Borrows] and [Tree Borrows].

Moreover, Miri recognizes some environment variables:
Moreover, Miri recognizes some environment variables (unless noted otherwise, these are supported
by all intended entry points, i.e. `cargo miri` and `./miri {test,run}`):

* `MIRI_AUTO_OPS` indicates whether the automatic execution of rustfmt, clippy and toolchain setup
should be skipped. If it is set to `no`, they are skipped. This is used to allow automated IDE
actions to avoid the auto ops.
* `MIRI_LOG`, `MIRI_BACKTRACE` control logging and backtrace printing during
Miri executions, also [see "Testing the Miri driver" in `CONTRIBUTING.md`][testing-miri].
* `MIRIFLAGS` (recognized by `cargo miri` and the test suite) defines extra
flags to be passed to Miri.
* `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.
* `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
`--sysroot` flag) is mandatory. When invoking `cargo miri setup`, this indicates where the sysroot
will be put.
* `MIRI_TEST_TARGET` (recognized by the test suite and the `./miri` script) indicates which target
* `MIRIFLAGS` defines extra flags to be passed to Miri.
* `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.
* `MIRI_SYSROOT` 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. When invoking
`cargo miri setup`, this indicates where the sysroot will be put.
* `MIRI_TEST_TARGET` (recognized by `./miri {test,run}`) indicates which target
architecture to test against. `miri` and `cargo miri` accept the `--target` flag for the same
purpose.
* `MIRI_TEST_THREADS` (recognized by the test suite): set the number of threads to use for running tests.
By default the number of cores is used.
* `MIRI_NO_STD` (recognized by `cargo miri`) makes sure that the target's sysroot is built without
libstd. This allows testing and running no_std programs.
(Miri has a heuristic to detect no-std targets based on the target name; this environment variable
is only needed when that heuristic fails.)
* `RUSTC_BLESS` (recognized by the test suite and `cargo-miri-test/run-test.py`): overwrite all
* `MIRI_TEST_THREADS` (recognized by `./miri test`): set the number of threads to use for running tests.
By default, the number of cores is used.
* `MIRI_NO_STD` makes sure that the target's sysroot is built without libstd. This allows testing
and running no_std programs. (Miri has a heuristic to detect no-std targets based on the target
name; this environment variable is only needed when that heuristic fails.)
* `RUSTC_BLESS` (recognized by `./miri test` and `cargo-miri-test/run-test.py`): overwrite all
`stderr` and `stdout` files instead of checking whether the output matches.
* `MIRI_SKIP_UI_CHECKS` (recognized by the test suite): don't check whether the
* `MIRI_SKIP_UI_CHECKS` (recognized by `./miri test`): don't check whether the
`stderr` or `stdout` files match the actual output.

The following environment variables are *internal* and must not be used by
Expand Down
4 changes: 2 additions & 2 deletions cargo-miri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cargo-miri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ directories = "5"
rustc_version = "0.4"
serde_json = "1.0.40"
cargo_metadata = "0.18.0"
rustc-build-sysroot = "0.4.1"
rustc-build-sysroot = "0.4.6"

# Enable some feature flags that dev-dependencies need but dependencies
# do not. This makes `./miri install` after `./miri build` faster.
Expand Down
26 changes: 19 additions & 7 deletions cargo-miri/src/phases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,6 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
// Forward all further arguments (not consumed by `ArgSplitFlagValue`) to cargo.
cmd.args(args);

// Let it know where the Miri sysroot lives.
cmd.env("MIRI_SYSROOT", miri_sysroot);
// Set `RUSTC_WRAPPER` to ourselves. Cargo will prepend that binary to its usual invocation,
// i.e., the first argument is `rustc` -- which is what we use in `main` to distinguish
// the two codepaths. (That extra argument is why we prefer this over setting `RUSTC`.)
Expand All @@ -200,10 +198,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
// always applied. However, buggy build scripts (https://github.com/eyre-rs/eyre/issues/84) and
// also cargo (https://github.com/rust-lang/cargo/issues/10885) will invoke `rustc` even when
// `RUSTC_WRAPPER` is set, bypassing the wrapper. To make sure everything is coherent, we want
// that to be the Miri driver, but acting as rustc, on the target level. (Target, rather than
// host, is needed for cross-interpretation situations.) This is not a perfect emulation of real
// rustc (it might be unable to produce binaries since the sysroot is check-only), but it's as
// close as we can get, and it's good enough for autocfg.
// that to be the Miri driver, but acting as rustc, in host mode.
//
// In `main`, we need the value of `RUSTC` to distinguish RUSTC_WRAPPER invocations from rustdoc
// or TARGET_RUNNER invocations, so we canonicalize it here to make it exceedingly unlikely that
Expand All @@ -212,14 +207,19 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
// bootstrap `rustc` thing in our way! Instead, we have MIRI_HOST_SYSROOT to use for host
// builds.
cmd.env("RUSTC", fs::canonicalize(find_miri()).unwrap());
cmd.env("MIRI_BE_RUSTC", "target"); // we better remember to *unset* this in the other phases!
// In case we get invoked as RUSTC without the wrapper, let's be a host rustc. This makes no
// sense for cross-interpretation situations, but without the wrapper, this will use the host
// sysroot, so asking it to behave like a target build makes even less sense.
cmd.env("MIRI_BE_RUSTC", "host"); // we better remember to *unset* this in the other phases!

// Set rustdoc to us as well, so we can run doctests.
if let Some(orig_rustdoc) = env::var_os("RUSTDOC") {
cmd.env("MIRI_ORIG_RUSTDOC", orig_rustdoc);
}
cmd.env("RUSTDOC", &cargo_miri_path);

// Forward some crucial information to our own re-invocations.
cmd.env("MIRI_SYSROOT", miri_sysroot);
cmd.env("MIRI_LOCAL_CRATES", local_crates(&metadata));
if verbose > 0 {
cmd.env("MIRI_VERBOSE", verbose.to_string()); // This makes the other phases verbose.
Expand Down Expand Up @@ -412,6 +412,12 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
// Arguments are treated very differently depending on whether this crate is
// for interpretation by Miri, or for use by a build script / proc macro.
if target_crate {
if phase != RustcPhase::Setup {
// Set the sysroot -- except during setup, where we don't have an existing sysroot yet
// and where the bootstrap wrapper adds its own `--sysroot` flag so we can't set ours.
cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
}

// Forward arguments, but patched.
let emit_flag = "--emit";
// This hack helps bootstrap run standard library tests in Miri. The issue is as follows:
Expand Down Expand Up @@ -574,6 +580,12 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
cmd.env(name, val);
}

if phase != RunnerPhase::Rustdoc {
// Set the sysroot. Not necessary in rustdoc, where we already set the sysroot in
// `phase_rustdoc`. rustdoc will forward that flag when invoking rustc (i.e., us), so the
// flag is present in `info.args`.
cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
}
// Forward rustc arguments.
// We need to patch "--extern" filenames because we forced a check-only
// build without cargo knowing about that: replace `.rlib` suffix by
Expand Down
18 changes: 11 additions & 7 deletions miri-script/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::env;
use std::ffi::OsString;
use std::io::Write;
use std::ops::Not;
use std::path::PathBuf;
use std::process;
use std::thread;
use std::time;
Expand All @@ -20,10 +21,11 @@ const JOSH_FILTER: &str =
const JOSH_PORT: &str = "42042";

impl MiriEnv {
fn build_miri_sysroot(&mut self, quiet: bool) -> Result<()> {
if self.sh.var("MIRI_SYSROOT").is_ok() {
/// Returns the location of the sysroot.
fn build_miri_sysroot(&mut self, quiet: bool) -> Result<PathBuf> {
if let Some(miri_sysroot) = self.sh.var_os("MIRI_SYSROOT") {
// Sysroot already set, use that.
return Ok(());
return Ok(miri_sysroot.into());
}
let manifest_path = path!(self.miri_dir / "cargo-miri" / "Cargo.toml");
let Self { toolchain, cargo_extra_flags, .. } = &self;
Expand Down Expand Up @@ -57,8 +59,8 @@ impl MiriEnv {
.with_context(|| "`cargo miri setup` failed")?;
panic!("`cargo miri setup` didn't fail again the 2nd time?");
};
self.sh.set_var("MIRI_SYSROOT", output);
Ok(())
self.sh.set_var("MIRI_SYSROOT", &output);
Ok(output.into())
}
}
Expand Down Expand Up @@ -505,8 +507,10 @@ impl Command {
flags.push("--edition=2021".into()); // keep in sync with `tests/ui.rs`.`
}

// Prepare a sysroot.
e.build_miri_sysroot(/* quiet */ true)?;
// Prepare a sysroot, and add it to the flags.
let miri_sysroot = e.build_miri_sysroot(/* quiet */ true)?;
flags.push("--sysroot".into());
flags.push(miri_sysroot.into());

// Then run the actual command. Also add MIRIFLAGS.
let miri_manifest = path!(e.miri_dir / "Cargo.toml");
Expand Down
19 changes: 0 additions & 19 deletions src/bin/miri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,25 +282,6 @@ fn run_compiler(
callbacks: &mut (dyn rustc_driver::Callbacks + Send),
using_internal_features: std::sync::Arc<std::sync::atomic::AtomicBool>,
) -> ! {
if target_crate {
// Miri needs a custom sysroot for target crates.
// If no `--sysroot` is given, the `MIRI_SYSROOT` env var is consulted to find where
// that sysroot lives, and that is passed to rustc.
let sysroot_flag = "--sysroot";
if !args.iter().any(|e| e.starts_with(sysroot_flag)) {
// Using the built-in default here would be plain wrong, so we *require*
// the env var to make sure things make sense.
let miri_sysroot = env::var("MIRI_SYSROOT").unwrap_or_else(|_| {
show_error!(
"Miri was invoked in 'target' mode without `MIRI_SYSROOT` or `--sysroot` being set"
)
});

args.push(sysroot_flag.to_owned());
args.push(miri_sysroot);
}
}

// Don't insert `MIRI_DEFAULT_ARGS`, in particular, `--cfg=miri`, if we are building
// a "host" crate. That may cause procedural macros (and probably build scripts) to
// depend on Miri-only symbols, such as `miri_resolve_frame`:
Expand Down
2 changes: 1 addition & 1 deletion src/borrow_tracker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ impl GlobalStateInner {
&mut self,
id: AllocId,
alloc_size: Size,
kind: MemoryKind<machine::MiriMemoryKind>,
kind: MemoryKind,
machine: &MiriMachine<'_, '_>,
) -> AllocState {
match self.borrow_tracker_method {
Expand Down
2 changes: 1 addition & 1 deletion src/borrow_tracker/stacked_borrows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ impl Stacks {
id: AllocId,
size: Size,
state: &mut GlobalStateInner,
kind: MemoryKind<MiriMemoryKind>,
kind: MemoryKind,
machine: &MiriMachine<'_, '_>,
) -> Self {
let (base_tag, perm) = match kind {
Expand Down
2 changes: 1 addition & 1 deletion src/borrow_tracker/tree_borrows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl<'tcx> Tree {
id: AllocId,
size: Size,
state: &mut GlobalStateInner,
_kind: MemoryKind<machine::MiriMemoryKind>,
_kind: MemoryKind,
machine: &MiriMachine<'_, 'tcx>,
) -> Self {
let tag = state.base_ptr_tag(id, machine); // Fresh tag for the root
Expand Down
2 changes: 1 addition & 1 deletion src/concurrency/data_race.rs
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ impl VClockAlloc {
global: &GlobalState,
thread_mgr: &ThreadManager<'_, '_>,
len: Size,
kind: MemoryKind<MiriMemoryKind>,
kind: MemoryKind,
current_span: Span,
) -> VClockAlloc {
let (alloc_timestamp, alloc_index) = match kind {
Expand Down
4 changes: 2 additions & 2 deletions src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ pub enum NonHaltingDiagnostic {
/// This `Item` was popped from the borrow stack. The string explains the reason.
PoppedPointerTag(Item, String),
CreatedCallId(CallId),
CreatedAlloc(AllocId, Size, Align, MemoryKind<MiriMemoryKind>),
CreatedAlloc(AllocId, Size, Align, MemoryKind),
FreedAlloc(AllocId),
AccessedAlloc(AllocId, AccessKind),
RejectedIsolatedOp(String),
Expand Down Expand Up @@ -414,7 +414,7 @@ pub fn report_error<'tcx, 'mir>(

pub fn report_leaks<'mir, 'tcx>(
ecx: &InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
leaks: Vec<(AllocId, MemoryKind<MiriMemoryKind>, Allocation<Provenance, AllocExtra<'tcx>>)>,
leaks: Vec<(AllocId, MemoryKind, Allocation<Provenance, AllocExtra<'tcx>>)>,
) {
let mut any_pruned = false;
for (id, kind, mut alloc) in leaks {
Expand Down
56 changes: 40 additions & 16 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
("EAGAIN", WouldBlock),
]
};
// This mapping should match `decode_error_kind` in
// <https://github.com/rust-lang/rust/blob/master/library/std/src/sys/pal/windows/mod.rs>.
const WINDOWS_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
use std::io::ErrorKind::*;
// FIXME: this is still incomplete.
&[
("ERROR_ACCESS_DENIED", PermissionDenied),
("ERROR_FILE_NOT_FOUND", NotFound),
("ERROR_INVALID_PARAMETER", InvalidInput),
]
};

/// Gets an instance for a path.
///
Expand Down Expand Up @@ -749,20 +760,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}
throw_unsup_format!("io error {:?} cannot be translated into a raw os error", err_kind)
} else if target.families.iter().any(|f| f == "windows") {
// FIXME: we have to finish implementing the Windows equivalent of this.
use std::io::ErrorKind::*;
Ok(this.eval_windows(
"c",
match err_kind {
NotFound => "ERROR_FILE_NOT_FOUND",
PermissionDenied => "ERROR_ACCESS_DENIED",
_ =>
throw_unsup_format!(
"io error {:?} cannot be translated into a raw os error",
err_kind
),
},
))
for &(name, kind) in WINDOWS_IO_ERROR_TABLE {
if err_kind == kind {
return Ok(this.eval_windows("c", name));
}
}
throw_unsup_format!("io error {:?} cannot be translated into a raw os error", err_kind);
} else {
throw_unsup_format!(
"converting io::Error into errnum is unsupported for OS {}",
Expand All @@ -786,8 +789,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
return Ok(Some(kind));
}
}
// Our table is as complete as the mapping in std, so we are okay with saying "that's a
// strange one" here.
return Ok(None);
} else if target.families.iter().any(|f| f == "windows") {
let errnum = errnum.to_u32()?;
for &(name, kind) in WINDOWS_IO_ERROR_TABLE {
if errnum == this.eval_windows("c", name).to_u32()? {
return Ok(Some(kind));
}
}
return Ok(None);
} else {
throw_unsup_format!(
Expand Down Expand Up @@ -1344,3 +1353,18 @@ pub(crate) fn simd_element_to_bool(elem: ImmTy<'_, Provenance>) -> InterpResult<
_ => throw_ub_format!("each element of a SIMD mask must be all-0-bits or all-1-bits"),
})
}

/// Check whether an operation that writes to a target buffer was successful.
/// Accordingly select return value.
/// Local helper function to be used in Windows shims.
pub(crate) fn windows_check_buffer_size((success, len): (bool, u64)) -> u32 {
if success {
// If the function succeeds, the return value is the number of characters stored in the target buffer,
// not including the terminating null character.
u32::try_from(len.checked_sub(1).unwrap()).unwrap()
} else {
// If the target buffer was not large enough to hold the data, the return value is the buffer size, in characters,
// required to hold the string and its terminating null character.
u32::try_from(len).unwrap()
}
}
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#![feature(let_chains)]
#![feature(lint_reasons)]
#![feature(trait_upcasting)]
#![feature(absolute_path)]
// Configure clippy and other lints
#![allow(
clippy::collapsible_else_if,
Expand Down Expand Up @@ -125,7 +126,7 @@ pub use crate::eval::{
};
pub use crate::helpers::{AccessKind, EvalContextExt as _};
pub use crate::machine::{
AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
AllocExtra, FrameExtra, MemoryKind, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
PrimitiveLayouts, Provenance, ProvenanceExtra,
};
pub use crate::mono_hash_map::MonoHashMap;
Expand Down
Loading

0 comments on commit 10b6685

Please sign in to comment.