diff options
| author | bors <bors@rust-lang.org> | 2023-01-10 03:26:29 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-01-10 03:26:29 +0000 |
| commit | deba5ddd0776108c51a69844d0ffe3f96886dd52 (patch) | |
| tree | fd0f493b3efc585f9779903c7451d10a016a958b /src | |
| parent | d53924d8c7046aee91c7f83bf4c9c788c2406a7d (diff) | |
| parent | ed840a6c3b953c54e221951910bb33b351bec145 (diff) | |
| download | rust-deba5ddd0776108c51a69844d0ffe3f96886dd52.tar.gz rust-deba5ddd0776108c51a69844d0ffe3f96886dd52.zip | |
Auto merge of #106656 - JohnTitor:rollup-rk2qltg, r=JohnTitor
Rollup of 9 pull requests Successful merges: - #105034 (Add example for iterator_flatten) - #105708 (Enable atomic cas for bpf targets) - #106175 (Fix bad import suggestion with nested `use` tree) - #106204 (No need to take opaques in `check_type_bounds`) - #106387 (Revert "bootstrap: Get rid of `tail_args` in `stream_cargo`") - #106636 (Accept old spelling of Fuchsia target triples) - #106639 (update Miri) - #106640 (update test for inductive canonical cycles) - #106647 (rustdoc: merge common CSS for `a`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'src')
30 files changed, 450 insertions, 110 deletions
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index b203ecd3844..2771bd2264c 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -99,13 +99,20 @@ impl Step for Std { cargo_subcommand(builder.kind), ); std_cargo(builder, target, compiler.stage, &mut cargo); - cargo.args(args(builder)); builder.info(&format!( "Checking stage{} library artifacts ({} -> {})", builder.top_stage, &compiler.host, target )); - run_cargo(builder, cargo, &libstd_stamp(builder, compiler, target), vec![], true, false); + run_cargo( + builder, + cargo, + args(builder), + &libstd_stamp(builder, compiler, target), + vec![], + true, + false, + ); // We skip populating the sysroot in non-zero stage because that'll lead // to rlib/rmeta conflicts if std gets built during this session. @@ -149,7 +156,6 @@ impl Step for Std { for krate in builder.in_tree_crates("test", Some(target)) { cargo.arg("-p").arg(krate.name); } - cargo.args(args(builder)); builder.info(&format!( "Checking stage{} library test/bench/example targets ({} -> {})", @@ -158,6 +164,7 @@ impl Step for Std { run_cargo( builder, cargo, + args(builder), &libstd_test_stamp(builder, compiler, target), vec![], true, @@ -226,13 +233,20 @@ impl Step for Rustc { for krate in builder.in_tree_crates("rustc-main", Some(target)) { cargo.arg("-p").arg(krate.name); } - cargo.args(args(builder)); builder.info(&format!( "Checking stage{} compiler artifacts ({} -> {})", builder.top_stage, &compiler.host, target )); - run_cargo(builder, cargo, &librustc_stamp(builder, compiler, target), vec![], true, false); + run_cargo( + builder, + cargo, + args(builder), + &librustc_stamp(builder, compiler, target), + vec![], + true, + false, + ); let libdir = builder.sysroot_libdir(compiler, target); let hostdir = builder.sysroot_libdir(compiler, compiler.host); @@ -279,7 +293,6 @@ impl Step for CodegenBackend { .arg("--manifest-path") .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend))); rustc_cargo_env(builder, &mut cargo, target); - cargo.args(args(builder)); builder.info(&format!( "Checking stage{} {} artifacts ({} -> {})", @@ -289,6 +302,7 @@ impl Step for CodegenBackend { run_cargo( builder, cargo, + args(builder), &codegen_backend_stamp(builder, compiler, target, backend), vec![], true, @@ -345,13 +359,19 @@ impl Step for RustAnalyzer { cargo.arg("--benches"); } - cargo.args(args(builder)); - builder.info(&format!( "Checking stage{} {} artifacts ({} -> {})", compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple )); - run_cargo(builder, cargo, &stamp(builder, compiler, target), vec![], true, false); + run_cargo( + builder, + cargo, + args(builder), + &stamp(builder, compiler, target), + vec![], + true, + false, + ); /// Cargo's output path in a given stage, compiled by a particular /// compiler for the specified target. @@ -405,8 +425,6 @@ macro_rules! tool_check_step { cargo.arg("--all-targets"); } - cargo.args(args(builder)); - // Enable internal lints for clippy and rustdoc // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]` // See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776 @@ -422,6 +440,7 @@ macro_rules! tool_check_step { run_cargo( builder, cargo, + args(builder), &stamp(builder, compiler, target), vec![], true, diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 147ded3a9ee..6b211d3ec6e 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -144,6 +144,7 @@ impl Step for Std { run_cargo( builder, cargo, + vec![], &libstd_stamp(builder, compiler, target), target_deps, false, @@ -738,6 +739,7 @@ impl Step for Rustc { run_cargo( builder, cargo, + vec![], &librustc_stamp(builder, compiler, target), vec![], false, @@ -998,7 +1000,7 @@ impl Step for CodegenBackend { "Building stage{} codegen backend {} ({} -> {})", compiler.stage, backend, &compiler.host, target )); - let files = run_cargo(builder, cargo, &tmp_stamp, vec![], false, false); + let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false); if builder.config.dry_run() { return; } @@ -1422,6 +1424,7 @@ pub fn add_to_sysroot( pub fn run_cargo( builder: &Builder<'_>, cargo: Cargo, + tail_args: Vec<String>, stamp: &Path, additional_target_deps: Vec<(PathBuf, DependencyType)>, is_check: bool, @@ -1448,7 +1451,7 @@ pub fn run_cargo( // files we need to probe for later. let mut deps = Vec::new(); let mut toplevel = Vec::new(); - let ok = stream_cargo(builder, cargo, &mut |msg| { + let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| { let (filenames, crate_types) = match msg { CargoMessage::CompilerArtifact { filenames, @@ -1585,6 +1588,7 @@ pub fn run_cargo( pub fn stream_cargo( builder: &Builder<'_>, cargo: Cargo, + tail_args: Vec<String>, cb: &mut dyn FnMut(CargoMessage<'_>), ) -> bool { let mut cargo = Command::from(cargo); @@ -1604,6 +1608,10 @@ pub fn stream_cargo( } cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped()); + for arg in tail_args { + cargo.arg(arg); + } + builder.verbose(&format!("running: {:?}", cargo)); let mut child = match cargo.spawn() { Ok(child) => child, diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 63026bd44d4..24b033cc0dc 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -72,7 +72,7 @@ impl Step for ToolBuild { builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); let mut duplicates = Vec::new(); - let is_expected = compile::stream_cargo(builder, cargo, &mut |msg| { + let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |msg| { // Only care about big things like the RLS/Cargo for now match tool { "rls" | "cargo" | "clippy-driver" | "miri" | "rustfmt" => {} diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 7ff26e420f1..16057048259 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -124,6 +124,7 @@ target | std | notes -------|:---:|------- `aarch64-apple-ios` | ✓ | ARM64 iOS [`aarch64-apple-ios-sim`](platform-support/aarch64-apple-ios-sim.md) | ✓ | Apple iOS Simulator on ARM64 +`aarch64-fuchsia` | ✓ | Alias for `aarch64-unknown-fuchsia` `aarch64-unknown-fuchsia` | ✓ | ARM64 Fuchsia [`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat @@ -177,6 +178,7 @@ target | std | notes `wasm32-wasi` | ✓ | WebAssembly with WASI `x86_64-apple-ios` | ✓ | 64-bit x86 iOS [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX +`x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia` `x86_64-unknown-fuchsia` | ✓ | 64-bit Fuchsia [`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android `x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 77401e8b76e..8ec4631f7d0 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -253,6 +253,7 @@ h1 a, a { color: var(--link-color); + text-decoration: none; } ol, ul { @@ -662,10 +663,6 @@ nav.sub { margin: 0 0 15px 0; } -a { - text-decoration: none; -} - .small-section-header { /* fields use <span> tags, but should get their own lines */ display: block; diff --git a/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr index e89c19b5881..f1f4caee361 100644 --- a/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr +++ b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -2,10 +2,7 @@ error[E0432]: unresolved import `my_core` --> $DIR/extern-prelude-from-opaque-fail.rs:20:9 | LL | use my_core; - | ^^^^^^^ - | | - | no `my_core` in the root - | help: a similar name exists in the module: `my_core` + | ^^^^^^^ no `my_core` in the root error[E0432]: unresolved import `my_core` --> $DIR/extern-prelude-from-opaque-fail.rs:7:13 diff --git a/src/test/ui/imports/bad-import-in-nested.rs b/src/test/ui/imports/bad-import-in-nested.rs new file mode 100644 index 00000000000..2e95480ad41 --- /dev/null +++ b/src/test/ui/imports/bad-import-in-nested.rs @@ -0,0 +1,27 @@ +// edition: 2021 + +#![allow(unused)] + +mod A { + pub(crate) type AA = (); + pub(crate) type BB = (); + + mod A2 { + use super::{super::C::D::AA, AA as _}; + //~^ ERROR unresolved import + } +} + +mod C { + pub mod D {} +} + +mod B { + use crate::C::{self, AA}; + //~^ ERROR unresolved import + + use crate::{A, C::BB}; + //~^ ERROR unresolved import +} + +fn main() {} diff --git a/src/test/ui/imports/bad-import-in-nested.stderr b/src/test/ui/imports/bad-import-in-nested.stderr new file mode 100644 index 00000000000..855b1e637e9 --- /dev/null +++ b/src/test/ui/imports/bad-import-in-nested.stderr @@ -0,0 +1,30 @@ +error[E0432]: unresolved import `super::super::C::D::AA` + --> $DIR/bad-import-in-nested.rs:10:21 + | +LL | use super::{super::C::D::AA, AA as _}; + | ^^^^^^^^^^^^^^^ no `AA` in `C::D` + | + = note: consider importing this type alias instead: + crate::A::AA + +error[E0432]: unresolved import `crate::C::AA` + --> $DIR/bad-import-in-nested.rs:20:26 + | +LL | use crate::C::{self, AA}; + | ^^ no `AA` in `C` + | + = note: consider importing this type alias instead: + crate::A::AA + +error[E0432]: unresolved import `crate::C::BB` + --> $DIR/bad-import-in-nested.rs:23:20 + | +LL | use crate::{A, C::BB}; + | ^^^^^ no `BB` in `C` + | + = note: consider importing this type alias instead: + crate::A::BB + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/bad-import-with-rename.rs b/src/test/ui/imports/bad-import-with-rename.rs new file mode 100644 index 00000000000..ffe56916f92 --- /dev/null +++ b/src/test/ui/imports/bad-import-with-rename.rs @@ -0,0 +1,16 @@ +mod A { + pub type B = (); + pub type B2 = (); +} + +mod C { + use crate::D::B as _; + //~^ ERROR unresolved import `crate::D::B` + + use crate::D::B2; + //~^ ERROR unresolved import `crate::D::B2` +} + +mod D {} + +fn main() {} diff --git a/src/test/ui/imports/bad-import-with-rename.stderr b/src/test/ui/imports/bad-import-with-rename.stderr new file mode 100644 index 00000000000..cace2a7a51c --- /dev/null +++ b/src/test/ui/imports/bad-import-with-rename.stderr @@ -0,0 +1,25 @@ +error[E0432]: unresolved import `crate::D::B` + --> $DIR/bad-import-with-rename.rs:7:9 + | +LL | use crate::D::B as _; + | ^^^^^^^^^^^^^^^^ no `B` in `D` + | +help: consider importing this type alias instead + | +LL | use A::B as _; + | ~~~~~~~~~~ + +error[E0432]: unresolved import `crate::D::B2` + --> $DIR/bad-import-with-rename.rs:10:9 + | +LL | use crate::D::B2; + | ^^^^^^^^^^^^ no `B2` in `D` + | +help: consider importing this type alias instead + | +LL | use A::B2; + | ~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/test-attrs/inaccessible-test-modules.stderr b/src/test/ui/test-attrs/inaccessible-test-modules.stderr index 0c16ecd4c86..a45c5bd4588 100644 --- a/src/test/ui/test-attrs/inaccessible-test-modules.stderr +++ b/src/test/ui/test-attrs/inaccessible-test-modules.stderr @@ -2,10 +2,7 @@ error[E0432]: unresolved import `main` --> $DIR/inaccessible-test-modules.rs:5:5 | LL | use main as x; - | ----^^^^^ - | | - | no `main` in the root - | help: a similar name exists in the module: `main` + | ^^^^^^^^^ no `main` in the root error[E0432]: unresolved import `test` --> $DIR/inaccessible-test-modules.rs:6:5 @@ -13,14 +10,10 @@ error[E0432]: unresolved import `test` LL | use test as y; | ^^^^^^^^^ no `test` in the root | -help: a similar name exists in the module - | -LL | use test as y; - | ~~~~ help: consider importing this module instead | -LL | use test::test; - | ~~~~~~~~~~~ +LL | use test::test as y; + | ~~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.rs b/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.rs index a3bb76d7e3b..5449f5f00d5 100644 --- a/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.rs +++ b/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.rs @@ -1,28 +1,69 @@ -// known-bug +// check-pass + +// This test checks that we're correctly dealing with inductive cycles +// with canonical inference variables. -// This should compile but fails with the current solver. -// -// This checks that the new solver uses `Ambiguous` when hitting the -// inductive cycle here when proving `exists<^0, ^1> (): Trait<^0, ^1>` -// which requires proving `Trait<?1, ?0>` but that has the same -// canonical representation. trait Trait<T, U> {} -impl<T, U> Trait<T, U> for () +trait IsNotU32 {} +impl IsNotU32 for i32 {} +impl<T: IsNotU32, U> Trait<T, U> for () // impl 1 where - (): Trait<U, T>, - T: OtherTrait, + (): Trait<U, T> {} -trait OtherTrait {} -impl OtherTrait for u32 {} +impl<T> Trait<u32, T> for () {} // impl 2 + +// If we now check whether `(): Trait<?0, ?1>` holds this has to +// result in ambiguity as both `for<T> (): Trait<u32, T>` and `(): Trait<i32, u32>` +// applies. The remainder of this test asserts that. + +// If we were to error on inductive cycles with canonical inference variables +// this would be wrong: -fn require_trait<T, U>() +// (): Trait<?0, ?1> +// - impl 1 +// - ?0: IsNotU32 // ambig +// - (): Trait<?1, ?0> // canonical cycle -> err +// - ERR +// - impl 2 +// - OK ?0 == u32 +// +// Result: OK ?0 == u32. + +// (): Trait<i32, u32> +// - impl 1 +// - i32: IsNotU32 // ok +// - (): Trait<u32, i32> +// - impl 1 +// - u32: IsNotU32 // err +// - ERR +// - impl 2 +// - OK +// - OK +// - impl 2 (trivial ERR) +// +// Result OK + +// This would mean that `(): Trait<?0, ?1>` is not complete, +// which is unsound if we're in coherence. + +fn implements_trait<T, U>() -> (T, U) where - (): Trait<T, U> -{} + (): Trait<T, U>, +{ + todo!() +} + +// A hack to only constrain the infer vars after first checking +// the `(): Trait<_, _>`. +trait Constrain<T> {} +impl<T> Constrain<T> for T {} +fn constrain<T: Constrain<U>, U>(_: U) {} fn main() { - require_trait::<_, _>(); - //~^ ERROR overflow evaluating + let (x, y) = implements_trait::<_, _>(); + + constrain::<i32, _>(x); + constrain::<u32, _>(y); } diff --git a/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.stderr b/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.stderr deleted file mode 100644 index e4b84e07822..00000000000 --- a/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0275]: overflow evaluating the requirement `_: Sized` - --> $DIR/inductive-canonical-cycle.rs:26:5 - | -LL | require_trait::<_, _>(); - | ^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inductive_canonical_cycle`) -note: required for `()` to implement `Trait<_, _>` - --> $DIR/inductive-canonical-cycle.rs:11:12 - | -LL | impl<T, U> Trait<T, U> for () - | ^^^^^^^^^^^ ^^ - = note: 128 redundant requirements hidden - = note: required for `()` to implement `Trait<_, _>` -note: required by a bound in `require_trait` - --> $DIR/inductive-canonical-cycle.rs:22:9 - | -LL | fn require_trait<T, U>() - | ------------- required by a bound in this -LL | where -LL | (): Trait<T, U> - | ^^^^^^^^^^^ required by this bound in `require_trait` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index e51bfa3798f..37f66d0033f 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -185,7 +185,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) { // explicitly do this even if RUSTC_STAGE is set, since for these builds we do *not* want the // 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("RUSTC", fs::canonicalize(find_miri()).unwrap()); cmd.env("MIRI_BE_RUSTC", "target"); // we better remember to *unset* this in the other phases! // Set rustdoc to us as well, so we can run doctests. diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index b35f7370d68..e01bfbc74d9 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -108,7 +108,8 @@ case $HOST_TARGET in MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic - MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer + MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings + MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture MIRI_TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std # JSON target file ;; diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index ee75e7a2932..cf6d9c28080 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -4f4d0586ad20c66a16d547581ca379beafece93a +c54c8cbac882e149e04a9e1f2d146fd548ae30ae diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index 5f132bf11a9..2cc8f035466 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -88,11 +88,7 @@ impl fmt::Display for InvalidationCause { match self { InvalidationCause::Access(kind) => write!(f, "{kind}"), InvalidationCause::Retag(perm, kind) => - if *kind == RetagCause::FnEntry { - write!(f, "{perm:?} FnEntry retag") - } else { - write!(f, "{perm:?} retag") - }, + write!(f, "{perm:?} {retag}", retag = kind.summary()), } } } @@ -193,7 +189,7 @@ struct RetagOp { #[derive(Debug, Clone, Copy, PartialEq)] pub enum RetagCause { Normal, - FnReturn, + FnReturnPlace, FnEntry, TwoPhase, } @@ -495,8 +491,8 @@ impl RetagCause { fn summary(&self) -> String { match self { RetagCause::Normal => "retag", - RetagCause::FnEntry => "FnEntry retag", - RetagCause::FnReturn => "FnReturn retag", + RetagCause::FnEntry => "function-entry retag", + RetagCause::FnReturnPlace => "return-place retag", RetagCause::TwoPhase => "two-phase retag", } .to_string() diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index bcdf2e75179..ec555ba2895 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -998,7 +998,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { access: Some(AccessKind::Write), protector: Some(ProtectorKind::StrongProtector), }; - let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturn)?; + let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturnPlace)?; // And use reborrowed pointer for return place. let return_place = this.ref_to_mplace(&val)?; this.frame_mut().return_place = return_place.into(); diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index c11c6104c28..527d31d1f0a 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -943,7 +943,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, ) -> InterpResult<'tcx, ()> { self.check_abi(abi, exp_abi)?; - if let Some((body, _)) = self.eval_context_mut().lookup_exported_symbol(link_name)? { + if let Some((body, instance)) = self.eval_context_mut().lookup_exported_symbol(link_name)? { + // If compiler-builtins is providing the symbol, then don't treat it as a clash. + // We'll use our built-in implementation in `emulate_foreign_item_by_name` for increased + // performance. Note that this means we won't catch any undefined behavior in + // compiler-builtins when running other crates, but Miri can still be run on + // compiler-builtins itself (or any crate that uses it as a normal dependency) + if self.eval_context_ref().tcx.is_compiler_builtins(instance.def_id().krate) { + return Ok(()); + } + throw_machine_stop!(TerminationInfo::SymbolShimClashing { link_name, span: body.span.data(), diff --git a/src/tools/miri/src/range_map.rs b/src/tools/miri/src/range_map.rs index c8ff06a3665..62198061827 100644 --- a/src/tools/miri/src/range_map.rs +++ b/src/tools/miri/src/range_map.rs @@ -219,7 +219,6 @@ mod tests { /// Query the map at every offset in the range and collect the results. fn to_vec<T: Copy>(map: &RangeMap<T>, offset: u64, len: u64) -> Vec<T> { (offset..offset + len) - .into_iter() .map(|i| { map.iter(Size::from_bytes(i), Size::from_bytes(1)).next().map(|(_, &t)| t).unwrap() }) diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs index e049eec57a3..ce24b23ca32 100644 --- a/src/tools/miri/src/shims/env.rs +++ b/src/tools/miri/src/shims/env.rs @@ -166,7 +166,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // `buf_size` represents the size in characters. let buf_size = u64::from(this.read_scalar(size_op)?.to_u32()?); Scalar::from_u32(windows_check_buffer_size( - this.write_os_str_to_wide_str(&var, buf_ptr, buf_size)?, + this.write_os_str_to_wide_str( + &var, buf_ptr, buf_size, /*truncate*/ false, + )?, )) } None => { @@ -366,7 +368,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { match env::current_dir() { Ok(cwd) => return Ok(Scalar::from_u32(windows_check_buffer_size( - this.write_path_to_wide_str(&cwd, buf, size)?, + this.write_path_to_wide_str(&cwd, buf, size, /*truncate*/ false)?, ))), Err(e) => this.set_last_error_from_io_error(e.kind())?, } diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs index 0375a228a21..f010d4251f4 100644 --- a/src/tools/miri/src/shims/os_str.rs +++ b/src/tools/miri/src/shims/os_str.rs @@ -101,17 +101,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { self.eval_context_mut().write_c_str(bytes, ptr, size) } - /// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what - /// the Windows APIs usually handle. This function returns `Ok((false, length))` without trying - /// to write if `size` is not large enough to fit the contents of `os_string` plus a null - /// terminator. It returns `Ok((true, length))` if the writing process was successful. The - /// string length returned does include the null terminator. Length is measured in units of - /// `u16.` + /// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what the + /// Windows APIs usually handle. + /// + /// If `truncate == false` (the usual mode of operation), this function returns `Ok((false, + /// length))` without trying to write if `size` is not large enough to fit the contents of + /// `os_string` plus a null terminator. It returns `Ok((true, length))` if the writing process + /// was successful. The string length returned does include the null terminator. Length is + /// measured in units of `u16.` + /// + /// If `truncate == true`, then in case `size` is not large enough it *will* write the first + /// `size.saturating_sub(1)` many items, followed by a null terminator (if `size > 0`). fn write_os_str_to_wide_str( &mut self, os_str: &OsStr, ptr: Pointer<Option<Provenance>>, size: u64, + truncate: bool, ) -> InterpResult<'tcx, (bool, u64)> { #[cfg(windows)] fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec<u16>> { @@ -129,7 +135,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } let u16_vec = os_str_to_u16vec(os_str)?; - self.eval_context_mut().write_wide_str(&u16_vec, ptr, size) + let (written, size_needed) = self.eval_context_mut().write_wide_str(&u16_vec, ptr, size)?; + if truncate && !written && size > 0 { + // Write the truncated part that fits. + let truncated_data = &u16_vec[..size.saturating_sub(1).try_into().unwrap()]; + let (written, written_len) = + self.eval_context_mut().write_wide_str(truncated_data, ptr, size)?; + assert!(written && written_len == size); + } + Ok((written, size_needed)) } /// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of bytes. @@ -143,7 +157,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let arg_type = this.tcx.mk_array(this.tcx.types.u8, size); let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?; - assert!(self.write_os_str_to_c_str(os_str, arg_place.ptr, size).unwrap().0); + let (written, _) = self.write_os_str_to_c_str(os_str, arg_place.ptr, size).unwrap(); + assert!(written); Ok(arg_place.ptr) } @@ -158,7 +173,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let arg_type = this.tcx.mk_array(this.tcx.types.u16, size); let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?; - assert!(self.write_os_str_to_wide_str(os_str, arg_place.ptr, size).unwrap().0); + let (written, _) = + self.write_os_str_to_wide_str(os_str, arg_place.ptr, size, /*truncate*/ false).unwrap(); + assert!(written); Ok(arg_place.ptr) } @@ -212,11 +229,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { path: &Path, ptr: Pointer<Option<Provenance>>, size: u64, + truncate: bool, ) -> InterpResult<'tcx, (bool, u64)> { let this = self.eval_context_mut(); let os_str = this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget); - this.write_os_str_to_wide_str(&os_str, ptr, size) + this.write_os_str_to_wide_str(&os_str, ptr, size, truncate) } /// Allocate enough memory to store a Path as a null-terminated sequence of bytes, @@ -232,6 +250,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.alloc_os_str_as_c_str(&os_str, memkind) } + /// Allocate enough memory to store a Path as a null-terminated sequence of `u16`s, + /// adjusting path separators if needed. + fn alloc_path_as_wide_str( + &mut self, + path: &Path, + memkind: MemoryKind<MiriMemoryKind>, + ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> { + let this = self.eval_context_mut(); + let os_str = + this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget); + this.alloc_os_str_as_wide_str(&os_str, memkind) + } + #[allow(clippy::get_first)] fn convert_path<'a>( &self, diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 1da8f7c0e3e..f310d16e861 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -381,6 +381,46 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(Scalar::from_u32(1), dest)?; } + "GetModuleFileNameW" => { + let [handle, filename, size] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + this.check_no_isolation("`GetModuleFileNameW`")?; + + let handle = this.read_machine_usize(handle)?; + let filename = this.read_pointer(filename)?; + let size = this.read_scalar(size)?.to_u32()?; + + if handle != 0 { + throw_unsup_format!("`GetModuleFileNameW` only supports the NULL handle"); + } + + // Using the host current_exe is a bit off, but consistent with Linux + // (where stdlib reads /proc/self/exe). + // Unfortunately this Windows function has a crazy behavior so we can't just use + // `write_path_to_wide_str`... + let path = std::env::current_exe().unwrap(); + let (all_written, size_needed) = this.write_path_to_wide_str( + &path, + filename, + size.into(), + /*truncate*/ true, + )?; + + if all_written { + // If the function succeeds, the return value is the length of the string that + // is copied to the buffer, in characters, not including the terminating null + // character. + this.write_int(size_needed.checked_sub(1).unwrap(), dest)?; + } else { + // If the buffer is too small to hold the module name, the string is truncated + // to nSize characters including the terminating null character, the function + // returns nSize, and the function sets the last error to + // ERROR_INSUFFICIENT_BUFFER. + this.write_int(size, dest)?; + let insufficient_buffer = this.eval_windows("c", "ERROR_INSUFFICIENT_BUFFER"); + this.set_last_error(insufficient_buffer)?; + } + } // Threading "CreateThread" => { diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index bf7f0411bed..a84ed859763 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -15,6 +15,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + +[[package]] name = "bytes" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -44,8 +50,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -58,6 +66,15 @@ dependencies = [ ] [[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + +[[package]] name = "libc" version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -124,6 +141,12 @@ dependencies = [ ] [[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + +[[package]] name = "page_size" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -269,9 +292,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" +checksum = "38a54aca0c15d014013256222ba0ebed095673f89345dd79119d912eb561b7a8" dependencies = [ "autocfg", "bytes", @@ -317,6 +340,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index 1df35bbbe2f..f5ab6acf008 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -13,11 +13,11 @@ libc = "0.2" num_cpus = "1.10.1" getrandom_1 = { package = "getrandom", version = "0.1" } -getrandom = { version = "0.2" } +getrandom = { version = "0.2", features = ["js"] } rand = { version = "0.8", features = ["small_rng"] } [target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies] page_size = "0.5" -tokio = { version = "1.0", features = ["full"] } +tokio = { version = "1.23", features = ["full"] } [workspace] diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr index 55aaed62f4f..ae54d0248dc 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr @@ -5,7 +5,7 @@ LL | pub fn safe(_x: &mut i32, _y: &i32) {} | ^^ | | | trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of FnEntry retag at ALLOC[0x0..0x4] + | this error occurs as part of function-entry retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information @@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4] | LL | safe_raw(xraw, xshr); | ^^^^ -help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag inside this call +help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique function-entry retag inside this call --> $DIR/aliasing_mut3.rs:LL:CC | LL | safe_raw(xraw, xshr); diff --git a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr index e3bffde1f01..236c8fb0187 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr @@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4] | LL | let z = &mut x as *mut i32; | ^^^^^^ -help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag inside this call +help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique function-entry retag inside this call --> $DIR/fnentry_invalidation.rs:LL:CC | LL | x.do_bad(); diff --git a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr index b104de4b8d9..45c2197050a 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr @@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0xc] | LL | let ptr = t.sli.as_ptr(); | ^^^^^^^^^^^^^^ -help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique FnEntry retag inside this call +help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique function-entry retag inside this call --> $DIR/fnentry_invalidation2.rs:LL:CC | LL | let _ = t.sli.as_mut_ptr(); diff --git a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs b/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs index 04e89ec361b..7ccafec6037 100644 --- a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs +++ b/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs @@ -186,8 +186,65 @@ fn join_orders_after_tls_destructors() { } } +fn dtors_in_dtors_in_dtors() { + use std::cell::UnsafeCell; + use std::sync::{Arc, Condvar, Mutex}; + + #[derive(Clone, Default)] + struct Signal(Arc<(Mutex<bool>, Condvar)>); + + impl Signal { + fn notify(&self) { + let (set, cvar) = &*self.0; + *set.lock().unwrap() = true; + cvar.notify_one(); + } + + fn wait(&self) { + let (set, cvar) = &*self.0; + let mut set = set.lock().unwrap(); + while !*set { + set = cvar.wait(set).unwrap(); + } + } + } + + struct NotifyOnDrop(Signal); + + impl Drop for NotifyOnDrop { + fn drop(&mut self) { + let NotifyOnDrop(ref f) = *self; + f.notify(); + } + } + + struct S1(Signal); + thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None)); + thread_local!(static K2: UnsafeCell<Option<NotifyOnDrop>> = UnsafeCell::new(None)); + + impl Drop for S1 { + fn drop(&mut self) { + let S1(ref signal) = *self; + unsafe { + let _ = K2.try_with(|s| *s.get() = Some(NotifyOnDrop(signal.clone()))); + } + } + } + + let signal = Signal::default(); + let signal2 = signal.clone(); + let _t = thread::spawn(move || unsafe { + let mut signal = Some(signal2); + K1.with(|s| *s.get() = Some(S1(signal.take().unwrap()))); + }); + // Note that this test will deadlock if TLS destructors aren't run (this + // requires the destructor to be run to pass the test). + signal.wait(); +} + fn main() { check_destructors(); check_blocking(); join_orders_after_tls_destructors(); + dtors_in_dtors_in_dtors(); } diff --git a/src/tools/miri/tests/pass/shims/env/current_exe.rs b/src/tools/miri/tests/pass/shims/env/current_exe.rs index 3f1153d265d..898a42b72d1 100644 --- a/src/tools/miri/tests/pass/shims/env/current_exe.rs +++ b/src/tools/miri/tests/pass/shims/env/current_exe.rs @@ -1,4 +1,3 @@ -//@ignore-target-windows: current_exe not supported on Windows //@only-on-host: the Linux std implementation opens /proc/self/exe, which doesn't work cross-target //@compile-flags: -Zmiri-disable-isolation use std::env; |
