Skip to content

Commit 813e43c

Browse files
authored
Unrolled build for rust-lang#124007
Rollup merge of rust-lang#124007 - RalfJung:miri, r=RalfJung Miri subtree update r? ``@ghost``
2 parents 1dea922 + 876ac7b commit 813e43c

File tree

17 files changed

+347
-145
lines changed

17 files changed

+347
-145
lines changed

Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -3364,9 +3364,9 @@ dependencies = [
33643364

33653365
[[package]]
33663366
name = "rustc-build-sysroot"
3367-
version = "0.4.5"
3367+
version = "0.4.6"
33683368
source = "registry+https://github.com/rust-lang/crates.io-index"
3369-
checksum = "a26170e1d79ea32f7ccec3188dd13cfc1f18c82764a9cbc1071667c0f865a4ea"
3369+
checksum = "a9bf37423495cd3a6a9ef8c75fc4566de0d26de0ab75f36f67a426e58df5768c"
33703370
dependencies = [
33713371
"anyhow",
33723372
"rustc_version",

src/tools/miri/README.md

+17-21
Original file line numberDiff line numberDiff line change
@@ -451,36 +451,32 @@ Some native rustc `-Z` flags are also very relevant for Miri:
451451
* `-Zmir-emit-retag` controls whether `Retag` statements are emitted. Miri
452452
enables this per default because it is needed for [Stacked Borrows] and [Tree Borrows].
453453

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

456457
* `MIRI_AUTO_OPS` indicates whether the automatic execution of rustfmt, clippy and toolchain setup
457458
should be skipped. If it is set to `no`, they are skipped. This is used to allow automated IDE
458459
actions to avoid the auto ops.
459460
* `MIRI_LOG`, `MIRI_BACKTRACE` control logging and backtrace printing during
460461
Miri executions, also [see "Testing the Miri driver" in `CONTRIBUTING.md`][testing-miri].
461-
* `MIRIFLAGS` (recognized by `cargo miri` and the test suite) defines extra
462-
flags to be passed to Miri.
463-
* `MIRI_LIB_SRC` defines the directory where Miri expects the sources of the
464-
standard library that it will build and use for interpretation. This directory
465-
must point to the `library` subdirectory of a `rust-lang/rust` repository
466-
checkout.
467-
* `MIRI_SYSROOT` (recognized by `cargo miri` and the Miri driver) indicates the sysroot to use. When
468-
using `cargo miri`, this skips the automatic setup -- only set this if you do not want to use the
469-
automatically created sysroot. For directly invoking the Miri driver, this variable (or a
470-
`--sysroot` flag) is mandatory. When invoking `cargo miri setup`, this indicates where the sysroot
471-
will be put.
472-
* `MIRI_TEST_TARGET` (recognized by the test suite and the `./miri` script) indicates which target
462+
* `MIRIFLAGS` defines extra flags to be passed to Miri.
463+
* `MIRI_LIB_SRC` defines the directory where Miri expects the sources of the standard library that
464+
it will build and use for interpretation. This directory must point to the `library` subdirectory
465+
of a `rust-lang/rust` repository checkout.
466+
* `MIRI_SYSROOT` indicates the sysroot to use. When using `cargo miri`, this skips the automatic
467+
setup -- only set this if you do not want to use the automatically created sysroot. When invoking
468+
`cargo miri setup`, this indicates where the sysroot will be put.
469+
* `MIRI_TEST_TARGET` (recognized by `./miri {test,run}`) indicates which target
473470
architecture to test against. `miri` and `cargo miri` accept the `--target` flag for the same
474471
purpose.
475-
* `MIRI_TEST_THREADS` (recognized by the test suite): set the number of threads to use for running tests.
476-
By default the number of cores is used.
477-
* `MIRI_NO_STD` (recognized by `cargo miri`) makes sure that the target's sysroot is built without
478-
libstd. This allows testing and running no_std programs.
479-
(Miri has a heuristic to detect no-std targets based on the target name; this environment variable
480-
is only needed when that heuristic fails.)
481-
* `RUSTC_BLESS` (recognized by the test suite and `cargo-miri-test/run-test.py`): overwrite all
472+
* `MIRI_TEST_THREADS` (recognized by `./miri test`): set the number of threads to use for running tests.
473+
By default, the number of cores is used.
474+
* `MIRI_NO_STD` makes sure that the target's sysroot is built without libstd. This allows testing
475+
and running no_std programs. (Miri has a heuristic to detect no-std targets based on the target
476+
name; this environment variable is only needed when that heuristic fails.)
477+
* `RUSTC_BLESS` (recognized by `./miri test` and `cargo-miri-test/run-test.py`): overwrite all
482478
`stderr` and `stdout` files instead of checking whether the output matches.
483-
* `MIRI_SKIP_UI_CHECKS` (recognized by the test suite): don't check whether the
479+
* `MIRI_SKIP_UI_CHECKS` (recognized by `./miri test`): don't check whether the
484480
`stderr` or `stdout` files match the actual output.
485481

486482
The following environment variables are *internal* and must not be used by

src/tools/miri/cargo-miri/Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,9 @@ dependencies = [
194194

195195
[[package]]
196196
name = "rustc-build-sysroot"
197-
version = "0.4.5"
197+
version = "0.4.6"
198198
source = "registry+https://github.com/rust-lang/crates.io-index"
199-
checksum = "a26170e1d79ea32f7ccec3188dd13cfc1f18c82764a9cbc1071667c0f865a4ea"
199+
checksum = "a9bf37423495cd3a6a9ef8c75fc4566de0d26de0ab75f36f67a426e58df5768c"
200200
dependencies = [
201201
"anyhow",
202202
"rustc_version",

src/tools/miri/cargo-miri/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ directories = "5"
1818
rustc_version = "0.4"
1919
serde_json = "1.0.40"
2020
cargo_metadata = "0.18.0"
21-
rustc-build-sysroot = "0.4.1"
21+
rustc-build-sysroot = "0.4.6"
2222

2323
# Enable some feature flags that dev-dependencies need but dependencies
2424
# do not. This makes `./miri install` after `./miri build` faster.

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

+19-7
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,6 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
172172
// Forward all further arguments (not consumed by `ArgSplitFlagValue`) to cargo.
173173
cmd.args(args);
174174

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

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

221+
// Forward some crucial information to our own re-invocations.
222+
cmd.env("MIRI_SYSROOT", miri_sysroot);
223223
cmd.env("MIRI_LOCAL_CRATES", local_crates(&metadata));
224224
if verbose > 0 {
225225
cmd.env("MIRI_VERBOSE", verbose.to_string()); // This makes the other phases verbose.
@@ -412,6 +412,12 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
412412
// Arguments are treated very differently depending on whether this crate is
413413
// for interpretation by Miri, or for use by a build script / proc macro.
414414
if target_crate {
415+
if phase != RustcPhase::Setup {
416+
// Set the sysroot -- except during setup, where we don't have an existing sysroot yet
417+
// and where the bootstrap wrapper adds its own `--sysroot` flag so we can't set ours.
418+
cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
419+
}
420+
415421
// Forward arguments, but patched.
416422
let emit_flag = "--emit";
417423
// This hack helps bootstrap run standard library tests in Miri. The issue is as follows:
@@ -574,6 +580,12 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
574580
cmd.env(name, val);
575581
}
576582

583+
if phase != RunnerPhase::Rustdoc {
584+
// Set the sysroot. Not necessary in rustdoc, where we already set the sysroot in
585+
// `phase_rustdoc`. rustdoc will forward that flag when invoking rustc (i.e., us), so the
586+
// flag is present in `info.args`.
587+
cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
588+
}
577589
// Forward rustc arguments.
578590
// We need to patch "--extern" filenames because we forced a check-only
579591
// build without cargo knowing about that: replace `.rlib` suffix by

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

+11-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::env;
22
use std::ffi::OsString;
33
use std::io::Write;
44
use std::ops::Not;
5+
use std::path::PathBuf;
56
use std::process;
67
use std::thread;
78
use std::time;
@@ -20,10 +21,11 @@ const JOSH_FILTER: &str =
2021
const JOSH_PORT: &str = "42042";
2122

2223
impl MiriEnv {
23-
fn build_miri_sysroot(&mut self, quiet: bool) -> Result<()> {
24-
if self.sh.var("MIRI_SYSROOT").is_ok() {
24+
/// Returns the location of the sysroot.
25+
fn build_miri_sysroot(&mut self, quiet: bool) -> Result<PathBuf> {
26+
if let Some(miri_sysroot) = self.sh.var_os("MIRI_SYSROOT") {
2527
// Sysroot already set, use that.
26-
return Ok(());
28+
return Ok(miri_sysroot.into());
2729
}
2830
let manifest_path = path!(self.miri_dir / "cargo-miri" / "Cargo.toml");
2931
let Self { toolchain, cargo_extra_flags, .. } = &self;
@@ -57,8 +59,8 @@ impl MiriEnv {
5759
.with_context(|| "`cargo miri setup` failed")?;
5860
panic!("`cargo miri setup` didn't fail again the 2nd time?");
5961
};
60-
self.sh.set_var("MIRI_SYSROOT", output);
61-
Ok(())
62+
self.sh.set_var("MIRI_SYSROOT", &output);
63+
Ok(output.into())
6264
}
6365
}
6466

@@ -505,8 +507,10 @@ impl Command {
505507
flags.push("--edition=2021".into()); // keep in sync with `tests/ui.rs`.`
506508
}
507509

508-
// Prepare a sysroot.
509-
e.build_miri_sysroot(/* quiet */ true)?;
510+
// Prepare a sysroot, and add it to the flags.
511+
let miri_sysroot = e.build_miri_sysroot(/* quiet */ true)?;
512+
flags.push("--sysroot".into());
513+
flags.push(miri_sysroot.into());
510514

511515
// Then run the actual command. Also add MIRIFLAGS.
512516
let miri_manifest = path!(e.miri_dir / "Cargo.toml");

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

-19
Original file line numberDiff line numberDiff line change
@@ -282,25 +282,6 @@ fn run_compiler(
282282
callbacks: &mut (dyn rustc_driver::Callbacks + Send),
283283
using_internal_features: std::sync::Arc<std::sync::atomic::AtomicBool>,
284284
) -> ! {
285-
if target_crate {
286-
// Miri needs a custom sysroot for target crates.
287-
// If no `--sysroot` is given, the `MIRI_SYSROOT` env var is consulted to find where
288-
// that sysroot lives, and that is passed to rustc.
289-
let sysroot_flag = "--sysroot";
290-
if !args.iter().any(|e| e.starts_with(sysroot_flag)) {
291-
// Using the built-in default here would be plain wrong, so we *require*
292-
// the env var to make sure things make sense.
293-
let miri_sysroot = env::var("MIRI_SYSROOT").unwrap_or_else(|_| {
294-
show_error!(
295-
"Miri was invoked in 'target' mode without `MIRI_SYSROOT` or `--sysroot` being set"
296-
)
297-
});
298-
299-
args.push(sysroot_flag.to_owned());
300-
args.push(miri_sysroot);
301-
}
302-
}
303-
304285
// Don't insert `MIRI_DEFAULT_ARGS`, in particular, `--cfg=miri`, if we are building
305286
// a "host" crate. That may cause procedural macros (and probably build scripts) to
306287
// depend on Miri-only symbols, such as `miri_resolve_frame`:

src/tools/miri/src/helpers.rs

+40-16
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,17 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
8383
("EAGAIN", WouldBlock),
8484
]
8585
};
86+
// This mapping should match `decode_error_kind` in
87+
// <https://github.com/rust-lang/rust/blob/master/library/std/src/sys/pal/windows/mod.rs>.
88+
const WINDOWS_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
89+
use std::io::ErrorKind::*;
90+
// FIXME: this is still incomplete.
91+
&[
92+
("ERROR_ACCESS_DENIED", PermissionDenied),
93+
("ERROR_FILE_NOT_FOUND", NotFound),
94+
("ERROR_INVALID_PARAMETER", InvalidInput),
95+
]
96+
};
8697

8798
/// Gets an instance for a path.
8899
///
@@ -749,20 +760,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
749760
}
750761
throw_unsup_format!("io error {:?} cannot be translated into a raw os error", err_kind)
751762
} else if target.families.iter().any(|f| f == "windows") {
752-
// FIXME: we have to finish implementing the Windows equivalent of this.
753-
use std::io::ErrorKind::*;
754-
Ok(this.eval_windows(
755-
"c",
756-
match err_kind {
757-
NotFound => "ERROR_FILE_NOT_FOUND",
758-
PermissionDenied => "ERROR_ACCESS_DENIED",
759-
_ =>
760-
throw_unsup_format!(
761-
"io error {:?} cannot be translated into a raw os error",
762-
err_kind
763-
),
764-
},
765-
))
763+
for &(name, kind) in WINDOWS_IO_ERROR_TABLE {
764+
if err_kind == kind {
765+
return Ok(this.eval_windows("c", name));
766+
}
767+
}
768+
throw_unsup_format!("io error {:?} cannot be translated into a raw os error", err_kind);
766769
} else {
767770
throw_unsup_format!(
768771
"converting io::Error into errnum is unsupported for OS {}",
@@ -786,8 +789,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
786789
return Ok(Some(kind));
787790
}
788791
}
789-
// Our table is as complete as the mapping in std, so we are okay with saying "that's a
790-
// strange one" here.
792+
return Ok(None);
793+
} else if target.families.iter().any(|f| f == "windows") {
794+
let errnum = errnum.to_u32()?;
795+
for &(name, kind) in WINDOWS_IO_ERROR_TABLE {
796+
if errnum == this.eval_windows("c", name).to_u32()? {
797+
return Ok(Some(kind));
798+
}
799+
}
791800
return Ok(None);
792801
} else {
793802
throw_unsup_format!(
@@ -1344,3 +1353,18 @@ pub(crate) fn simd_element_to_bool(elem: ImmTy<'_, Provenance>) -> InterpResult<
13441353
_ => throw_ub_format!("each element of a SIMD mask must be all-0-bits or all-1-bits"),
13451354
})
13461355
}
1356+
1357+
/// Check whether an operation that writes to a target buffer was successful.
1358+
/// Accordingly select return value.
1359+
/// Local helper function to be used in Windows shims.
1360+
pub(crate) fn windows_check_buffer_size((success, len): (bool, u64)) -> u32 {
1361+
if success {
1362+
// If the function succeeds, the return value is the number of characters stored in the target buffer,
1363+
// not including the terminating null character.
1364+
u32::try_from(len.checked_sub(1).unwrap()).unwrap()
1365+
} else {
1366+
// If the target buffer was not large enough to hold the data, the return value is the buffer size, in characters,
1367+
// required to hold the string and its terminating null character.
1368+
u32::try_from(len).unwrap()
1369+
}
1370+
}

src/tools/miri/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#![feature(let_chains)]
1414
#![feature(lint_reasons)]
1515
#![feature(trait_upcasting)]
16+
#![feature(absolute_path)]
1617
// Configure clippy and other lints
1718
#![allow(
1819
clippy::collapsible_else_if,

src/tools/miri/src/shims/env.rs

+7-18
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,7 @@ use rustc_middle::ty::Ty;
99
use rustc_target::abi::Size;
1010

1111
use crate::*;
12-
13-
/// Check whether an operation that writes to a target buffer was successful.
14-
/// Accordingly select return value.
15-
/// Local helper function to be used in Windows shims.
16-
fn windows_check_buffer_size((success, len): (bool, u64)) -> u32 {
17-
if success {
18-
// If the function succeeds, the return value is the number of characters stored in the target buffer,
19-
// not including the terminating null character.
20-
u32::try_from(len.checked_sub(1).unwrap()).unwrap()
21-
} else {
22-
// If the target buffer was not large enough to hold the data, the return value is the buffer size, in characters,
23-
// required to hold the string and its terminating null character.
24-
u32::try_from(len).unwrap()
25-
}
26-
}
12+
use helpers::windows_check_buffer_size;
2713

2814
#[derive(Default)]
2915
pub struct EnvVars<'tcx> {
@@ -164,7 +150,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
164150
let name_ptr = this.read_pointer(name_op)?;
165151
let name = this.read_os_str_from_wide_str(name_ptr)?;
166152
Ok(match this.machine.env_vars.map.get(&name) {
167-
Some(var_ptr) => {
153+
Some(&var_ptr) => {
154+
this.set_last_error(Scalar::from_u32(0))?; // make sure this is unambiguously not an error
168155
// The offset is used to strip the "{name}=" part of the string.
169156
#[rustfmt::skip]
170157
let name_offset_bytes = u64::try_from(name.len()).unwrap()
@@ -375,10 +362,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
375362

376363
// If we cannot get the current directory, we return 0
377364
match env::current_dir() {
378-
Ok(cwd) =>
365+
Ok(cwd) => {
366+
this.set_last_error(Scalar::from_u32(0))?; // make sure this is unambiguously not an error
379367
return Ok(Scalar::from_u32(windows_check_buffer_size(
380368
this.write_path_to_wide_str(&cwd, buf, size, /*truncate*/ false)?,
381-
))),
369+
)));
370+
}
382371
Err(e) => this.set_last_error_from_io_error(e.kind())?,
383372
}
384373
Ok(Scalar::from_u32(0))

0 commit comments

Comments
 (0)