From d3299af26d8e884c484c5d06991b4cbf7fced590 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 12 Mar 2024 13:29:15 +0100 Subject: [PATCH 01/36] transmute: caution against int2ptr transmutation --- library/core/src/intrinsics.rs | 37 ++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 86b9a39d68a67..ce498561eeb12 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1169,14 +1169,6 @@ extern "rust-intrinsic" { /// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly /// unsafe**. `transmute` should be the absolute last resort. /// - /// Transmuting pointers *to* integers in a `const` context is [undefined behavior][ub], - /// unless the pointer was originally created *from* an integer. - /// (That includes this function specifically, integer-to-pointer casts, and helpers like [`invalid`][crate::ptr::dangling], - /// but also semantically-equivalent conversions such as punning through `repr(C)` union fields.) - /// Any attempt to use the resulting value for integer operations will abort const-evaluation. - /// (And even outside `const`, such transmutation is touching on many unspecified aspects of the - /// Rust memory model and should be avoided. See below for alternatives.) - /// /// Because `transmute` is a by-value operation, alignment of the *transmuted values /// themselves* is not a concern. As with any other function, the compiler already ensures /// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point @@ -1187,6 +1179,35 @@ extern "rust-intrinsic" { /// /// [ub]: ../../reference/behavior-considered-undefined.html /// + /// # Transmutation between pointers and integers + /// + /// Special care has to be taken when transmuting between pointers and integers, e.g. + /// transmuting between `*const ()` and `usize`. + /// + /// Transmuting *pointers to integers* in a `const` context is [undefined behavior][ub], unless + /// the pointer was originally created *from* an integer. (That includes this function + /// specifically, integer-to-pointer casts, and helpers like [`invalid`][crate::ptr::dangling], + /// but also semantically-equivalent conversions such as punning through `repr(C)` union + /// fields.) Any attempt to use the resulting value for integer operations will abort + /// const-evaluation. (And even outside `const`, such transmutation is touching on many + /// unspecified aspects of the Rust memory model and should be avoided. See below for + /// alternatives.) + /// + /// Transmuting *integers to pointers* is a largely unspecified operation. It is likely *not* + /// equivalent to an `as` cast. Doing non-zero-sized memory accesses with a pointer constructed + /// this way is currently considered undefined behavior. + /// + /// All this also applies when the integer is nested inside an array, tuple, struct, or enum. + /// However, `MaybeUninit` is not considered an integer type for the purpose of this + /// section. Transmuting `*const ()` to `MaybeUninit` is fine---but then calling + /// `assume_init()` on that result is considered as completing the pointer-to-integer transmute + /// and thus runs into the issues discussed above. + /// + /// In particular, doing a pointer-to-integer-to-pointer roundtrip via `transmute` is *not* a + /// lossless process. If you want to round-trip a pointer through an integer in a way that you + /// can get back the original pointer, you need to use `as` casts, or replace the integer type + /// by `MaybeUninit<$int>` (and never call `assume_init()`). + /// /// # Examples /// /// There are a few things that `transmute` is really useful for. From 96674fce4ce73a231bae472d4e214f034eb2c4c9 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 17 Mar 2024 05:15:04 +0000 Subject: [PATCH 02/36] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index e32968d8178e8..f04e6e374799e 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -ee03c286cfdca26fa5b2a4ee40957625d2c826ff +a615cea3339046c7ab2d75cd253727d1fd42dd0b From b4cb2ee55f7b5bfd60d2d1061f273bb7668860bf Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 17 Mar 2024 10:56:28 +0100 Subject: [PATCH 03/36] fix Zulip topic for PR-creation message --- src/tools/miri/.github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index c70005c2c582a..1097fc6db7293 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -206,7 +206,7 @@ jobs: run: | PR=$(gh pr create -B master --title 'Automatic Rustup' --body '') ~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \ - --stream miri --subject "Cron Job Failure (miri, $(date -u +%Y-%m))" \ + --stream miri --subject "Miri Build Failure ($(date -u +%Y-%m))" \ --message "A PR doing a rustc-pull [has been automatically created]($PR) for your convenience." env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From a6f362f4714968d450042dbf639970c0ab538bde Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 17 Mar 2024 14:30:03 +0100 Subject: [PATCH 04/36] make 'invalidate' benchmark shorter --- src/tools/miri/bench-cargo-miri/invalidate/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/bench-cargo-miri/invalidate/src/main.rs b/src/tools/miri/bench-cargo-miri/invalidate/src/main.rs index fa8deb851c37b..42492b1a88f45 100644 --- a/src/tools/miri/bench-cargo-miri/invalidate/src/main.rs +++ b/src/tools/miri/bench-cargo-miri/invalidate/src/main.rs @@ -1,4 +1,4 @@ fn main() { // The end of the range is just chosen to make the benchmark run for a few seconds. - for _ in 0..200_000 {} + for _ in 0..50_000 {} } From c99c3141711e156ee56eb48f325c0e7146cd0e48 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 18 Mar 2024 08:55:45 +0100 Subject: [PATCH 05/36] add exposed-provenance example where we miss UB --- src/tools/miri/tests/pass/intptrcast.rs | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/tools/miri/tests/pass/intptrcast.rs b/src/tools/miri/tests/pass/intptrcast.rs index 370b09f512cbf..4e9fa12c18142 100644 --- a/src/tools/miri/tests/pass/intptrcast.rs +++ b/src/tools/miri/tests/pass/intptrcast.rs @@ -149,6 +149,31 @@ fn functions() { } } +/// Example that should be UB but due to wildcard pointers being too permissive +/// we don't notice. +fn should_be_ub() { + let alloc1 = 1u8; + let alloc2 = 2u8; + // Expose both allocations + let addr1: usize = &alloc1 as *const u8 as usize; + let addr2: usize = &alloc2 as *const u8 as usize; + + // Cast addr1 back to a pointer. In Miri, this gives it Wildcard provenance. + let wildcard = addr1 as *const u8; + unsafe { + // Read through the wildcard + assert_eq!(*wildcard, 1); + // Offset the pointer to another allocation. + // Note that we are doing this arithmetic that does not require we stay within bounds of the allocation. + let wildcard = wildcard.wrapping_offset(addr2 as isize - addr1 as isize); + // This should report UB: + assert_eq!(*wildcard, 2); + // ... but it doesn't. A pointer's provenance specifies a single allocation that it is allowed to read from. + // And wrapping_offset only modifies the address, not the provenance. + // So which allocation is wildcard allowed to access? It cannot be both. + } +} + fn main() { cast(); cast_dangling(); @@ -162,4 +187,5 @@ fn main() { ptr_eq_integer(); zst_deref_of_dangling(); functions(); + should_be_ub(); } From 311024c575c29ce615646460ec4833a7b829fb66 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 18 Mar 2024 08:59:19 +0100 Subject: [PATCH 06/36] rename 'invalidate' bench to something more clear --- .../bench-cargo-miri/{invalidate => range-iteration}/Cargo.lock | 2 +- .../bench-cargo-miri/{invalidate => range-iteration}/Cargo.toml | 2 +- .../{invalidate => range-iteration}/src/main.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) rename src/tools/miri/bench-cargo-miri/{invalidate => range-iteration}/Cargo.lock (84%) rename src/tools/miri/bench-cargo-miri/{invalidate => range-iteration}/Cargo.toml (86%) rename src/tools/miri/bench-cargo-miri/{invalidate => range-iteration}/src/main.rs (66%) diff --git a/src/tools/miri/bench-cargo-miri/invalidate/Cargo.lock b/src/tools/miri/bench-cargo-miri/range-iteration/Cargo.lock similarity index 84% rename from src/tools/miri/bench-cargo-miri/invalidate/Cargo.lock rename to src/tools/miri/bench-cargo-miri/range-iteration/Cargo.lock index 7bf23225ea5b4..2a5f8f3225427 100644 --- a/src/tools/miri/bench-cargo-miri/invalidate/Cargo.lock +++ b/src/tools/miri/bench-cargo-miri/range-iteration/Cargo.lock @@ -3,5 +3,5 @@ version = 3 [[package]] -name = "invalidate" +name = "range-iteration" version = "0.1.0" diff --git a/src/tools/miri/bench-cargo-miri/invalidate/Cargo.toml b/src/tools/miri/bench-cargo-miri/range-iteration/Cargo.toml similarity index 86% rename from src/tools/miri/bench-cargo-miri/invalidate/Cargo.toml rename to src/tools/miri/bench-cargo-miri/range-iteration/Cargo.toml index 14cf0882f0b6c..3f0146f6259b4 100644 --- a/src/tools/miri/bench-cargo-miri/invalidate/Cargo.toml +++ b/src/tools/miri/bench-cargo-miri/range-iteration/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "invalidate" +name = "range-iteration" version = "0.1.0" edition = "2021" diff --git a/src/tools/miri/bench-cargo-miri/invalidate/src/main.rs b/src/tools/miri/bench-cargo-miri/range-iteration/src/main.rs similarity index 66% rename from src/tools/miri/bench-cargo-miri/invalidate/src/main.rs rename to src/tools/miri/bench-cargo-miri/range-iteration/src/main.rs index 42492b1a88f45..1ef35ee6b3c5b 100644 --- a/src/tools/miri/bench-cargo-miri/invalidate/src/main.rs +++ b/src/tools/miri/bench-cargo-miri/range-iteration/src/main.rs @@ -1,3 +1,4 @@ +//! This generates a lot of work for the AllocId part of the GC. fn main() { // The end of the range is just chosen to make the benchmark run for a few seconds. for _ in 0..50_000 {} From 74b68af18aec5a98b923fb707ef25c23df0c2bb2 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 19 Mar 2024 04:56:56 +0000 Subject: [PATCH 07/36] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index f04e6e374799e..0cdb0de033c19 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -a615cea3339046c7ab2d75cd253727d1fd42dd0b +148a41c6b5687f941c5256d9ef8145eb03b72094 From f4adb1e6bdaef12d8b5776f74dadab0ddc11694d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 14 Mar 2024 21:29:21 +0100 Subject: [PATCH 08/36] add notes on how to store 'ptr or int' --- library/core/src/intrinsics.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index ce498561eeb12..27ed26fdcf16d 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1186,7 +1186,7 @@ extern "rust-intrinsic" { /// /// Transmuting *pointers to integers* in a `const` context is [undefined behavior][ub], unless /// the pointer was originally created *from* an integer. (That includes this function - /// specifically, integer-to-pointer casts, and helpers like [`invalid`][crate::ptr::dangling], + /// specifically, integer-to-pointer casts, and helpers like [`dangling`][crate::ptr::dangling], /// but also semantically-equivalent conversions such as punning through `repr(C)` union /// fields.) Any attempt to use the resulting value for integer operations will abort /// const-evaluation. (And even outside `const`, such transmutation is touching on many @@ -1206,7 +1206,11 @@ extern "rust-intrinsic" { /// In particular, doing a pointer-to-integer-to-pointer roundtrip via `transmute` is *not* a /// lossless process. If you want to round-trip a pointer through an integer in a way that you /// can get back the original pointer, you need to use `as` casts, or replace the integer type - /// by `MaybeUninit<$int>` (and never call `assume_init()`). + /// by `MaybeUninit<$int>` (and never call `assume_init()`). If you are looking for a way to + /// store data of arbitrary type, also use `MaybeUninit` (that will also handle uninitialized + /// memory due to padding). If you specifically need to store something that is "either an + /// integer or a pointer", use `*mut ()`: integers can be converted to pointers and back without + /// any loss (via `as` casts or via `transmute`). /// /// # Examples /// From 92a841d6692d59e5c00ff3bd5e232a6f9e54ca0c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 19 Mar 2024 07:55:28 +0100 Subject: [PATCH 09/36] remove duplicate test --- src/tools/miri/tests/pass/main_fn.rs | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 src/tools/miri/tests/pass/main_fn.rs diff --git a/src/tools/miri/tests/pass/main_fn.rs b/src/tools/miri/tests/pass/main_fn.rs deleted file mode 100644 index 4cdd034f30eea..0000000000000 --- a/src/tools/miri/tests/pass/main_fn.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod foo { - pub(crate) fn bar() {} -} - -use foo::bar as main; From e5398041b4ed1a65a108e06cd7bdf8122177fb92 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 19 Mar 2024 19:35:35 +0100 Subject: [PATCH 10/36] run full mono-item collection on all MIRI_BE_RUSTC=target builds this fixes compile_fail doctests with post-mono errors --- src/tools/miri/src/bin/miri.rs | 20 +++++++++++++++++++ src/tools/miri/test-cargo-miri/src/lib.rs | 18 +++++++++++++++++ .../test-cargo-miri/test.default.stdout.ref | 6 +++--- .../test-cargo-miri/test.filter.stdout.ref | 2 +- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 6955e649b4d17..c12382527e7bf 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -179,6 +179,26 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls { }); } } + + fn after_analysis<'tcx>( + &mut self, + _: &rustc_interface::interface::Compiler, + queries: &'tcx rustc_interface::Queries<'tcx>, + ) -> Compilation { + queries.global_ctxt().unwrap().enter(|tcx| { + if self.target_crate { + // cargo-miri has patched the compiler flags to make these into check-only builds, + // but we are still emulating regular rustc builds, which would perform post-mono + // const-eval during collection. So let's also do that here, even if we might be + // running with `--emit=metadata`. In particular this is needed to make + // `compile_fail` doc tests trigger post-mono errors. + // In general `collect_and_partition_mono_items` is not safe to call in check-only + // builds, but we are setting `-Zalways-encode-mir` which avoids those issues. + let _ = tcx.collect_and_partition_mono_items(()); + } + }); + Compilation::Continue + } } fn show_error(msg: &impl std::fmt::Display) -> ! { diff --git a/src/tools/miri/test-cargo-miri/src/lib.rs b/src/tools/miri/test-cargo-miri/src/lib.rs index 66c8aa2eac57e..e6b8c4ef65b2f 100644 --- a/src/tools/miri/test-cargo-miri/src/lib.rs +++ b/src/tools/miri/test-cargo-miri/src/lib.rs @@ -1,13 +1,31 @@ /// Doc-test test +/// /// ```rust /// assert!(cargo_miri_test::make_true()); /// ``` +/// +/// `no_run` test: +/// /// ```rust,no_run /// assert!(!cargo_miri_test::make_true()); /// ``` +/// +/// `compile_fail` test: +/// /// ```rust,compile_fail /// assert!(cargo_miri_test::make_true() == 5); /// ``` +/// +/// Post-monomorphization error in `compile_fail` test: +/// +/// ```rust,compile_fail +/// struct Fail(T); +/// impl Fail { +/// const C: () = panic!(); +/// } +/// +/// let _val = Fail::::C; +/// ``` #[no_mangle] pub fn make_true() -> bool { issue_1567::use_the_dependency(); diff --git a/src/tools/miri/test-cargo-miri/test.default.stdout.ref b/src/tools/miri/test-cargo-miri/test.default.stdout.ref index 9a17f3d61b6ac..922d2120bed0f 100644 --- a/src/tools/miri/test-cargo-miri/test.default.stdout.ref +++ b/src/tools/miri/test-cargo-miri/test.default.stdout.ref @@ -10,7 +10,7 @@ running 6 tests test result: ok. 5 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out -running 4 tests -.... -test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +running 5 tests +..... +test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/src/tools/miri/test-cargo-miri/test.filter.stdout.ref b/src/tools/miri/test-cargo-miri/test.filter.stdout.ref index c618956656a8a..5c819dd532366 100644 --- a/src/tools/miri/test-cargo-miri/test.filter.stdout.ref +++ b/src/tools/miri/test-cargo-miri/test.filter.stdout.ref @@ -13,5 +13,5 @@ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 5 filtered out running 0 tests -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 4 filtered out; finished in $TIME +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 5 filtered out; finished in $TIME From 89bc81f0dfdd128a9c4b906efebf5070a70f39d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Thu, 21 Mar 2024 17:54:53 +0100 Subject: [PATCH 11/36] Allow `llvm.x86.sse2.pause` instrinsic to be called without SSE2 The instrinsic is compiled to a `pause` instruction, which behaves like a no-op when SSE2 is not available. https://www.felixcloutier.com/x86/pause.html --- src/tools/miri/src/shims/x86/mod.rs | 13 ++++++++++ src/tools/miri/src/shims/x86/sse2.rs | 6 ----- .../pass/intrinsics-x86-pause-without-sse2.rs | 25 +++++++++++++++++++ .../miri/tests/pass/intrinsics-x86-sse2.rs | 5 ++++ 4 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 src/tools/miri/tests/pass/intrinsics-x86-pause-without-sse2.rs diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 7cd397625dca6..7b7921219e616 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -88,6 +88,19 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_immediate(*sub, &this.project_field(dest, 1)?)?; } + // Used to implement the `_mm_pause` function. + // The intrinsic is used to hint the processor that the code is in a spin-loop. + // It is compiled down to a `pause` instruction. When SSE2 is not available, + // the instruction behaves like a no-op, so it is always safe to call the + // intrinsic. + "sse2.pause" => { + let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + // Only exhibit the spin-loop hint behavior when SSE2 is enabled. + if this.tcx.sess.unstable_target_features.contains(&Symbol::intern("sse2")) { + this.yield_active_thread(); + } + } + name if name.starts_with("sse.") => { return sse::EvalContextExt::emulate_x86_sse_intrinsic( this, link_name, abi, args, dest, diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index 18ff5d809e322..eb2cc9d37c826 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -580,12 +580,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?; } } - // Used to implement the `_mm_pause` function. - // The intrinsic is used to hint the processor that the code is in a spin-loop. - "pause" => { - let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - this.yield_active_thread(); - } _ => return Ok(EmulateForeignItemResult::NotSupported), } Ok(EmulateForeignItemResult::NeedsJumping) diff --git a/src/tools/miri/tests/pass/intrinsics-x86-pause-without-sse2.rs b/src/tools/miri/tests/pass/intrinsics-x86-pause-without-sse2.rs new file mode 100644 index 0000000000000..c8b92fd545850 --- /dev/null +++ b/src/tools/miri/tests/pass/intrinsics-x86-pause-without-sse2.rs @@ -0,0 +1,25 @@ +// Ignore everything except x86 and x86_64 +// Any new targets that are added to CI should be ignored here. +// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) +//@ignore-target-aarch64 +//@ignore-target-arm +//@ignore-target-avr +//@ignore-target-s390x +//@ignore-target-thumbv7em +//@ignore-target-wasm32 +//@compile-flags: -C target-feature=-sse2 + +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +fn main() { + assert!(!is_x86_feature_detected!("sse2")); + + unsafe { + // This is a SSE2 intrinsic, but it behaves as a no-op when SSE2 + // is not available, so it is always safe to call. + _mm_pause(); + } +} diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs b/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs index e636d6c8aaf8d..e0088b9eb24d3 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs @@ -54,6 +54,11 @@ mod tests { } } + fn test_mm_pause() { + unsafe { _mm_pause() } + } + test_mm_pause(); + #[target_feature(enable = "sse2")] unsafe fn test_mm_avg_epu8() { let (a, b) = (_mm_set1_epi8(3), _mm_set1_epi8(9)); From 5719d09d92a4dc171531452b5f72f46c28c9ee32 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 22 Mar 2024 16:03:56 +0100 Subject: [PATCH 12/36] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 0cdb0de033c19..78a07cd99a04c 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -148a41c6b5687f941c5256d9ef8145eb03b72094 +1447f9d38ca388ca178a544534b3cff72945fa1e From 063f0112704ec3a32fc58634f38d93343cac4a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 22 Mar 2024 17:49:04 +0100 Subject: [PATCH 13/36] add test for #52334 Fixes #52334 --- .../extern-C-non-FFI-safe-arg-ice-52334.rs | 13 +++++++++++ ...extern-C-non-FFI-safe-arg-ice-52334.stderr | 22 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.rs create mode 100644 tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr diff --git a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.rs b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.rs new file mode 100644 index 0000000000000..3f515ea890935 --- /dev/null +++ b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.rs @@ -0,0 +1,13 @@ +// test for #52334 ICE when casting extern "C" fn when it has a non-FFI-safe argument +//@ check-pass + +type Foo = extern "C" fn(::std::ffi::CStr); +//~^ WARN `extern` fn uses type `[i8]`, which is not FFI-safe +extern "C" { + fn meh(blah: Foo); + //~^ WARN `extern` block uses type `[i8]`, which is not FFI-safe +} + +fn main() { + meh as usize; +} diff --git a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr new file mode 100644 index 0000000000000..97c632740e884 --- /dev/null +++ b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr @@ -0,0 +1,22 @@ +warning: `extern` fn uses type `[i8]`, which is not FFI-safe + --> $DIR/extern-C-non-FFI-safe-arg-ice-52334.rs:4:12 + | +LL | type Foo = extern "C" fn(::std::ffi::CStr); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider using a raw pointer instead + = note: slices have no C equivalent + = note: `#[warn(improper_ctypes_definitions)]` on by default + +warning: `extern` block uses type `[i8]`, which is not FFI-safe + --> $DIR/extern-C-non-FFI-safe-arg-ice-52334.rs:7:18 + | +LL | fn meh(blah: Foo); + | ^^^ not FFI-safe + | + = help: consider using a raw pointer instead + = note: slices have no C equivalent + = note: `#[warn(improper_ctypes)]` on by default + +warning: 2 warnings emitted + From c3bde2477445b469bd8be74424d780a523389cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 22 Mar 2024 18:00:38 +0100 Subject: [PATCH 14/36] add test for #64784 Declarative macros can create infinite glob import cycles Fixes #64784 --- ...acro-infinite-global-import-cycle-ice-64784.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/ui/privacy/decl-macro-infinite-global-import-cycle-ice-64784.rs diff --git a/tests/ui/privacy/decl-macro-infinite-global-import-cycle-ice-64784.rs b/tests/ui/privacy/decl-macro-infinite-global-import-cycle-ice-64784.rs new file mode 100644 index 0000000000000..da7c5442d36da --- /dev/null +++ b/tests/ui/privacy/decl-macro-infinite-global-import-cycle-ice-64784.rs @@ -0,0 +1,15 @@ +// ICE #64784 already borrowed: BorrowMutError +//@ check-pass +#![feature(decl_macro)] + +pub macro m($i:ident, $j:ident) { + mod $i { + pub use crate::$j::*; + pub struct A; + } +} + +m!(x, y); +m!(y, x); + +fn main() {} From 72d2b5958230519d8fe522f7e5f147e4ac2eee51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 22 Mar 2024 18:12:49 +0100 Subject: [PATCH 15/36] add test for str as extern "C" arg causes compiler panic #80125 Fixes #80125 --- tests/ui/extern/extern-C-str-arg-ice-80125.rs | 15 ++++++++ .../extern/extern-C-str-arg-ice-80125.stderr | 35 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 tests/ui/extern/extern-C-str-arg-ice-80125.rs create mode 100644 tests/ui/extern/extern-C-str-arg-ice-80125.stderr diff --git a/tests/ui/extern/extern-C-str-arg-ice-80125.rs b/tests/ui/extern/extern-C-str-arg-ice-80125.rs new file mode 100644 index 0000000000000..71098fed2efad --- /dev/null +++ b/tests/ui/extern/extern-C-str-arg-ice-80125.rs @@ -0,0 +1,15 @@ +// test for #80125 +//@ check-pass +type ExternCallback = extern "C" fn(*const u8, u32, str); +//~^ WARN `extern` fn uses type `str`, which is not FFI-safe + +pub struct Struct(ExternCallback); + +#[no_mangle] +pub extern "C" fn register_something(bind: ExternCallback) -> Struct { +//~^ WARN `extern` fn uses type `str`, which is not FFI-safe +//~^^ WARN `extern` fn uses type `Struct`, which is not FFI-safe + Struct(bind) +} + +fn main() {} diff --git a/tests/ui/extern/extern-C-str-arg-ice-80125.stderr b/tests/ui/extern/extern-C-str-arg-ice-80125.stderr new file mode 100644 index 0000000000000..ebd6cec6ecd3f --- /dev/null +++ b/tests/ui/extern/extern-C-str-arg-ice-80125.stderr @@ -0,0 +1,35 @@ +warning: `extern` fn uses type `str`, which is not FFI-safe + --> $DIR/extern-C-str-arg-ice-80125.rs:3:23 + | +LL | type ExternCallback = extern "C" fn(*const u8, u32, str); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent + = note: `#[warn(improper_ctypes_definitions)]` on by default + +warning: `extern` fn uses type `str`, which is not FFI-safe + --> $DIR/extern-C-str-arg-ice-80125.rs:9:44 + | +LL | pub extern "C" fn register_something(bind: ExternCallback) -> Struct { + | ^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent + +warning: `extern` fn uses type `Struct`, which is not FFI-safe + --> $DIR/extern-C-str-arg-ice-80125.rs:9:63 + | +LL | pub extern "C" fn register_something(bind: ExternCallback) -> Struct { + | ^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/extern-C-str-arg-ice-80125.rs:6:1 + | +LL | pub struct Struct(ExternCallback); + | ^^^^^^^^^^^^^^^^^ + +warning: 3 warnings emitted + From 6b0dfc5b9a95ad06df5399e8a8d9027e03dd9adb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 22 Mar 2024 18:18:56 +0100 Subject: [PATCH 16/36] add test for ice 83056 "bad input type for cast" Fixes #83056 --- .../ice-bad-input-type-for-cast-83056.rs | 6 ++++++ .../ice-bad-input-type-for-cast-83056.stderr | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/ui/consts/ice-bad-input-type-for-cast-83056.rs create mode 100644 tests/ui/consts/ice-bad-input-type-for-cast-83056.stderr diff --git a/tests/ui/consts/ice-bad-input-type-for-cast-83056.rs b/tests/ui/consts/ice-bad-input-type-for-cast-83056.rs new file mode 100644 index 0000000000000..ea0aba2c91160 --- /dev/null +++ b/tests/ui/consts/ice-bad-input-type-for-cast-83056.rs @@ -0,0 +1,6 @@ +// #83056 ICE "bad input type for cast" + +struct S([bool; f as usize]); +fn f() -> T {} +//~^ ERROR cannot find type `T` in this scope +pub fn main() {} diff --git a/tests/ui/consts/ice-bad-input-type-for-cast-83056.stderr b/tests/ui/consts/ice-bad-input-type-for-cast-83056.stderr new file mode 100644 index 0000000000000..4764f49cf464a --- /dev/null +++ b/tests/ui/consts/ice-bad-input-type-for-cast-83056.stderr @@ -0,0 +1,20 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/ice-bad-input-type-for-cast-83056.rs:4:11 + | +LL | struct S([bool; f as usize]); + | ----------------------------- similarly named struct `S` defined here +LL | fn f() -> T {} + | ^ + | +help: a struct with a similar name exists + | +LL | fn f() -> S {} + | ~ +help: you might be missing a type parameter + | +LL | fn f() -> T {} + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0412`. From c7ef3cd65d1cfb1a4ca6a50ab7d93e0c2b7bdb4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 22 Mar 2024 18:23:19 +0100 Subject: [PATCH 17/36] add test for #88212 ICE when lambda captures unsized local Fixes #88212 --- ...nd_align_of-closure-not-supported-88212.rs | 21 +++++++++++++++++ ...lign_of-closure-not-supported-88212.stderr | 23 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs create mode 100644 tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.stderr diff --git a/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs b/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs new file mode 100644 index 0000000000000..1c43e3a448976 --- /dev/null +++ b/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs @@ -0,0 +1,21 @@ +// ICE size_and_align_of::<[closure@test.rs:15:5: 17:7]> not supported #88212 + +#![feature(unsized_locals)] +//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + +trait Example {} +struct Foo(); + +impl Example for Foo {} + +fn example() -> Box { + Box::new(Foo()) +} + +fn main() { + let x: dyn Example = *example(); + (move || { + let _y = x; + //~^ ERROR the size for values of type `dyn Example` cannot be known at compilation time + })(); +} diff --git a/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.stderr b/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.stderr new file mode 100644 index 0000000000000..a0253ac1f35aa --- /dev/null +++ b/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.stderr @@ -0,0 +1,23 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/ice-size_and_align_of-closure-not-supported-88212.rs:3:12 + | +LL | #![feature(unsized_locals)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the size for values of type `dyn Example` cannot be known at compilation time + --> $DIR/ice-size_and_align_of-closure-not-supported-88212.rs:18:18 + | +LL | (move || { + | -- this closure captures all values by move +LL | let _y = x; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Example` + = note: all values captured by value by a closure must have a statically known size + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. From 3c1db068d3e972511e6149caf094c278a68294a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 22 Mar 2024 18:29:41 +0100 Subject: [PATCH 18/36] add test for 88421 ICE: could not fully normalize `&>::Output Fixes #88421 --- .../failed-to-normalize-ice-issue-88421.rs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/ui/const-generics/generic_const_exprs/failed-to-normalize-ice-issue-88421.rs diff --git a/tests/ui/const-generics/generic_const_exprs/failed-to-normalize-ice-issue-88421.rs b/tests/ui/const-generics/generic_const_exprs/failed-to-normalize-ice-issue-88421.rs new file mode 100644 index 0000000000000..2ea7394fb72a5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/failed-to-normalize-ice-issue-88421.rs @@ -0,0 +1,36 @@ +//@ check-pass + +#![feature(adt_const_params)] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +use std::ops::Index; + +pub struct CellPossibilities; + +pub enum CellState { + Empty(Option), +} + +pub struct Sudoku; + +impl Sudokuwhere + [CellState; SQUARE_SIZE * SQUARE_SIZE]: Sized, +{ + pub fn random() { + let CellState::Empty(_) = Self[()]; + } +} + +impl Index<()> for Sudoku +where + [CellState; SQUARE_SIZE * SQUARE_SIZE]: Sized, +{ + type Output = CellState; + + fn index(&self, _: ()) -> &Self::Output { + todo!() + } +} + +pub fn main() {} From efc57fbdb42411b5a6253588de05f42b62376f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 22 Mar 2024 18:36:16 +0100 Subject: [PATCH 19/36] add test for ice #90691 ICE: resolution failed during building vtable representation Fixes #90691 --- ...uilding-vtable-representation-ice-90691.rs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/ui/associated-type-bounds/resolution-failure-building-vtable-representation-ice-90691.rs diff --git a/tests/ui/associated-type-bounds/resolution-failure-building-vtable-representation-ice-90691.rs b/tests/ui/associated-type-bounds/resolution-failure-building-vtable-representation-ice-90691.rs new file mode 100644 index 0000000000000..33776809a7912 --- /dev/null +++ b/tests/ui/associated-type-bounds/resolution-failure-building-vtable-representation-ice-90691.rs @@ -0,0 +1,41 @@ +// ICE #90691 Encountered error `Unimplemented` selecting ... +//@ build-pass + +trait TError: std::fmt::Debug {} +impl TError for () {} + +trait SuperTrait { + type Error; +} + +trait Trait: SuperTrait {} + +impl Trait for T +where + T: SuperTrait, + ::Error: TError, +{ +} + +struct SomeTrait(S); +struct BoxedTrait(Box>); + +impl From> for BoxedTrait { + fn from(other: SomeTrait) -> Self { + Self(Box::new(other)) + } +} + +impl SuperTrait for SomeTrait { + type Error = (); +} + +impl From<()> for BoxedTrait { + fn from(c: ()) -> Self { + Self::from(SomeTrait(c)) + } +} + +fn main() { + let _: BoxedTrait = ().into(); +} From 15ef7a0ee1b13b4485e8dad2590a99e7fcc5eb9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 22 Mar 2024 19:06:46 +0100 Subject: [PATCH 20/36] add test for stack overflow with recursive type #98842 Fixes #98842 --- .../sized/stack-overflow-trait-infer-98842.rs | 15 +++++++++++ .../stack-overflow-trait-infer-98842.stderr | 25 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/ui/sized/stack-overflow-trait-infer-98842.rs create mode 100644 tests/ui/sized/stack-overflow-trait-infer-98842.stderr diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.rs b/tests/ui/sized/stack-overflow-trait-infer-98842.rs new file mode 100644 index 0000000000000..2bba0777be49f --- /dev/null +++ b/tests/ui/sized/stack-overflow-trait-infer-98842.rs @@ -0,0 +1,15 @@ +// #98842 stack overflow in trait inference +//@ check-fail +//@ edition:2021 +//~^^^ ERROR cycle detected when computing layout of `Foo` + +// If the inner `Foo` is named through an associated type, +// the "infinite size" error does not occur. +struct Foo(<&'static Foo as ::core::ops::Deref>::Target); +// But Rust will be unable to know whether `Foo` is sized or not, +// and it will infinitely recurse somewhere trying to figure out the +// size of this pointer (is my guess): +const _: *const Foo = 0 as _; +//~^ ERROR it is undefined behavior to use this value + +pub fn main() {} diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.stderr new file mode 100644 index 0000000000000..42b2718e33246 --- /dev/null +++ b/tests/ui/sized/stack-overflow-trait-infer-98842.stderr @@ -0,0 +1,25 @@ +error[E0391]: cycle detected when computing layout of `Foo` + | + = note: ...which requires computing layout of `<&'static Foo as core::ops::deref::Deref>::Target`... + = note: ...which again requires computing layout of `Foo`, completing the cycle +note: cycle used when const-evaluating + checking `_` + --> $DIR/stack-overflow-trait-infer-98842.rs:12:1 + | +LL | const _: *const Foo = 0 as _; + | ^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0080]: it is undefined behavior to use this value + --> $DIR/stack-overflow-trait-infer-98842.rs:12:1 + | +LL | const _: *const Foo = 0 as _; + | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation + | + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0080, E0391. +For more information about an error, try `rustc --explain E0080`. From 1fcf2eaa9f5ff9336e9b43f017eaf261acfdc2d3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 22 Mar 2024 16:35:44 -0400 Subject: [PATCH 21/36] Uniquify ReError on input mode in canonicalizer --- .../src/canonicalizer.rs | 3 +- .../next-solver/dont-canonicalize-re-error.rs | 28 +++++++++++++++++++ .../dont-canonicalize-re-error.stderr | 21 ++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/next-solver/dont-canonicalize-re-error.rs create mode 100644 tests/ui/traits/next-solver/dont-canonicalize-re-error.stderr diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 95b3006666202..2dbb44bdee207 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -239,7 +239,7 @@ impl, I: Interner> TypeFolder // FIXME: We should investigate the perf implications of not uniquifying // `ReErased`. We may be able to short-circuit registering region // obligations if we encounter a `ReErased` on one side, for example. - ty::ReStatic | ty::ReErased => match self.canonicalize_mode { + ty::ReStatic | ty::ReErased | ty::ReError(_) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { .. } => return r, }, @@ -277,7 +277,6 @@ impl, I: Interner> TypeFolder } } } - ty::ReError(_) => return r, }; let existing_bound_var = match self.canonicalize_mode { diff --git a/tests/ui/traits/next-solver/dont-canonicalize-re-error.rs b/tests/ui/traits/next-solver/dont-canonicalize-re-error.rs new file mode 100644 index 0000000000000..57f814bc81ec2 --- /dev/null +++ b/tests/ui/traits/next-solver/dont-canonicalize-re-error.rs @@ -0,0 +1,28 @@ +//@ compile-flags: -Znext-solver + +trait Tr<'a> {} + +// Fulfillment in the new solver relies on an invariant to hold: Either +// `has_changed` is true, or computing a goal's certainty is idempotent. +// This isn't true for `ReError`, which we used to pass through in the +// canonicalizer even on input mode, which can cause a goal to go from +// ambig => pass, but we don't consider `has_changed` when the response +// only contains region constraints (since we usually uniquify regions). +// +// In this test: +// Implicit negative coherence tries to prove `W: Constrain<'?1>`, +// which will then match with the impl below. This constrains `'?1` to +// `ReError`, but still bails w/ ambiguity bc we can't prove `?0: Sized`. +// Then, when we recompute the goal `W: Constrain<'error>`, when +// collecting ambiguities and overflows, we end up assembling a default +// error candidate w/o ambiguity, which causes the goal to pass, and ICE. +impl<'a, A: ?Sized> Tr<'a> for W {} +struct W(A); +impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {} +//~^ ERROR conflicting implementations of trait `Tr<'_>` for type `W<_>` + +trait Constrain<'a> {} +impl Constrain<'missing> for W {} +//~^ ERROR use of undeclared lifetime name `'missing` + +fn main() {} diff --git a/tests/ui/traits/next-solver/dont-canonicalize-re-error.stderr b/tests/ui/traits/next-solver/dont-canonicalize-re-error.stderr new file mode 100644 index 0000000000000..cf85c52fb42ee --- /dev/null +++ b/tests/ui/traits/next-solver/dont-canonicalize-re-error.stderr @@ -0,0 +1,21 @@ +error[E0261]: use of undeclared lifetime name `'missing` + --> $DIR/dont-canonicalize-re-error.rs:25:26 + | +LL | impl Constrain<'missing> for W {} + | - ^^^^^^^^ undeclared lifetime + | | + | help: consider introducing lifetime `'missing` here: `'missing,` + +error[E0119]: conflicting implementations of trait `Tr<'_>` for type `W<_>` + --> $DIR/dont-canonicalize-re-error.rs:21:1 + | +LL | impl<'a, A: ?Sized> Tr<'a> for W {} + | ----------------------------------- first implementation here +LL | struct W(A); +LL | impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<_>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0119, E0261. +For more information about an error, try `rustc --explain E0119`. From 0115f73fd15dda8735c615ec3fcbb3663cd84565 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 23 Mar 2024 04:54:00 +0000 Subject: [PATCH 22/36] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 78a07cd99a04c..9b89f016a7702 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -1447f9d38ca388ca178a544534b3cff72945fa1e +c3b05c6e5b5b59613350b8c2875b0add67ed74df From 5039f8b1e98720893bc2e32912e8d0535587c9e9 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 23 Mar 2024 05:03:40 +0000 Subject: [PATCH 23/36] fmt --- src/tools/miri/src/machine.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 29315c4933cdd..89bfbe8afa110 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -372,10 +372,8 @@ pub struct PrimitiveLayouts<'tcx> { impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> { fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result> { let tcx = layout_cx.tcx; - let mut_raw_ptr = - Ty::new_mut_ptr(tcx, tcx.types.unit); - let const_raw_ptr = - Ty::new_imm_ptr(tcx, tcx.types.unit); + let mut_raw_ptr = Ty::new_mut_ptr(tcx, tcx.types.unit); + let const_raw_ptr = Ty::new_imm_ptr(tcx, tcx.types.unit); Ok(Self { unit: layout_cx.layout_of(Ty::new_unit(tcx))?, i8: layout_cx.layout_of(tcx.types.i8)?, From d7eeb719542d77cb070f9d010a690da94485cb5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 22 Mar 2024 19:21:50 +0100 Subject: [PATCH 24/36] add issue numbers via // issue: rust-lang/rust#ISSUE_NUM directive --- ...uilding-vtable-representation-ice-90691.rs | 1 + .../failed-to-normalize-ice-issue-88421.rs | 2 +- .../ice-bad-input-type-for-cast-83056.rs | 1 + .../ice-bad-input-type-for-cast-83056.stderr | 2 +- .../extern-C-non-FFI-safe-arg-ice-52334.rs | 2 +- tests/ui/extern/extern-C-str-arg-ice-80125.rs | 2 +- ...-infinite-global-import-cycle-ice-64784.rs | 1 + ...ck-overflow-trait-infer-98842.32bit.stderr | 25 +++++++++++++++++++ ...ck-overflow-trait-infer-98842.64bit.stderr | 25 +++++++++++++++++++ .../sized/stack-overflow-trait-infer-98842.rs | 5 +++- .../stack-overflow-trait-infer-98842.stderr | 4 +-- ...nd_align_of-closure-not-supported-88212.rs | 2 +- 12 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr create mode 100644 tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr diff --git a/tests/ui/associated-type-bounds/resolution-failure-building-vtable-representation-ice-90691.rs b/tests/ui/associated-type-bounds/resolution-failure-building-vtable-representation-ice-90691.rs index 33776809a7912..d3c13974127cb 100644 --- a/tests/ui/associated-type-bounds/resolution-failure-building-vtable-representation-ice-90691.rs +++ b/tests/ui/associated-type-bounds/resolution-failure-building-vtable-representation-ice-90691.rs @@ -1,5 +1,6 @@ // ICE #90691 Encountered error `Unimplemented` selecting ... //@ build-pass +// issue: rust-lang/rust#90691 trait TError: std::fmt::Debug {} impl TError for () {} diff --git a/tests/ui/const-generics/generic_const_exprs/failed-to-normalize-ice-issue-88421.rs b/tests/ui/const-generics/generic_const_exprs/failed-to-normalize-ice-issue-88421.rs index 2ea7394fb72a5..3d41eeeff45cd 100644 --- a/tests/ui/const-generics/generic_const_exprs/failed-to-normalize-ice-issue-88421.rs +++ b/tests/ui/const-generics/generic_const_exprs/failed-to-normalize-ice-issue-88421.rs @@ -1,5 +1,5 @@ //@ check-pass - +// issue: rust-lang/rust#88421 #![feature(adt_const_params)] #![feature(generic_const_exprs)] #![allow(incomplete_features)] diff --git a/tests/ui/consts/ice-bad-input-type-for-cast-83056.rs b/tests/ui/consts/ice-bad-input-type-for-cast-83056.rs index ea0aba2c91160..1a22dc2b5495a 100644 --- a/tests/ui/consts/ice-bad-input-type-for-cast-83056.rs +++ b/tests/ui/consts/ice-bad-input-type-for-cast-83056.rs @@ -1,4 +1,5 @@ // #83056 ICE "bad input type for cast" +// issue: rust-lang/rust#83056 struct S([bool; f as usize]); fn f() -> T {} diff --git a/tests/ui/consts/ice-bad-input-type-for-cast-83056.stderr b/tests/ui/consts/ice-bad-input-type-for-cast-83056.stderr index 4764f49cf464a..115f168852058 100644 --- a/tests/ui/consts/ice-bad-input-type-for-cast-83056.stderr +++ b/tests/ui/consts/ice-bad-input-type-for-cast-83056.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `T` in this scope - --> $DIR/ice-bad-input-type-for-cast-83056.rs:4:11 + --> $DIR/ice-bad-input-type-for-cast-83056.rs:5:11 | LL | struct S([bool; f as usize]); | ----------------------------- similarly named struct `S` defined here diff --git a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.rs b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.rs index 3f515ea890935..fb4e3a95c2a2e 100644 --- a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.rs +++ b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.rs @@ -1,6 +1,6 @@ // test for #52334 ICE when casting extern "C" fn when it has a non-FFI-safe argument //@ check-pass - +// issue: rust-lang/rust#52334 type Foo = extern "C" fn(::std::ffi::CStr); //~^ WARN `extern` fn uses type `[i8]`, which is not FFI-safe extern "C" { diff --git a/tests/ui/extern/extern-C-str-arg-ice-80125.rs b/tests/ui/extern/extern-C-str-arg-ice-80125.rs index 71098fed2efad..0908d6199efb8 100644 --- a/tests/ui/extern/extern-C-str-arg-ice-80125.rs +++ b/tests/ui/extern/extern-C-str-arg-ice-80125.rs @@ -1,4 +1,4 @@ -// test for #80125 +// issue: rust-lang/rust#80125 //@ check-pass type ExternCallback = extern "C" fn(*const u8, u32, str); //~^ WARN `extern` fn uses type `str`, which is not FFI-safe diff --git a/tests/ui/privacy/decl-macro-infinite-global-import-cycle-ice-64784.rs b/tests/ui/privacy/decl-macro-infinite-global-import-cycle-ice-64784.rs index da7c5442d36da..72b1ea7ccc8ba 100644 --- a/tests/ui/privacy/decl-macro-infinite-global-import-cycle-ice-64784.rs +++ b/tests/ui/privacy/decl-macro-infinite-global-import-cycle-ice-64784.rs @@ -1,5 +1,6 @@ // ICE #64784 already borrowed: BorrowMutError //@ check-pass +// issue: rust-lang/rust#64784 #![feature(decl_macro)] pub macro m($i:ident, $j:ident) { diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr new file mode 100644 index 0000000000000..3f8011d961ae7 --- /dev/null +++ b/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr @@ -0,0 +1,25 @@ +error[E0391]: cycle detected when computing layout of `Foo` + | + = note: ...which requires computing layout of `<&'static Foo as core::ops::deref::Deref>::Target`... + = note: ...which again requires computing layout of `Foo`, completing the cycle +note: cycle used when const-evaluating + checking `_` + --> $DIR/stack-overflow-trait-infer-98842.rs:15:1 + | +LL | const _: *const Foo = 0 as _; + | ^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0080]: it is undefined behavior to use this value + --> $DIR/stack-overflow-trait-infer-98842.rs:15:1 + | +LL | const _: *const Foo = 0 as _; + | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation + | + = note: the raw bytes of the constant (size: 4, align: 4) { + 00 00 00 00 │ .... + } + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0080, E0391. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr new file mode 100644 index 0000000000000..04e2c4483bf64 --- /dev/null +++ b/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr @@ -0,0 +1,25 @@ +error[E0391]: cycle detected when computing layout of `Foo` + | + = note: ...which requires computing layout of `<&'static Foo as core::ops::deref::Deref>::Target`... + = note: ...which again requires computing layout of `Foo`, completing the cycle +note: cycle used when const-evaluating + checking `_` + --> $DIR/stack-overflow-trait-infer-98842.rs:15:1 + | +LL | const _: *const Foo = 0 as _; + | ^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0080]: it is undefined behavior to use this value + --> $DIR/stack-overflow-trait-infer-98842.rs:15:1 + | +LL | const _: *const Foo = 0 as _; + | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation + | + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0080, E0391. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.rs b/tests/ui/sized/stack-overflow-trait-infer-98842.rs index 2bba0777be49f..54d50346cc831 100644 --- a/tests/ui/sized/stack-overflow-trait-infer-98842.rs +++ b/tests/ui/sized/stack-overflow-trait-infer-98842.rs @@ -1,7 +1,10 @@ // #98842 stack overflow in trait inference +// issue: rust-lang/rust#98842 //@ check-fail //@ edition:2021 -//~^^^ ERROR cycle detected when computing layout of `Foo` +//@ stderr-per-bitwidth +//@ ignore-endian-big +//~^^^^^^ ERROR cycle detected when computing layout of `Foo` // If the inner `Foo` is named through an associated type, // the "infinite size" error does not occur. diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.stderr index 42b2718e33246..8ddddeb5bf2d1 100644 --- a/tests/ui/sized/stack-overflow-trait-infer-98842.stderr +++ b/tests/ui/sized/stack-overflow-trait-infer-98842.stderr @@ -3,14 +3,14 @@ error[E0391]: cycle detected when computing layout of `Foo` = note: ...which requires computing layout of `<&'static Foo as core::ops::deref::Deref>::Target`... = note: ...which again requires computing layout of `Foo`, completing the cycle note: cycle used when const-evaluating + checking `_` - --> $DIR/stack-overflow-trait-infer-98842.rs:12:1 + --> $DIR/stack-overflow-trait-infer-98842.rs:13:1 | LL | const _: *const Foo = 0 as _; | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0080]: it is undefined behavior to use this value - --> $DIR/stack-overflow-trait-infer-98842.rs:12:1 + --> $DIR/stack-overflow-trait-infer-98842.rs:13:1 | LL | const _: *const Foo = 0 as _; | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation diff --git a/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs b/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs index 1c43e3a448976..ec475673d0d84 100644 --- a/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs +++ b/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs @@ -1,5 +1,5 @@ // ICE size_and_align_of::<[closure@test.rs:15:5: 17:7]> not supported #88212 - +// issue: rust-lang/rust#88212 #![feature(unsized_locals)] //~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes From c87ec61a42345b2260ac52902b4544fbb57f99e3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 23 Mar 2024 11:32:36 +0100 Subject: [PATCH 25/36] add support for missing SIMD float intrinsics --- src/tools/miri/src/shims/intrinsics/simd.rs | 44 +++++++++++++++++---- src/tools/miri/tests/pass/portable-simd.rs | 18 +++++++++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index c97a052f51715..af98b38af8c96 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -33,6 +33,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | "round" | "trunc" | "fsqrt" + | "fsin" + | "fcos" + | "fexp" + | "fexp2" + | "flog" + | "flog2" + | "flog10" | "ctlz" | "cttz" | "bswap" @@ -45,17 +52,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { assert_eq!(dest_len, op_len); #[derive(Copy, Clone)] - enum Op { + enum Op<'a> { MirOp(mir::UnOp), Abs, - Sqrt, Round(rustc_apfloat::Round), Numeric(Symbol), + HostOp(&'a str), } let which = match intrinsic_name { "neg" => Op::MirOp(mir::UnOp::Neg), "fabs" => Op::Abs, - "fsqrt" => Op::Sqrt, "ceil" => Op::Round(rustc_apfloat::Round::TowardPositive), "floor" => Op::Round(rustc_apfloat::Round::TowardNegative), "round" => Op::Round(rustc_apfloat::Round::NearestTiesToAway), @@ -64,7 +70,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "cttz" => Op::Numeric(sym::cttz), "bswap" => Op::Numeric(sym::bswap), "bitreverse" => Op::Numeric(sym::bitreverse), - _ => unreachable!(), + _ => Op::HostOp(intrinsic_name), }; for i in 0..dest_len { @@ -89,7 +95,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { FloatTy::F128 => unimplemented!("f16_f128"), } } - Op::Sqrt => { + Op::HostOp(host_op) => { let ty::Float(float_ty) = op.layout.ty.kind() else { span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name) }; @@ -98,13 +104,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { FloatTy::F16 => unimplemented!("f16_f128"), FloatTy::F32 => { let f = op.to_scalar().to_f32()?; - let res = f.to_host().sqrt().to_soft(); + let f_host = f.to_host(); + let res = match host_op { + "fsqrt" => f_host.sqrt(), + "fsin" => f_host.sin(), + "fcos" => f_host.cos(), + "fexp" => f_host.exp(), + "fexp2" => f_host.exp2(), + "flog" => f_host.ln(), + "flog2" => f_host.log2(), + "flog10" => f_host.log10(), + _ => bug!(), + }; + let res = res.to_soft(); let res = this.adjust_nan(res, &[f]); Scalar::from(res) } FloatTy::F64 => { let f = op.to_scalar().to_f64()?; - let res = f.to_host().sqrt().to_soft(); + let f_host = f.to_host(); + let res = match host_op { + "fsqrt" => f_host.sqrt(), + "fsin" => f_host.sin(), + "fcos" => f_host.cos(), + "fexp" => f_host.exp(), + "fexp2" => f_host.exp2(), + "flog" => f_host.ln(), + "flog2" => f_host.log2(), + "flog10" => f_host.log10(), + _ => bug!(), + }; + let res = res.to_soft(); let res = this.adjust_nan(res, &[f]); Scalar::from(res) } diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/portable-simd.rs index 399913a757bb3..cdb441b450b36 100644 --- a/src/tools/miri/tests/pass/portable-simd.rs +++ b/src/tools/miri/tests/pass/portable-simd.rs @@ -526,6 +526,23 @@ fn simd_intrinsics() { } } +fn simd_float_intrinsics() { + use intrinsics::*; + + // These are just smoke tests to ensure the intrinsics can be called. + unsafe { + let a = f32x4::splat(10.0); + simd_fsqrt(a); + simd_fsin(a); + simd_fcos(a); + simd_fexp(a); + simd_fexp2(a); + simd_flog(a); + simd_flog2(a); + simd_flog10(a); + } +} + fn simd_masked_loadstore() { // The buffer is deliberarely too short, so reading the last element would be UB. let buf = [3i32; 3]; @@ -559,5 +576,6 @@ fn main() { simd_gather_scatter(); simd_round(); simd_intrinsics(); + simd_float_intrinsics(); simd_masked_loadstore(); } From 12e362989b59469f8bbabe6b93f787b8127609a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 23 Mar 2024 11:57:26 +0100 Subject: [PATCH 26/36] add test for #99945 Fixes #99945 --- .../failed-to-normalize-ice-99945.rs | 36 +++++++++++++++++++ .../failed-to-normalize-ice-99945.stderr | 25 +++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs create mode 100644 tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr diff --git a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs new file mode 100644 index 0000000000000..023991c29d090 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs @@ -0,0 +1,36 @@ +// issue: rust-lang/rust#99945 +// ICE Failed to normalize + +#![feature(type_alias_impl_trait)] + +trait Widget { + type State; + + fn make_state(&self) -> Self::State; +} + +impl Widget for () { + type State = (); + + fn make_state(&self) -> Self::State {} +} + +struct StatefulWidget(F); + +type StateWidget<'a> = impl Widget<&'a ()>; + +impl Fn(&'a ()) -> StateWidget<'a>> Widget<()> for StatefulWidget { + type State = (); + + fn make_state(&self) -> Self::State {} +} + +fn new_stateful_widget Fn(&'a ()) -> StateWidget<'a>>(build: F) -> impl Widget<()> { + StatefulWidget(build) + //~^ ERROR expected generic lifetime parameter, found `'a` +} + +fn main() { + new_stateful_widget(|_| ()).make_state(); + //~^ ERROR mismatched types +} diff --git a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr new file mode 100644 index 0000000000000..0c76feae198ba --- /dev/null +++ b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/failed-to-normalize-ice-99945.rs:34:29 + | +LL | type StateWidget<'a> = impl Widget<&'a ()>; + | ------------------- the expected opaque type +... +LL | new_stateful_widget(|_| ()).make_state(); + | ^^ expected opaque type, found `()` + | + = note: expected opaque type `StateWidget<'_>` + found unit type `()` + +error[E0792]: expected generic lifetime parameter, found `'a` + --> $DIR/failed-to-normalize-ice-99945.rs:29:5 + | +LL | type StateWidget<'a> = impl Widget<&'a ()>; + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | StatefulWidget(build) + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0792. +For more information about an error, try `rustc --explain E0308`. From 2f9a240b91f766f158b652f537b828c9909bfdd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 23 Mar 2024 12:01:39 +0100 Subject: [PATCH 27/36] add test for opaque type with non-universal region substs #101852 Fixes #101852 --- tests/ui/impl-trait/recursive-ice-101862.rs | 12 ++++++++++ .../ui/impl-trait/recursive-ice-101862.stderr | 24 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/ui/impl-trait/recursive-ice-101862.rs create mode 100644 tests/ui/impl-trait/recursive-ice-101862.stderr diff --git a/tests/ui/impl-trait/recursive-ice-101862.rs b/tests/ui/impl-trait/recursive-ice-101862.rs new file mode 100644 index 0000000000000..02f95fe5604b2 --- /dev/null +++ b/tests/ui/impl-trait/recursive-ice-101862.rs @@ -0,0 +1,12 @@ +// issue: rust-lang/rust#101852 +// ICE opaque type with non-universal region substs + +pub fn ice(x: impl AsRef) -> impl IntoIterator { +//~^ WARN function cannot return without recursing + vec![].append(&mut ice(x.as_ref())); + //~^ ERROR expected generic type parameter, found `&str` + + Vec::new() +} + +fn main() {} diff --git a/tests/ui/impl-trait/recursive-ice-101862.stderr b/tests/ui/impl-trait/recursive-ice-101862.stderr new file mode 100644 index 0000000000000..f4148720c3331 --- /dev/null +++ b/tests/ui/impl-trait/recursive-ice-101862.stderr @@ -0,0 +1,24 @@ +warning: function cannot return without recursing + --> $DIR/recursive-ice-101862.rs:4:1 + | +LL | pub fn ice(x: impl AsRef) -> impl IntoIterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | vec![].append(&mut ice(x.as_ref())); + | --------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0792]: expected generic type parameter, found `&str` + --> $DIR/recursive-ice-101862.rs:6:5 + | +LL | pub fn ice(x: impl AsRef) -> impl IntoIterator { + | --------------- this generic parameter must be used with a generic type parameter +LL | +LL | vec![].append(&mut ice(x.as_ref())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0792`. From e54bff71091e7c3a16c96e2f79328eb73815d7cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 23 Mar 2024 12:19:05 +0100 Subject: [PATCH 28/36] add test for #104779 opaque types, patterns and subtyping ICE: IndexMap: key not found Fixes #104779 --- ...que-types-patterns-subtyping-ice-104779.rs | 26 ++++++++++++ ...types-patterns-subtyping-ice-104779.stderr | 42 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs create mode 100644 tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.stderr diff --git a/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs new file mode 100644 index 0000000000000..b9e729bff62a0 --- /dev/null +++ b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs @@ -0,0 +1,26 @@ +// issue: rust-lang/rust#104779 +// ICE region infer, IndexMap: key not found + +struct Inv<'a>(&'a mut &'a ()); +enum Foo { + Bar, + Var(T), +} +type Subtype = Foo fn(Inv<'a>, Inv<'b>)>; +type Supertype = Foo fn(Inv<'a>, Inv<'a>)>; + +fn foo() -> impl Sized { +//~^ WARN function cannot return without recursing + loop { + match foo() { + //~^ ERROR higher-ranked subtype error + //~^^ ERROR higher-ranked subtype error + Subtype::Bar => (), + //~^ ERROR higher-ranked subtype error + //~^^ ERROR higher-ranked subtype error + Supertype::Var(x) => {} + } + } +} + +pub fn main() {} diff --git a/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.stderr b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.stderr new file mode 100644 index 0000000000000..887cb14a76935 --- /dev/null +++ b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.stderr @@ -0,0 +1,42 @@ +warning: function cannot return without recursing + --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:12:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | match foo() { + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: higher-ranked subtype error + --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:15:15 + | +LL | match foo() { + | ^^^^^ + +error: higher-ranked subtype error + --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:15:15 + | +LL | match foo() { + | ^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: higher-ranked subtype error + --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:18:13 + | +LL | Subtype::Bar => (), + | ^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:18:13 + | +LL | Subtype::Bar => (), + | ^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors; 1 warning emitted + From f1f287fadb91451b116ff00a2f8b9c32c5e1571b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 23 Mar 2024 12:24:40 +0100 Subject: [PATCH 29/36] add test for ICE "raw ptr comparison should already be caught in the trait system" #105047 Fixes #105047 --- .../const-eval-compare-ice-105047.rs | 15 +++++++++ .../const-eval-compare-ice-105047.stderr | 31 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs create mode 100644 tests/ui/raw-ref-op/const-eval-compare-ice-105047.stderr diff --git a/tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs b/tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs new file mode 100644 index 0000000000000..0a736a5a8e21b --- /dev/null +++ b/tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs @@ -0,0 +1,15 @@ +// issue: rust-lang/rust#105047 +// ICE raw ptr comparison should already be caught in the trait systems + +#![feature(raw_ref_op)] + +const RCZ: *const i32 = &raw const *&0; + +const fn f() { + if let RCZ = &raw const *&0 { } + //~^ WARN function pointers and raw pointers not derived from integers in patterns + //~^^ ERROR pointers cannot be reliably compared during const eval + //~^^^ WARN this was previously accepted by the compiler but is being phased out +} + +fn main() {} diff --git a/tests/ui/raw-ref-op/const-eval-compare-ice-105047.stderr b/tests/ui/raw-ref-op/const-eval-compare-ice-105047.stderr new file mode 100644 index 0000000000000..9c472cda2442c --- /dev/null +++ b/tests/ui/raw-ref-op/const-eval-compare-ice-105047.stderr @@ -0,0 +1,31 @@ +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/const-eval-compare-ice-105047.rs:9:12 + | +LL | if let RCZ = &raw const *&0 { } + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +error: pointers cannot be reliably compared during const eval + --> $DIR/const-eval-compare-ice-105047.rs:9:12 + | +LL | if let RCZ = &raw const *&0 { } + | ^^^ + | + = note: see issue #53020 for more information + +error: aborting due to 1 previous error; 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/const-eval-compare-ice-105047.rs:9:12 + | +LL | if let RCZ = &raw const *&0 { } + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + From f8aeac8a3692b1a02002a1293c231de73149e676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 23 Mar 2024 12:32:32 +0100 Subject: [PATCH 30/36] add test for #106423 Fixes #106423 --- .../poly-const-uneval-ice-106423.rs | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/ui/const-generics/generic_const_exprs/poly-const-uneval-ice-106423.rs diff --git a/tests/ui/const-generics/generic_const_exprs/poly-const-uneval-ice-106423.rs b/tests/ui/const-generics/generic_const_exprs/poly-const-uneval-ice-106423.rs new file mode 100644 index 0000000000000..ed5ba32b62105 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/poly-const-uneval-ice-106423.rs @@ -0,0 +1,57 @@ +// issue: rust-lang/rust#106423 +// ICE collection encountered polymorphic constant: UnevaluatedConst {..} +//@ edition:2021 +//@ check-pass + +#![feature(generic_const_exprs, generic_arg_infer)] +#![allow(incomplete_features)] +#![allow(unused)] + +use core::mem::MaybeUninit; + +pub struct Arr { + v: [MaybeUninit; N], +} + +impl Arr { + const ELEM: MaybeUninit = MaybeUninit::uninit(); + const INIT: [MaybeUninit; N] = [Self::ELEM; N]; // important for optimization of `new` + + fn new() -> Self { + Arr { v: Self::INIT } + } +} + +pub struct BaFormatFilter {} + +pub enum DigitalFilter +where + [(); N * 2 + 1]: Sized, + [(); N * 2]: Sized, +{ + Ba(BaFormatFilter<{ N * 2 + 1 }>), +} + +pub fn iirfilter_st_copy(_: [f32; M]) -> DigitalFilter +where + [(); N * 2 + 1]: Sized, + [(); N * 2]: Sized, +{ + let zpk = zpk2tf_st(&Arr::::new(), &Arr::::new()); + DigitalFilter::Ba(zpk) +} + +pub fn zpk2tf_st( + _z: &Arr, + _p: &Arr, +) -> BaFormatFilter<{ N + 1 }> +where + [(); N + 1]: Sized, +{ + BaFormatFilter {} +} + + +fn main() { + iirfilter_st_copy::<4, 2>([10., 50.,]); +} From cc422cee97e53195ac75b25d221f192b6a3a200b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 23 Mar 2024 12:38:50 +0100 Subject: [PATCH 31/36] add test for ICE #106444 Fixes #106444 --- tests/ui/drop/norm-ice-106444.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/ui/drop/norm-ice-106444.rs diff --git a/tests/ui/drop/norm-ice-106444.rs b/tests/ui/drop/norm-ice-106444.rs new file mode 100644 index 0000000000000..b248bc73bbefa --- /dev/null +++ b/tests/ui/drop/norm-ice-106444.rs @@ -0,0 +1,16 @@ +// issue: rust-lang/rust#106444 +// ICE failed to normalize +//@ compile-flags: -Zmir-opt-level=3 +//@ check-pass + +#![crate_type="lib"] + +pub trait A { + type B; +} + +pub struct S(T::B); + +pub fn foo(p: *mut S) { + unsafe { core::ptr::drop_in_place(p) }; +} From f2bc9c5997a3647a61cfb5045866314088c6befa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 23 Mar 2024 12:50:21 +0100 Subject: [PATCH 32/36] add test for #106874 ICE BoundUniversalRegionError Fixes #106874 --- tests/ui/nll/ice-106874.rs | 48 ++++++++++++++++++ tests/ui/nll/ice-106874.stderr | 90 ++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 tests/ui/nll/ice-106874.rs create mode 100644 tests/ui/nll/ice-106874.stderr diff --git a/tests/ui/nll/ice-106874.rs b/tests/ui/nll/ice-106874.rs new file mode 100644 index 0000000000000..77a91d6d823a2 --- /dev/null +++ b/tests/ui/nll/ice-106874.rs @@ -0,0 +1,48 @@ +// issue: rust-lang/rust#106874 +// ICE BoundUniversalRegionError + +use std::marker::PhantomData; +use std::rc::Rc; + +pub fn func(f: F) -> A { + A(B(C::new(D::new(move |st| f(st))))) + //~^ ERROR implementation of `FnOnce` is not general enough + //~^^ ERROR implementation of `Fn` is not general enough + //~^^^ ERROR implementation of `FnOnce` is not general enough + //~^^^^ ERROR implementation of `FnOnce` is not general enough + //~^^^^^ ERROR implementation of `Fn` is not general enough + //~^^^^^^ ERROR implementation of `FnOnce` is not general enough + //~^^^^^^^ ERROR implementation of `Fn` is not general enough + //~^^^^^^^^ ERROR implementation of `FnOnce` is not general enough + //~^^^^^^^^^ ERROR higher-ranked subtype error + //~^^^^^^^^^^ ERROR higher-ranked subtype error +} + +trait X {} +trait Y { + type V; +} + +struct A(T); + +struct B(Rc); +impl X for B {} + +struct C(T::V); +impl C { + fn new(_: T) -> Rc { + todo!() + } +} +struct D(F, PhantomData); + +impl D { + fn new(_: F) -> Self { + todo!() + } +} +impl Y for D { + type V = V; +} + +pub fn main() {} diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr new file mode 100644 index 0000000000000..ead4d490a6248 --- /dev/null +++ b/tests/ui/nll/ice-106874.stderr @@ -0,0 +1,90 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/ice-106874.rs:8:5 + | +LL | A(B(C::new(D::new(move |st| f(st))))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` + +error: implementation of `FnOnce` is not general enough + --> $DIR/ice-106874.rs:8:5 + | +LL | A(B(C::new(D::new(move |st| f(st))))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `Fn` is not general enough + --> $DIR/ice-106874.rs:8:7 + | +LL | A(B(C::new(D::new(move |st| f(st))))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough + | + = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` + +error: implementation of `FnOnce` is not general enough + --> $DIR/ice-106874.rs:8:7 + | +LL | A(B(C::new(D::new(move |st| f(st))))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` + +error: implementation of `Fn` is not general enough + --> $DIR/ice-106874.rs:8:7 + | +LL | A(B(C::new(D::new(move |st| f(st))))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough + | + = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `FnOnce` is not general enough + --> $DIR/ice-106874.rs:8:9 + | +LL | A(B(C::new(D::new(move |st| f(st))))) + | ^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` + +error: implementation of `Fn` is not general enough + --> $DIR/ice-106874.rs:8:9 + | +LL | A(B(C::new(D::new(move |st| f(st))))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough + | + = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` + +error: implementation of `FnOnce` is not general enough + --> $DIR/ice-106874.rs:8:9 + | +LL | A(B(C::new(D::new(move |st| f(st))))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` + +error: higher-ranked subtype error + --> $DIR/ice-106874.rs:8:41 + | +LL | A(B(C::new(D::new(move |st| f(st))))) + | ^ + +error: higher-ranked subtype error + --> $DIR/ice-106874.rs:8:41 + | +LL | A(B(C::new(D::new(move |st| f(st))))) + | ^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 10 previous errors + From 368bfb2c10541129f9e6af98d88125d9bfc77820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 23 Mar 2024 13:05:22 +0100 Subject: [PATCH 33/36] add test for #107228 Fixes #107228 --- .../broken-mir-drop-glue-107228.rs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/ui/specialization/broken-mir-drop-glue-107228.rs diff --git a/tests/ui/specialization/broken-mir-drop-glue-107228.rs b/tests/ui/specialization/broken-mir-drop-glue-107228.rs new file mode 100644 index 0000000000000..5a6dbf9ffc761 --- /dev/null +++ b/tests/ui/specialization/broken-mir-drop-glue-107228.rs @@ -0,0 +1,28 @@ +// issue: rust-lang/rust#107228 +// ICE broken MIR in DropGlue +//@ compile-flags: -Zvalidate-mir +//@ check-pass + +#![feature(specialization)] +#![crate_type="lib"] +#![allow(incomplete_features)] + +pub(crate) trait SpecTrait { + type Assoc; +} + +impl SpecTrait for C { + default type Assoc = Vec; +} + +pub(crate) struct AssocWrap { + _assoc: C::Assoc, +} + +fn instantiate() -> AssocWrap { + loop {} +} + +pub fn main() { + instantiate::<()>(); +} From 2d610f74731b667695e0baa1357857c09915ea4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 17 Mar 2024 09:59:43 +0100 Subject: [PATCH 34/36] Report retags as distinct from real memory accesses for data races --- .../src/borrow_tracker/stacked_borrows/mod.rs | 17 ++- .../src/borrow_tracker/tree_borrows/mod.rs | 13 +- src/tools/miri/src/concurrency/data_race.rs | 141 ++++++++++-------- .../miri/src/concurrency/vector_clock.rs | 62 +++++++- src/tools/miri/src/diagnostics.rs | 8 +- src/tools/miri/src/lib.rs | 1 + src/tools/miri/src/machine.rs | 15 +- .../both_borrows/retag_data_race_write.rs | 2 +- .../retag_data_race_write.stack.stderr | 7 +- .../retag_data_race_write.tree.stderr | 7 +- .../retag_data_race_protected_read.rs | 2 +- .../retag_data_race_protected_read.stderr | 7 +- .../stacked_borrows/retag_data_race_read.rs | 2 +- .../retag_data_race_read.stderr | 7 +- 14 files changed, 202 insertions(+), 89 deletions(-) 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 9130601bbddb9..96d631b1e14d8 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -18,6 +18,7 @@ use crate::borrow_tracker::{ stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder}, GlobalStateInner, ProtectorKind, }; +use crate::concurrency::data_race::{NaReadType, NaWriteType}; use crate::*; use diagnostics::{RetagCause, RetagInfo}; @@ -751,7 +752,13 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' assert_eq!(access, AccessKind::Write); // Make sure the data race model also knows about this. if let Some(data_race) = alloc_extra.data_race.as_mut() { - data_race.write(alloc_id, range, machine)?; + data_race.write( + alloc_id, + range, + NaWriteType::Retag, + Some(place.layout.ty), + machine, + )?; } } } @@ -794,7 +801,13 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' assert_eq!(access, AccessKind::Read); // Make sure the data race model also knows about this. if let Some(data_race) = alloc_extra.data_race.as_ref() { - data_race.read(alloc_id, range, &this.machine)?; + data_race.read( + alloc_id, + range, + NaReadType::Retag, + Some(place.layout.ty), + &this.machine, + )?; } } Ok(()) diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 9eb78b08ef77d..051639350004a 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -9,8 +9,11 @@ use rustc_middle::{ use rustc_span::def_id::DefId; use rustc_target::abi::{Abi, Size}; -use crate::borrow_tracker::{GlobalState, GlobalStateInner, ProtectorKind}; use crate::*; +use crate::{ + borrow_tracker::{GlobalState, GlobalStateInner, ProtectorKind}, + concurrency::data_race::NaReadType, +}; pub mod diagnostics; mod perms; @@ -312,7 +315,13 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' // Also inform the data race model (but only if any bytes are actually affected). if range.size.bytes() > 0 { if let Some(data_race) = alloc_extra.data_race.as_ref() { - data_race.read(alloc_id, range, &this.machine)?; + data_race.read( + alloc_id, + range, + NaReadType::Retag, + Some(place.layout.ty), + &this.machine, + )?; } } diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 127d97bd5af1f..d51160b2831dd 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -49,7 +49,7 @@ use std::{ use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::{Idx, IndexVec}; -use rustc_middle::mir; +use rustc_middle::{mir, ty::Ty}; use rustc_span::Span; use rustc_target::abi::{Align, HasDataLayout, Size}; @@ -200,18 +200,38 @@ enum AtomicAccessType { Rmw, } -/// Type of write operation: allocating memory -/// non-atomic writes and deallocating memory -/// are all treated as writes for the purpose -/// of the data-race detector. +/// Type of a non-atomic read operation. #[derive(Copy, Clone, PartialEq, Eq, Debug)] -enum NaWriteType { +pub enum NaReadType { + /// Standard unsynchronized write. + Read, + + // An implicit read generated by a retag. + Retag, +} + +impl NaReadType { + fn description(self) -> &'static str { + match self { + NaReadType::Read => "non-atomic read", + NaReadType::Retag => "retag read", + } + } +} + +/// Type of a non-atomic write operation: allocating memory, non-atomic writes, and +/// deallocating memory are all treated as writes for the purpose of the data-race detector. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum NaWriteType { /// Allocate memory. Allocate, /// Standard unsynchronized write. Write, + // An implicit write generated by a retag. + Retag, + /// Deallocate memory. /// Note that when memory is deallocated first, later non-atomic accesses /// will be reported as use-after-free, not as data races. @@ -224,6 +244,7 @@ impl NaWriteType { match self { NaWriteType::Allocate => "creating a new allocation", NaWriteType::Write => "non-atomic write", + NaWriteType::Retag => "retag write", NaWriteType::Deallocate => "deallocation", } } @@ -231,7 +252,7 @@ impl NaWriteType { #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum AccessType { - NaRead, + NaRead(NaReadType), NaWrite(NaWriteType), AtomicLoad, AtomicStore, @@ -239,29 +260,48 @@ enum AccessType { } impl AccessType { - fn description(self) -> &'static str { - match self { - AccessType::NaRead => "non-atomic read", + fn description(self, ty: Option>, size: Option) -> String { + let mut msg = String::new(); + + if let Some(size) = size { + msg.push_str(&format!("{}-byte {}", size.bytes(), msg)) + } + + msg.push_str(match self { + AccessType::NaRead(w) => w.description(), AccessType::NaWrite(w) => w.description(), AccessType::AtomicLoad => "atomic load", AccessType::AtomicStore => "atomic store", AccessType::AtomicRmw => "atomic read-modify-write", + }); + + if let Some(ty) = ty { + msg.push_str(&format!(" of type `{}`", ty)); } + + msg } fn is_atomic(self) -> bool { match self { AccessType::AtomicLoad | AccessType::AtomicStore | AccessType::AtomicRmw => true, - AccessType::NaRead | AccessType::NaWrite(_) => false, + AccessType::NaRead(_) | AccessType::NaWrite(_) => false, } } fn is_read(self) -> bool { match self { - AccessType::AtomicLoad | AccessType::NaRead => true, + AccessType::AtomicLoad | AccessType::NaRead(_) => true, AccessType::NaWrite(_) | AccessType::AtomicStore | AccessType::AtomicRmw => false, } } + + fn is_retag(self) -> bool { + matches!( + self, + AccessType::NaRead(NaReadType::Retag) | AccessType::NaWrite(NaWriteType::Retag) + ) + } } /// Memory Cell vector clock metadata @@ -502,12 +542,14 @@ impl MemoryCellClocks { &mut self, thread_clocks: &mut ThreadClockSet, index: VectorIdx, + read_type: NaReadType, current_span: Span, ) -> Result<(), DataRace> { trace!("Unsynchronized read with vectors: {:#?} :: {:#?}", self, thread_clocks); if !current_span.is_dummy() { thread_clocks.clock[index].span = current_span; } + thread_clocks.clock[index].set_read_type(read_type); if self.write_was_before(&thread_clocks.clock) { let race_free = if let Some(atomic) = self.atomic() { // We must be ordered-after all atomic accesses, reads and writes. @@ -875,7 +917,8 @@ impl VClockAlloc { /// This finds the two racing threads and the type /// of data-race that occurred. This will also /// return info about the memory location the data-race - /// occurred in. + /// occurred in. The `ty` parameter is used for diagnostics, letting + /// the user know which type was involved in the access. #[cold] #[inline(never)] fn report_data_race<'tcx>( @@ -885,6 +928,7 @@ impl VClockAlloc { access: AccessType, access_size: Size, ptr_dbg: Pointer, + ty: Option>, ) -> InterpResult<'tcx> { let (current_index, current_clocks) = global.current_thread_state(thread_mgr); let mut other_size = None; // if `Some`, this was a size-mismatch race @@ -908,7 +952,7 @@ impl VClockAlloc { write_clock = mem_clocks.write(); (AccessType::NaWrite(mem_clocks.write_type), mem_clocks.write.0, &write_clock) } else if let Some(idx) = Self::find_gt_index(&mem_clocks.read, ¤t_clocks.clock) { - (AccessType::NaRead, idx, &mem_clocks.read) + (AccessType::NaRead(mem_clocks.read[idx].read_type()), idx, &mem_clocks.read) // Finally, mixed-size races. } else if access.is_atomic() && let Some(atomic) = mem_clocks.atomic() && atomic.size != access_size { // This is only a race if we are not synchronized with all atomic accesses, so find @@ -950,37 +994,33 @@ impl VClockAlloc { Err(err_machine_stop!(TerminationInfo::DataRace { involves_non_atomic, extra, + retag_explain: access.is_retag() || other_access.is_retag(), ptr: ptr_dbg, op1: RacingOp { - action: if let Some(other_size) = other_size { - format!("{}-byte {}", other_size.bytes(), other_access.description()) - } else { - other_access.description().to_owned() - }, + action: other_access.description(None, other_size), thread_info: other_thread_info, span: other_clock.as_slice()[other_thread.index()].span_data(), }, op2: RacingOp { - action: if other_size.is_some() { - format!("{}-byte {}", access_size.bytes(), access.description()) - } else { - access.description().to_owned() - }, + action: access.description(ty, other_size.map(|_| access_size)), thread_info: current_thread_info, span: current_clocks.clock.as_slice()[current_index.index()].span_data(), }, }))? } - /// Detect data-races for an unsynchronized read operation, will not perform + /// Detect data-races for an unsynchronized read operation. It will not perform /// data-race detection if `race_detecting()` is false, either due to no threads /// being created or if it is temporarily disabled during a racy read or write /// operation for which data-race detection is handled separately, for example - /// atomic read operations. + /// atomic read operations. The `ty` parameter is used for diagnostics, letting + /// the user know which type was read. pub fn read<'tcx>( &self, alloc_id: AllocId, access_range: AllocRange, + read_type: NaReadType, + ty: Option>, machine: &MiriMachine<'_, '_>, ) -> InterpResult<'tcx> { let current_span = machine.current_span(); @@ -992,7 +1032,7 @@ impl VClockAlloc { alloc_ranges.iter_mut(access_range.start, access_range.size) { if let Err(DataRace) = - mem_clocks.read_race_detect(&mut thread_clocks, index, current_span) + mem_clocks.read_race_detect(&mut thread_clocks, index, read_type, current_span) { drop(thread_clocks); // Report data-race. @@ -1000,9 +1040,10 @@ impl VClockAlloc { global, &machine.threads, mem_clocks, - AccessType::NaRead, + AccessType::NaRead(read_type), access_range.size, Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)), + ty, ); } } @@ -1012,12 +1053,17 @@ impl VClockAlloc { } } - // Shared code for detecting data-races on unique access to a section of memory - fn unique_access<'tcx>( + /// Detect data-races for an unsynchronized write operation. It will not perform + /// data-race detection if `race_detecting()` is false, either due to no threads + /// being created or if it is temporarily disabled during a racy read or write + /// operation. The `ty` parameter is used for diagnostics, letting + /// the user know which type was written. + pub fn write<'tcx>( &mut self, alloc_id: AllocId, access_range: AllocRange, write_type: NaWriteType, + ty: Option>, machine: &mut MiriMachine<'_, '_>, ) -> InterpResult<'tcx> { let current_span = machine.current_span(); @@ -1042,6 +1088,7 @@ impl VClockAlloc { AccessType::NaWrite(write_type), access_range.size, Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)), + ty, ); } } @@ -1050,37 +1097,6 @@ impl VClockAlloc { Ok(()) } } - - /// Detect data-races for an unsynchronized write operation, will not perform - /// data-race threads if `race_detecting()` is false, either due to no threads - /// being created or if it is temporarily disabled during a racy read or write - /// operation - pub fn write<'tcx>( - &mut self, - alloc_id: AllocId, - range: AllocRange, - machine: &mut MiriMachine<'_, '_>, - ) -> InterpResult<'tcx> { - self.unique_access(alloc_id, range, NaWriteType::Write, machine) - } - - /// Detect data-races for an unsynchronized deallocate operation, will not perform - /// data-race threads if `race_detecting()` is false, either due to no threads - /// being created or if it is temporarily disabled during a racy read or write - /// operation - pub fn deallocate<'tcx>( - &mut self, - alloc_id: AllocId, - size: Size, - machine: &mut MiriMachine<'_, '_>, - ) -> InterpResult<'tcx> { - self.unique_access( - alloc_id, - alloc_range(Size::ZERO, size), - NaWriteType::Deallocate, - machine, - ) - } } impl<'mir, 'tcx: 'mir> EvalContextPrivExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> {} @@ -1279,7 +1295,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let alloc_meta = this.get_alloc_extra(alloc_id)?.data_race.as_ref().unwrap(); trace!( "Atomic op({}) with ordering {:?} on {:?} (size={})", - access.description(), + access.description(None, None), &atomic, place.ptr(), size.bytes() @@ -1307,6 +1323,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { alloc_id, Size::from_bytes(mem_clocks_range.start), ), + None, ) .map(|_| true); } diff --git a/src/tools/miri/src/concurrency/vector_clock.rs b/src/tools/miri/src/concurrency/vector_clock.rs index fa93c9e00b14a..fe719943dcb65 100644 --- a/src/tools/miri/src/concurrency/vector_clock.rs +++ b/src/tools/miri/src/concurrency/vector_clock.rs @@ -4,9 +4,11 @@ use smallvec::SmallVec; use std::{ cmp::Ordering, fmt::Debug, - ops::{Index, IndexMut}, + ops::{Index, IndexMut, Shr}, }; +use super::data_race::NaReadType; + /// A vector clock index, this is associated with a thread id /// but in some cases one vector index may be shared with /// multiple thread ids if it's safe to do so. @@ -50,13 +52,51 @@ const SMALL_VECTOR: usize = 4; /// so that diagnostics can report what code was responsible for an operation. #[derive(Clone, Copy, Debug)] pub struct VTimestamp { - time: u32, + /// The lowest bit indicates read type, the rest is the time. + /// `1` indicates a retag read, `0` a regular read. + time_and_read_type: u32, pub span: Span, } impl VTimestamp { - pub const ZERO: VTimestamp = VTimestamp { time: 0, span: DUMMY_SP }; + pub const ZERO: VTimestamp = VTimestamp::new(0, NaReadType::Read, DUMMY_SP); + + #[inline] + const fn encode_time_and_read_type(time: u32, read_type: NaReadType) -> u32 { + let read_type_bit = match read_type { + NaReadType::Read => 0, + NaReadType::Retag => 1, + }; + // Put the `read_type` in the lowest bit and `time` in the rest + read_type_bit | time.checked_mul(2).expect("Vector clock overflow") + } + + #[inline] + const fn new(time: u32, read_type: NaReadType, span: Span) -> Self { + Self { time_and_read_type: Self::encode_time_and_read_type(time, read_type), span } + } + + #[inline] + fn time(&self) -> u32 { + self.time_and_read_type.shr(1) + } + #[inline] + fn set_time(&mut self, time: u32) { + self.time_and_read_type = Self::encode_time_and_read_type(time, self.read_type()); + } + + #[inline] + pub fn read_type(&self) -> NaReadType { + if self.time_and_read_type & 1 == 0 { NaReadType::Read } else { NaReadType::Retag } + } + + #[inline] + pub fn set_read_type(&mut self, read_type: NaReadType) { + self.time_and_read_type = Self::encode_time_and_read_type(self.time(), read_type); + } + + #[inline] pub fn span_data(&self) -> SpanData { self.span.data() } @@ -64,7 +104,7 @@ impl VTimestamp { impl PartialEq for VTimestamp { fn eq(&self, other: &Self) -> bool { - self.time == other.time + self.time() == other.time() } } @@ -78,7 +118,7 @@ impl PartialOrd for VTimestamp { impl Ord for VTimestamp { fn cmp(&self, other: &Self) -> Ordering { - self.time.cmp(&other.time) + self.time().cmp(&other.time()) } } @@ -130,7 +170,7 @@ impl VClock { let idx = idx.index(); let mut_slice = self.get_mut_with_min_len(idx + 1); let idx_ref = &mut mut_slice[idx]; - idx_ref.time = idx_ref.time.checked_add(1).expect("Vector clock overflow"); + idx_ref.set_time(idx_ref.time().checked_add(1).expect("Vector clock overflow")); if !current_span.is_dummy() { idx_ref.span = current_span; } @@ -379,8 +419,8 @@ impl IndexMut for VClock { /// test suite #[cfg(test)] mod tests { - use super::{VClock, VTimestamp, VectorIdx}; + use crate::concurrency::data_race::NaReadType; use rustc_span::DUMMY_SP; use std::cmp::Ordering; @@ -448,7 +488,13 @@ mod tests { while let Some(0) = slice.last() { slice = &slice[..slice.len() - 1] } - VClock(slice.iter().copied().map(|time| VTimestamp { time, span: DUMMY_SP }).collect()) + VClock( + slice + .iter() + .copied() + .map(|time| VTimestamp::new(time, NaReadType::Read, DUMMY_SP)) + .collect(), + ) } fn assert_order(l: &[u32], r: &[u32], o: Option) { diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 03428b081c569..99d37065bace4 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -46,6 +46,7 @@ pub enum TerminationInfo { op1: RacingOp, op2: RacingOp, extra: Option<&'static str>, + retag_explain: bool, }, } @@ -263,12 +264,17 @@ pub fn report_error<'tcx, 'mir>( vec![(Some(*span), format!("the `{link_name}` symbol is defined here"))], Int2PtrWithStrictProvenance => vec![(None, format!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"))], - DataRace { op1, extra, .. } => { + DataRace { op1, extra, retag_explain, .. } => { let mut helps = vec![(Some(op1.span), format!("and (1) occurred earlier here"))]; if let Some(extra) = extra { helps.push((None, format!("{extra}"))); helps.push((None, format!("see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model"))); } + if *retag_explain { + helps.push((None, "retags occur on all (re)borrows and as well as when references are copied or moved".to_owned())); + helps.push((None, "retags permit optimizations that insert speculative reads or writes".to_owned())); + helps.push((None, "therefore from the perspective of data races, a retag has the same implications as a read or write".to_owned())); + } helps.push((None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"))); helps.push((None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"))); helps diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 416d0cda8f1ec..7821aa9efd4c1 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -1,5 +1,6 @@ #![feature(rustc_private)] #![feature(cell_update)] +#![feature(const_option)] #![feature(float_gamma)] #![feature(generic_nonzero)] #![feature(map_try_insert)] diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 7e5518392d8a7..71a4f2ca87ef6 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -36,6 +36,9 @@ use crate::{ *, }; +use self::concurrency::data_race::NaReadType; +use self::concurrency::data_race::NaWriteType; + /// First real-time signal. /// `signal(7)` says this must be between 32 and 64 and specifies 34 or 35 /// as typical values. @@ -1241,7 +1244,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { .emit_diagnostic(NonHaltingDiagnostic::AccessedAlloc(alloc_id, AccessKind::Read)); } if let Some(data_race) = &alloc_extra.data_race { - data_race.read(alloc_id, range, machine)?; + data_race.read(alloc_id, range, NaReadType::Read, None, machine)?; } if let Some(borrow_tracker) = &alloc_extra.borrow_tracker { borrow_tracker.before_memory_read(alloc_id, prov_extra, range, machine)?; @@ -1265,7 +1268,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { .emit_diagnostic(NonHaltingDiagnostic::AccessedAlloc(alloc_id, AccessKind::Write)); } if let Some(data_race) = &mut alloc_extra.data_race { - data_race.write(alloc_id, range, machine)?; + data_race.write(alloc_id, range, NaWriteType::Write, None, machine)?; } if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker { borrow_tracker.before_memory_write(alloc_id, prov_extra, range, machine)?; @@ -1289,7 +1292,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { machine.emit_diagnostic(NonHaltingDiagnostic::FreedAlloc(alloc_id)); } if let Some(data_race) = &mut alloc_extra.data_race { - data_race.deallocate(alloc_id, size, machine)?; + data_race.write( + alloc_id, + alloc_range(Size::ZERO, size), + NaWriteType::Deallocate, + None, + machine, + )?; } if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker { borrow_tracker.before_memory_deallocation(alloc_id, prove_extra, size, machine)?; diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.rs b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.rs index eb1fe56df0721..3edaf10f3dc69 100644 --- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.rs +++ b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.rs @@ -17,7 +17,7 @@ fn thread_1(p: SendPtr) { fn thread_2(p: SendPtr) { let p = p.0; unsafe { - *p = 5; //~ ERROR: /Data race detected between \(1\) non-atomic (read|write) on thread `unnamed-[0-9]+` and \(2\) non-atomic write on thread `unnamed-[0-9]+`/ + *p = 5; //~ ERROR: /Data race detected between \(1\) retag (read|write) on thread `unnamed-[0-9]+` and \(2\) non-atomic write on thread `unnamed-[0-9]+`/ } } diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr index c5b65e6f747fb..6f4b52fb88718 100644 --- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr @@ -1,14 +1,17 @@ -error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here +error: Undefined Behavior: Data race detected between (1) retag write on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here --> $DIR/retag_data_race_write.rs:LL:CC | LL | *p = 5; - | ^^^^^^ Data race detected between (1) non-atomic write on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | ^^^^^^ Data race detected between (1) retag write on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here | help: and (1) occurred earlier here --> $DIR/retag_data_race_write.rs:LL:CC | LL | let _r = &mut *p; | ^^^^^^^ + = help: retags occur on all (re)borrows and as well as when references are copied or moved + = help: retags permit optimizations that insert speculative reads or writes + = help: therefore from the perspective of data races, a retag has the same implications as a read or write = 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 (of the first span) on thread `unnamed-ID`: diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr index 62f139f6f086a..fa0012f9b26cf 100644 --- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr @@ -1,14 +1,17 @@ -error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here +error: Undefined Behavior: Data race detected between (1) retag read on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here --> $DIR/retag_data_race_write.rs:LL:CC | LL | *p = 5; - | ^^^^^^ Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | ^^^^^^ Data race detected between (1) retag read on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here | help: and (1) occurred earlier here --> $DIR/retag_data_race_write.rs:LL:CC | LL | let _r = &mut *p; | ^^^^^^^ + = help: retags occur on all (re)borrows and as well as when references are copied or moved + = help: retags permit optimizations that insert speculative reads or writes + = help: therefore from the perspective of data races, a retag has the same implications as a read or write = 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 (of the first span) on thread `unnamed-ID`: diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs index 5db89c89b77ec..3de517055ec66 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs @@ -13,7 +13,7 @@ fn main() { let ptr = ptr; // We do a protected mutable retag (but no write!) in this thread. fn retag(_x: &mut i32) {} - retag(unsafe { &mut *ptr.0 }); //~ERROR: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-1` + retag(unsafe { &mut *ptr.0 }); //~ERROR: Data race detected between (1) non-atomic read on thread `main` and (2) retag write of type `i32` on thread `unnamed-1` }); // We do a read in the main thread. diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr index 2ce757013d5f2..47ae4b5d46d6f 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr @@ -1,14 +1,17 @@ -error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here +error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `main` and (2) retag write of type `i32` on thread `unnamed-ID` at ALLOC. (2) just happened here --> $DIR/retag_data_race_protected_read.rs:LL:CC | LL | retag(unsafe { &mut *ptr.0 }); - | ^^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | ^^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `main` and (2) retag write of type `i32` on thread `unnamed-ID` at ALLOC. (2) just happened here | help: and (1) occurred earlier here --> $DIR/retag_data_race_protected_read.rs:LL:CC | LL | unsafe { ptr.0.read() }; | ^^^^^^^^^^^^ + = help: retags occur on all (re)borrows and as well as when references are copied or moved + = help: retags permit optimizations that insert speculative reads or writes + = help: therefore from the perspective of data races, a retag has the same implications as a read or write = 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 (of the first span) on thread `unnamed-ID`: diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs index 01a2e9ac474ac..25c92ddf6ca08 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs @@ -15,7 +15,7 @@ fn thread_1(p: SendPtr) { fn thread_2(p: SendPtr) { let p = p.0; unsafe { - *p = 5; //~ ERROR: Data race detected between (1) non-atomic read on thread `unnamed-1` and (2) non-atomic write on thread `unnamed-2` + *p = 5; //~ ERROR: Data race detected between (1) retag read on thread `unnamed-1` and (2) non-atomic write on thread `unnamed-2` } } diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr index d3c8d14e2a198..9fe9fbeda449a 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr @@ -1,14 +1,17 @@ -error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here +error: Undefined Behavior: Data race detected between (1) retag read on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here --> $DIR/retag_data_race_read.rs:LL:CC | LL | *p = 5; - | ^^^^^^ Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | ^^^^^^ Data race detected between (1) retag read on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here | help: and (1) occurred earlier here --> $DIR/retag_data_race_read.rs:LL:CC | LL | let _r = &*p; | ^^^ + = help: retags occur on all (re)borrows and as well as when references are copied or moved + = help: retags permit optimizations that insert speculative reads or writes + = help: therefore from the perspective of data races, a retag has the same implications as a read or write = 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 (of the first span) on thread `unnamed-ID`: From 9aea37d3c114395219a85115f2fd19c249ccf105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 23 Mar 2024 16:14:42 +0100 Subject: [PATCH 35/36] address review feedback --- tests/ui/nll/ice-106874.rs | 18 +++++++++--------- .../const-eval-compare-ice-105047.rs | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/ui/nll/ice-106874.rs b/tests/ui/nll/ice-106874.rs index 77a91d6d823a2..9337eee961bfb 100644 --- a/tests/ui/nll/ice-106874.rs +++ b/tests/ui/nll/ice-106874.rs @@ -7,15 +7,15 @@ use std::rc::Rc; pub fn func(f: F) -> A { A(B(C::new(D::new(move |st| f(st))))) //~^ ERROR implementation of `FnOnce` is not general enough - //~^^ ERROR implementation of `Fn` is not general enough - //~^^^ ERROR implementation of `FnOnce` is not general enough - //~^^^^ ERROR implementation of `FnOnce` is not general enough - //~^^^^^ ERROR implementation of `Fn` is not general enough - //~^^^^^^ ERROR implementation of `FnOnce` is not general enough - //~^^^^^^^ ERROR implementation of `Fn` is not general enough - //~^^^^^^^^ ERROR implementation of `FnOnce` is not general enough - //~^^^^^^^^^ ERROR higher-ranked subtype error - //~^^^^^^^^^^ ERROR higher-ranked subtype error + //~| ERROR implementation of `Fn` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `Fn` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `Fn` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough + //~| ERROR higher-ranked subtype error + //~| ERROR higher-ranked subtype error } trait X {} diff --git a/tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs b/tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs index 0a736a5a8e21b..87ce4f1e14d94 100644 --- a/tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs +++ b/tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs @@ -8,8 +8,8 @@ const RCZ: *const i32 = &raw const *&0; const fn f() { if let RCZ = &raw const *&0 { } //~^ WARN function pointers and raw pointers not derived from integers in patterns - //~^^ ERROR pointers cannot be reliably compared during const eval - //~^^^ WARN this was previously accepted by the compiler but is being phased out + //~| ERROR pointers cannot be reliably compared during const eval + //~| WARN this was previously accepted by the compiler but is being phased out } fn main() {} From 246f7465b35f827d200eba25a1c27fddd18d7962 Mon Sep 17 00:00:00 2001 From: Luv-Ray Date: Sat, 23 Mar 2024 23:33:43 +0800 Subject: [PATCH 36/36] Add test in `higher-ranked` --- .../structually-relate-aliases.rs | 17 ++++++++++++ .../structually-relate-aliases.stderr | 27 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tests/ui/higher-ranked/structually-relate-aliases.rs create mode 100644 tests/ui/higher-ranked/structually-relate-aliases.stderr diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs new file mode 100644 index 0000000000000..8df24702811dd --- /dev/null +++ b/tests/ui/higher-ranked/structually-relate-aliases.rs @@ -0,0 +1,17 @@ +// regression test for issue #121649. + +trait ToUnit<'a> { + type Unit; +} + +trait Overlap {} + +type Assoc<'a, T> = >::Unit; + +impl Overlap for T {} + +impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} +//~^ ERROR 13:17: 13:49: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277] +//~| ERROR 13:36: 13:48: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277] + +fn main() {} diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr new file mode 100644 index 0000000000000..59fab52b221e2 --- /dev/null +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -0,0 +1,27 @@ +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } +error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied + --> $DIR/structually-relate-aliases.rs:13:36 + | +LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} + | ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} + | ++++++++++++++++++++ + +error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied + --> $DIR/structually-relate-aliases.rs:13:17 + | +LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} + | ++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`.