From e71d06be1079db18c39b7088414380d94ce5a8f4 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Tue, 18 Jun 2024 12:43:06 -0500 Subject: [PATCH 01/22] On `target_os = "linux"`, ensure that only one Rust thread calls `libc::exit` or returns from `main`. --- library/std/src/rt.rs | 3 + library/std/src/sys/pal/common/exit_guard.rs | 88 ++++++++++++++++++++ library/std/src/sys/pal/common/mod.rs | 1 + library/std/src/sys/pal/unix/os.rs | 1 + 4 files changed, 93 insertions(+) create mode 100644 library/std/src/sys/pal/common/exit_guard.rs diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index b03fa1c01f266..376bf3440693e 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -161,5 +161,8 @@ fn lang_start( argv, sigpipe, ); + // Guard against multple threads calling `libc::exit` concurrently. + // See the documentation for `unique_thread_exit` for more information. + crate::sys::common::exit_guard::unique_thread_exit(); v } diff --git a/library/std/src/sys/pal/common/exit_guard.rs b/library/std/src/sys/pal/common/exit_guard.rs new file mode 100644 index 0000000000000..3a0398a659831 --- /dev/null +++ b/library/std/src/sys/pal/common/exit_guard.rs @@ -0,0 +1,88 @@ +cfg_if::cfg_if! { + if #[cfg(target_os = "linux")] { + /// Mitigation for https://github.com/rust-lang/rust/issues/126600 + /// + /// On `unix` (where `libc::exit` may not be thread-safe), ensure that only one Rust thread + /// calls `libc::exit` (or returns from `main`) by calling this function before calling + /// `libc::exit` (or returning from `main`). + /// + /// Technically not enough to ensure soundness, since other code directly calling + /// libc::exit will still race with this. + /// + /// *This function does not itself call `libc::exit`.* This is so it can also be used + /// to guard returning from `main`. + /// + /// This function will return only the first time it is called in a process. + /// + /// * If it is called again on the same thread as the first call, it will abort. + /// * If it is called again on a different thread, it will `thread::park()` in a loop + /// (waiting for the process to exit). + pub(crate) fn unique_thread_exit() { + let this_thread_id = unsafe { libc::gettid() }; + debug_assert_ne!(this_thread_id, 0, "thread ID cannot be zero"); + #[cfg(target_has_atomic = "32")] + { + use crate::sync::atomic::{AtomicI32, Ordering}; + static EXITING_THREAD_ID: AtomicI32 = AtomicI32::new(0); + match EXITING_THREAD_ID.compare_exchange( + 0, + this_thread_id, + Ordering::Relaxed, + Ordering::Relaxed, + ) { + Ok(_zero) => { + // This is the first thread to call `unique_thread_exit`, + // and this is the first time it is called. + // Set EXITING_THREAD_ID to this thread's ID (done by the + // compare_exchange) and return. + } + Err(id) if id == this_thread_id => { + // This is the first thread to call `unique_thread_exit`, + // but this is the second time it is called. + // Abort the process. + core::panicking::panic_nounwind("std::process::exit called re-entrantly") + } + Err(_) => { + // This is not the first thread to call `unique_thread_exit`. + // Park until the process exits. + loop { + crate::thread::park(); + } + } + } + } + #[cfg(not(target_has_atomic = "32"))] + { + use crate::sync::{Mutex, PoisonError}; + static EXITING_THREAD_ID: Mutex = Mutex::new(0); + let mut exiting_thread_id = + EXITING_THREAD_ID.lock().unwrap_or_else(PoisonError::into_inner); + if *exiting_thread_id == 0 { + // This is the first thread to call `unique_thread_exit`, + // and this is the first time it is called. + // Set EXITING_THREAD_ID to this thread's ID and return. + *exiting_thread_id = this_thread_id; + } else if *exiting_thread_id == this_thread_id { + // This is the first thread to call `unique_thread_exit`, + // but this is the second time it is called. + // Abort the process. + core::panicking::panic_nounwind("std::process::exit called re-entrantly") + } else { + // This is not the first thread to call `unique_thread_exit`. + // Park until the process exits. + drop(exiting_thread_id); + loop { + crate::thread::park(); + } + } + } + } + } else { + /// Mitigation for https://github.com/rust-lang/rust/issues/126600 + /// + /// Mitigation is ***NOT*** implemented on this platform, either because this platform is not affected, or because mitigation is not yet implemented for this platform. + pub(crate) fn unique_thread_exit() { + // Mitigation not required on platforms where `exit` is thread-safe. + } + } +} diff --git a/library/std/src/sys/pal/common/mod.rs b/library/std/src/sys/pal/common/mod.rs index 29fc0835d7666..cc1dceb63e2f5 100644 --- a/library/std/src/sys/pal/common/mod.rs +++ b/library/std/src/sys/pal/common/mod.rs @@ -11,6 +11,7 @@ #![allow(dead_code)] pub mod alloc; +pub mod exit_guard; pub mod small_c_string; #[cfg(test)] diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 2e71ceceb58b1..3f598a095c156 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -758,6 +758,7 @@ pub fn home_dir() -> Option { } pub fn exit(code: i32) -> ! { + crate::sys::common::exit_guard::unique_thread_exit(); unsafe { libc::exit(code as c_int) } } From bff35313972b0d3e248a39cf5a2d03d916ba56d2 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Thu, 20 Jun 2024 22:18:46 -0500 Subject: [PATCH 02/22] fix rustdoc URL --- library/std/src/sys/pal/common/exit_guard.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/common/exit_guard.rs b/library/std/src/sys/pal/common/exit_guard.rs index 3a0398a659831..49d3b4a96f073 100644 --- a/library/std/src/sys/pal/common/exit_guard.rs +++ b/library/std/src/sys/pal/common/exit_guard.rs @@ -1,6 +1,6 @@ cfg_if::cfg_if! { if #[cfg(target_os = "linux")] { - /// Mitigation for https://github.com/rust-lang/rust/issues/126600 + /// Mitigation for /// /// On `unix` (where `libc::exit` may not be thread-safe), ensure that only one Rust thread /// calls `libc::exit` (or returns from `main`) by calling this function before calling @@ -78,9 +78,10 @@ cfg_if::cfg_if! { } } } else { - /// Mitigation for https://github.com/rust-lang/rust/issues/126600 + /// Mitigation for /// - /// Mitigation is ***NOT*** implemented on this platform, either because this platform is not affected, or because mitigation is not yet implemented for this platform. + /// Mitigation is ***NOT*** implemented on this platform, either because this platform + /// is not affected, or because mitigation is not yet implemented for this platform. pub(crate) fn unique_thread_exit() { // Mitigation not required on platforms where `exit` is thread-safe. } From c36fdeb9a3da04839e0892e1351286881c848e39 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Thu, 20 Jun 2024 23:19:18 -0500 Subject: [PATCH 03/22] Don't perform mitigation for thread-unsafe libc::exit under Miri. 1. Miri's exit is thread-safe 2. Miri doesn't (yet) support `libc::gettid`, used in the implementation of the mitigation on Linux. --- library/std/src/sys/pal/common/exit_guard.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/common/exit_guard.rs b/library/std/src/sys/pal/common/exit_guard.rs index 49d3b4a96f073..37c8f97e45d9d 100644 --- a/library/std/src/sys/pal/common/exit_guard.rs +++ b/library/std/src/sys/pal/common/exit_guard.rs @@ -1,5 +1,13 @@ cfg_if::cfg_if! { - if #[cfg(target_os = "linux")] { + if #[cfg(miri)] { + /// Mitigation for + /// + /// This mitigation is not necessary when running under Miri, so this function does nothing + /// when running under Miri. + pub(crate) fn unique_thread_exit() { + // Mitigation not required on Miri, where `exit` is thread-safe. + } + } else if #[cfg(target_os = "linux")] { /// Mitigation for /// /// On `unix` (where `libc::exit` may not be thread-safe), ensure that only one Rust thread From 31851d4770774ac95a694f2596138fc43fcd39b4 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 14 Jun 2024 15:49:45 -0700 Subject: [PATCH 04/22] Add `-Zdump-mir-exclude-alloc-bytes` --- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_middle/src/mir/pretty.rs | 3 +++ compiler/rustc_session/src/options.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 6ffc518097ef0..619b125a8780d 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -683,6 +683,7 @@ fn test_unstable_options_tracking_hash() { untracked!(dump_mir, Some(String::from("abc"))); untracked!(dump_mir_dataflow, true); untracked!(dump_mir_dir, String::from("abc")); + untracked!(dump_mir_exclude_alloc_bytes, true); untracked!(dump_mir_exclude_pass_number, true); untracked!(dump_mir_graphviz, true); untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into()))); diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 4657f4dcf8132..3ea98de1a177d 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1521,6 +1521,9 @@ impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> std::fmt::Display // We are done. return write!(w, " {{}}"); } + if tcx.sess.opts.unstable_opts.dump_mir_exclude_alloc_bytes { + return write!(w, " {{ .. }}"); + } // Write allocation bytes. writeln!(w, " {{")?; write_allocation_bytes(tcx, alloc, w, " ")?; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9a10adeb6d1a1..a3f1369776de4 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1662,6 +1662,8 @@ options! { (default: no)"), dump_mir_dir: String = ("mir_dump".to_string(), parse_string, [UNTRACKED], "the directory the MIR is dumped into (default: `mir_dump`)"), + dump_mir_exclude_alloc_bytes: bool = (false, parse_bool, [UNTRACKED], + "exclude the raw bytes of allocations when dumping MIR (used in tests) (default: no)"), dump_mir_exclude_pass_number: bool = (false, parse_bool, [UNTRACKED], "exclude the pass number when dumping MIR (used in tests) (default: no)"), dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED], From 1a05cb2d9358879468c87645b0c1d5d1e8e12a12 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 14 Jun 2024 16:01:26 -0700 Subject: [PATCH 05/22] Use `-Zdump-mir-exclude-alloc-bytes` in some mir-opt tests --- tests/mir-opt/const_debuginfo.rs | 2 +- tests/mir-opt/const_prop/address_of_pair.rs | 1 + tests/mir-opt/const_prop/checked_add.rs | 2 +- tests/mir-opt/const_prop/mutable_variable_aggregate.rs | 1 + tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs | 1 + tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs | 1 + tests/mir-opt/const_prop/return_place.rs | 2 +- tests/mir-opt/const_prop/slice_len.rs | 2 +- tests/mir-opt/const_prop/tuple_literal_propagation.rs | 1 + tests/mir-opt/dataflow-const-prop/checked.rs | 2 +- tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs | 2 +- tests/mir-opt/dataflow-const-prop/enum.rs | 1 + tests/mir-opt/dataflow-const-prop/struct.rs | 1 + tests/mir-opt/dataflow-const-prop/tuple.rs | 1 + tests/mir-opt/enum_opt.rs | 2 +- tests/mir-opt/gvn.rs | 1 + tests/mir-opt/pre-codegen/optimizes_into_variable.rs | 2 +- 17 files changed, 17 insertions(+), 8 deletions(-) diff --git a/tests/mir-opt/const_debuginfo.rs b/tests/mir-opt/const_debuginfo.rs index 907d7fef06746..3b2bc4559ced9 100644 --- a/tests/mir-opt/const_debuginfo.rs +++ b/tests/mir-opt/const_debuginfo.rs @@ -1,5 +1,5 @@ //@ test-mir-pass: SingleUseConsts -//@ compile-flags: -C overflow-checks=no -Zmir-enable-passes=+GVN +//@ compile-flags: -C overflow-checks=no -Zmir-enable-passes=+GVN -Zdump-mir-exclude-alloc-bytes #![allow(unused)] diff --git a/tests/mir-opt/const_prop/address_of_pair.rs b/tests/mir-opt/const_prop/address_of_pair.rs index 6d0c0f8ad52a7..9acaaa0ccaf9d 100644 --- a/tests/mir-opt/const_prop/address_of_pair.rs +++ b/tests/mir-opt/const_prop/address_of_pair.rs @@ -1,4 +1,5 @@ //@ test-mir-pass: GVN +//@ compile-flags: -Zdump-mir-exclude-alloc-bytes // EMIT_MIR address_of_pair.fn0.GVN.diff pub fn fn0() -> bool { diff --git a/tests/mir-opt/const_prop/checked_add.rs b/tests/mir-opt/const_prop/checked_add.rs index 0560b04957311..d450f7d03f38c 100644 --- a/tests/mir-opt/const_prop/checked_add.rs +++ b/tests/mir-opt/const_prop/checked_add.rs @@ -1,6 +1,6 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY //@ test-mir-pass: GVN -//@ compile-flags: -C overflow-checks=on +//@ compile-flags: -C overflow-checks=on -Zdump-mir-exclude-alloc-bytes // EMIT_MIR checked_add.main.GVN.diff fn main() { diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate.rs index 7de647ed9c37f..80cd75215c1b7 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.rs @@ -1,4 +1,5 @@ //@ test-mir-pass: GVN +//@ compile-flags: -Zdump-mir-exclude-alloc-bytes // EMIT_MIR mutable_variable_aggregate.main.GVN.diff fn main() { diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs index 5656c0e7a6863..856afd53ab46b 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs @@ -1,4 +1,5 @@ //@ test-mir-pass: GVN +//@ compile-flags: -Zdump-mir-exclude-alloc-bytes // EMIT_MIR mutable_variable_aggregate_mut_ref.main.GVN.diff fn main() { diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs index cc92949128f72..2c6cc0db6b211 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs @@ -1,5 +1,6 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY //@ test-mir-pass: GVN +//@ compile-flags: -Zdump-mir-exclude-alloc-bytes // EMIT_MIR mutable_variable_unprop_assign.main.GVN.diff fn main() { diff --git a/tests/mir-opt/const_prop/return_place.rs b/tests/mir-opt/const_prop/return_place.rs index e7eea11ae492f..c5293aa73e55b 100644 --- a/tests/mir-opt/const_prop/return_place.rs +++ b/tests/mir-opt/const_prop/return_place.rs @@ -1,6 +1,6 @@ //@ test-mir-pass: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -//@ compile-flags: -C overflow-checks=on +//@ compile-flags: -C overflow-checks=on -Zdump-mir-exclude-alloc-bytes // EMIT_MIR return_place.add.GVN.diff // EMIT_MIR return_place.add.PreCodegen.before.mir diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs index 63cdbf01b3e82..265a496f39a36 100644 --- a/tests/mir-opt/const_prop/slice_len.rs +++ b/tests/mir-opt/const_prop/slice_len.rs @@ -1,5 +1,5 @@ //@ test-mir-pass: GVN -//@ compile-flags: -Zmir-enable-passes=+InstSimplify +//@ compile-flags: -Zmir-enable-passes=+InstSimplify -Zdump-mir-exclude-alloc-bytes // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.rs b/tests/mir-opt/const_prop/tuple_literal_propagation.rs index e42a62cb6fdf3..baed5670dda81 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.rs +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.rs @@ -1,4 +1,5 @@ //@ test-mir-pass: GVN +//@ compile-flags: -Zdump-mir-exclude-alloc-bytes // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR tuple_literal_propagation.main.GVN.diff diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs index a73693464f95b..f5a6cdb2c8d35 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.rs +++ b/tests/mir-opt/dataflow-const-prop/checked.rs @@ -1,5 +1,5 @@ //@ test-mir-pass: DataflowConstProp -//@ compile-flags: -Coverflow-checks=on +//@ compile-flags: -Coverflow-checks=on -Zdump-mir-exclude-alloc-bytes // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR checked.main.DataflowConstProp.diff diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs index 3a0cbac328cb5..087bd7a18572c 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -1,5 +1,5 @@ //@ test-mir-pass: DataflowConstProp -//@ compile-flags: -Zmir-enable-passes=+GVN,+Inline +//@ compile-flags: -Zmir-enable-passes=+GVN,+Inline -Zdump-mir-exclude-alloc-bytes // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR_FOR_EACH_PANIC_STRATEGY diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index 946cfa4c76c02..37304e3a270e9 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -1,4 +1,5 @@ //@ test-mir-pass: DataflowConstProp +//@ compile-flags: -Zdump-mir-exclude-alloc-bytes // EMIT_MIR_FOR_EACH_BIT_WIDTH #![feature(custom_mir, core_intrinsics, rustc_attrs)] diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index eed782c9036b2..4b160c3dab7e8 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -1,4 +1,5 @@ //@ test-mir-pass: DataflowConstProp +//@ compile-flags: -Zdump-mir-exclude-alloc-bytes // EMIT_MIR_FOR_EACH_BIT_WIDTH #[derive(Copy, Clone)] diff --git a/tests/mir-opt/dataflow-const-prop/tuple.rs b/tests/mir-opt/dataflow-const-prop/tuple.rs index d624e21f21ac4..19b675770abe9 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.rs +++ b/tests/mir-opt/dataflow-const-prop/tuple.rs @@ -1,4 +1,5 @@ //@ test-mir-pass: DataflowConstProp +//@ compile-flags: -Zdump-mir-exclude-alloc-bytes // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR tuple.main.DataflowConstProp.diff diff --git a/tests/mir-opt/enum_opt.rs b/tests/mir-opt/enum_opt.rs index 2cc5df84d6b59..e42be8ac06dc9 100644 --- a/tests/mir-opt/enum_opt.rs +++ b/tests/mir-opt/enum_opt.rs @@ -1,7 +1,7 @@ // skip-filecheck //@ test-mir-pass: EnumSizeOpt // EMIT_MIR_FOR_EACH_BIT_WIDTH -//@ compile-flags: -Zunsound-mir-opts +//@ compile-flags: -Zunsound-mir-opts -Zdump-mir-exclude-alloc-bytes #![feature(arbitrary_enum_discriminant, repr128)] diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 86f42d23f3835..29f28e7af4145 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -1,4 +1,5 @@ //@ test-mir-pass: GVN +//@ compile-flags: -Zdump-mir-exclude-alloc-bytes // EMIT_MIR_FOR_EACH_PANIC_STRATEGY //@ only-64bit diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.rs b/tests/mir-opt/pre-codegen/optimizes_into_variable.rs index de5e2d5c3121b..44b4b0ad888a5 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.rs +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.rs @@ -1,6 +1,6 @@ // skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -//@ compile-flags: -C overflow-checks=on +//@ compile-flags: -C overflow-checks=on -Zdump-mir-exclude-alloc-bytes struct Point { x: u32, From 7c3673ff6f2ff4e8e85344c091c9feb4b5da1290 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 14 Jun 2024 16:05:22 -0700 Subject: [PATCH 06/22] Bless mir-opt for excluded alloc bytes --- .../const_debuginfo.main.SingleUseConsts.diff | 8 +-- .../const_prop/address_of_pair.fn0.GVN.diff | 6 +- .../checked_add.main.GVN.panic-abort.diff | 6 +- .../checked_add.main.GVN.panic-unwind.diff | 6 +- .../mutable_variable_aggregate.main.GVN.diff | 6 +- ...e_variable_aggregate_mut_ref.main.GVN.diff | 6 +- ...le_unprop_assign.main.GVN.panic-abort.diff | 6 +- ...e_unprop_assign.main.GVN.panic-unwind.diff | 6 +- .../return_place.add.GVN.panic-abort.diff | 6 +- .../return_place.add.GVN.panic-unwind.diff | 6 +- ...lace.add.PreCodegen.before.panic-abort.mir | 4 +- ...ace.add.PreCodegen.before.panic-unwind.mir | 4 +- .../slice_len.main.GVN.32bit.panic-abort.diff | 6 +- ...slice_len.main.GVN.32bit.panic-unwind.diff | 6 +- .../slice_len.main.GVN.64bit.panic-abort.diff | 6 +- ...slice_len.main.GVN.64bit.panic-unwind.diff | 6 +- ...eral_propagation.main.GVN.panic-abort.diff | 6 +- ...ral_propagation.main.GVN.panic-unwind.diff | 6 +- ...ed.main.DataflowConstProp.panic-abort.diff | 10 +--- ...d.main.DataflowConstProp.panic-unwind.diff | 10 +--- ...n.DataflowConstProp.32bit.panic-abort.diff | 12 +--- ....DataflowConstProp.32bit.panic-unwind.diff | 12 +--- ...n.DataflowConstProp.64bit.panic-abort.diff | 12 +--- ....DataflowConstProp.64bit.panic-unwind.diff | 12 +--- ...oxed_slice.main.GVN.32bit.panic-abort.diff | 14 ++--- ...xed_slice.main.GVN.32bit.panic-unwind.diff | 14 ++--- ...oxed_slice.main.GVN.64bit.panic-abort.diff | 14 ++--- ...xed_slice.main.GVN.64bit.panic-unwind.diff | 14 ++--- .../enum.simple.DataflowConstProp.32bit.diff | 6 +- .../enum.simple.DataflowConstProp.64bit.diff | 6 +- .../enum.statics.DataflowConstProp.32bit.diff | 23 +++----- .../enum.statics.DataflowConstProp.64bit.diff | 23 +++----- .../struct.main.DataflowConstProp.32bit.diff | 58 ++++++------------- .../struct.main.DataflowConstProp.64bit.diff | 58 ++++++------------- .../tuple.main.DataflowConstProp.32bit.diff | 18 ++---- .../tuple.main.DataflowConstProp.64bit.diff | 18 ++---- .../enum_opt.cand.EnumSizeOpt.32bit.diff | 6 +- .../enum_opt.cand.EnumSizeOpt.64bit.diff | 6 +- .../enum_opt.unin.EnumSizeOpt.32bit.diff | 6 +- .../enum_opt.unin.EnumSizeOpt.64bit.diff | 6 +- ...vn.arithmetic_checked.GVN.panic-abort.diff | 6 +- ...n.arithmetic_checked.GVN.panic-unwind.diff | 6 +- .../gvn.fn_pointers.GVN.panic-abort.diff | 18 +++--- .../gvn.fn_pointers.GVN.panic-unwind.diff | 18 +++--- .../gvn.indirect_static.GVN.panic-abort.diff | 4 +- .../gvn.indirect_static.GVN.panic-unwind.diff | 4 +- .../gvn.wide_ptr_integer.GVN.panic-abort.diff | 10 +--- ...gvn.wide_ptr_integer.GVN.panic-unwind.diff | 10 +--- ...o_variable.main.GVN.32bit.panic-abort.diff | 6 +- ..._variable.main.GVN.32bit.panic-unwind.diff | 6 +- ...o_variable.main.GVN.64bit.panic-abort.diff | 6 +- ..._variable.main.GVN.64bit.panic-unwind.diff | 6 +- 52 files changed, 182 insertions(+), 382 deletions(-) diff --git a/tests/mir-opt/const_debuginfo.main.SingleUseConsts.diff b/tests/mir-opt/const_debuginfo.main.SingleUseConsts.diff index ac33f51984cd8..8088984bc77ab 100644 --- a/tests/mir-opt/const_debuginfo.main.SingleUseConsts.diff +++ b/tests/mir-opt/const_debuginfo.main.SingleUseConsts.diff @@ -119,11 +119,7 @@ } } - ALLOC0 (size: 8, align: 4) { - 20 00 00 00 20 00 00 00 │ ... ... - } + ALLOC0 (size: 8, align: 4) { .. } - ALLOC1 (size: 4, align: 2) { - 01 00 63 00 │ ..c. - } + ALLOC1 (size: 4, align: 2) { .. } diff --git a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff index 3f4958f60e85b..ac372f837268b 100644 --- a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff +++ b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff @@ -44,9 +44,7 @@ StorageDead(_2); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 01 00 00 00 00 __ __ __ │ .....░░░ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/checked_add.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/checked_add.main.GVN.panic-abort.diff index 0e93c167ebc96..798f957caa58c 100644 --- a/tests/mir-opt/const_prop/checked_add.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/checked_add.main.GVN.panic-abort.diff @@ -24,9 +24,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 02 00 00 00 00 __ __ __ │ .....░░░ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/checked_add.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/checked_add.main.GVN.panic-unwind.diff index 589eed5776c9f..a09f8ee5be12a 100644 --- a/tests/mir-opt/const_prop/checked_add.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/checked_add.main.GVN.panic-unwind.diff @@ -24,9 +24,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 02 00 00 00 00 __ __ __ │ .....░░░ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.GVN.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.GVN.diff index b6ff7b0fc234d..7584353620ec5 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.GVN.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.GVN.diff @@ -24,9 +24,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 2a 00 00 00 2b 00 00 00 │ *...+... } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff index 4ed7c98514796..e16e2969eb895 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff @@ -31,9 +31,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 2a 00 00 00 2b 00 00 00 │ *...+... } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-abort.diff index d1d23675bfd91..19d79694666f2 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-abort.diff @@ -48,9 +48,7 @@ + nop; return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 01 00 00 00 02 00 00 00 │ ........ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-unwind.diff index 4d69c9ce2efe6..2bb277bf27f7f 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-unwind.diff @@ -48,9 +48,7 @@ + nop; return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 01 00 00 00 02 00 00 00 │ ........ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/return_place.add.GVN.panic-abort.diff b/tests/mir-opt/const_prop/return_place.add.GVN.panic-abort.diff index b2d40daa80c4c..037fe60c2fdb3 100644 --- a/tests/mir-opt/const_prop/return_place.add.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/return_place.add.GVN.panic-abort.diff @@ -17,9 +17,7 @@ + _0 = const 4_u32; return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 04 00 00 00 00 __ __ __ │ .....░░░ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/return_place.add.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/return_place.add.GVN.panic-unwind.diff index 2eafc51cd3db6..438a1cebea8cb 100644 --- a/tests/mir-opt/const_prop/return_place.add.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/return_place.add.GVN.panic-unwind.diff @@ -17,9 +17,7 @@ + _0 = const 4_u32; return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 04 00 00 00 00 __ __ __ │ .....░░░ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir index f87c26bb004c6..66fd61cc3aee9 100644 --- a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir +++ b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir @@ -15,6 +15,4 @@ fn add() -> u32 { } } -ALLOC0 (size: 8, align: 4) { - 04 00 00 00 00 __ __ __ │ .....░░░ -} +ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir index 33f97591387c3..f9b07a59de9c3 100644 --- a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir +++ b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir @@ -15,6 +15,4 @@ fn add() -> u32 { } } -ALLOC0 (size: 8, align: 4) { - 04 00 00 00 00 __ __ __ │ .....░░░ -} +ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff index ef298dddd5a49..8415789de6ecd 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff @@ -49,9 +49,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 12, align: 4) { -+ 01 00 00 00 02 00 00 00 03 00 00 00 │ ............ } ++ ++ ALLOC0 (size: 12, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff index 5379df3f60b44..fea7caac3cdce 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff @@ -49,9 +49,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 12, align: 4) { -+ 01 00 00 00 02 00 00 00 03 00 00 00 │ ............ } ++ ++ ALLOC0 (size: 12, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff index ef298dddd5a49..8415789de6ecd 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff @@ -49,9 +49,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 12, align: 4) { -+ 01 00 00 00 02 00 00 00 03 00 00 00 │ ............ } ++ ++ ALLOC0 (size: 12, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff index 5379df3f60b44..fea7caac3cdce 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff @@ -49,9 +49,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 12, align: 4) { -+ 01 00 00 00 02 00 00 00 03 00 00 00 │ ............ } ++ ++ ALLOC0 (size: 12, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-abort.diff index c2f3fb1b3b575..bf8fece3d37b9 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-abort.diff @@ -31,9 +31,7 @@ + nop; return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 01 00 00 00 02 00 00 00 │ ........ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-unwind.diff index 55d9a3b0cac67..02a75849d8872 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-unwind.diff @@ -31,9 +31,7 @@ + nop; return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 01 00 00 00 02 00 00 00 │ ........ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff index 53663c6476bdc..79ea55617481e 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff @@ -76,13 +76,9 @@ StorageDead(_1); return; } -+ } + } + -+ ALLOC0 (size: 8, align: 4) { -+ 00 00 00 80 01 __ __ __ │ .....░░░ -+ } ++ ALLOC0 (size: 8, align: 4) { .. } + -+ ALLOC1 (size: 8, align: 4) { -+ 03 00 00 00 00 __ __ __ │ .....░░░ - } ++ ALLOC1 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff index 34feb2a640629..bd22c50dd8fcf 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff @@ -76,13 +76,9 @@ StorageDead(_1); return; } -+ } + } + -+ ALLOC0 (size: 8, align: 4) { -+ 00 00 00 80 01 __ __ __ │ .....░░░ -+ } ++ ALLOC0 (size: 8, align: 4) { .. } + -+ ALLOC1 (size: 8, align: 4) { -+ 03 00 00 00 00 __ __ __ │ .....░░░ - } ++ ALLOC1 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index 8005bc23cf699..4097e060f4d47 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -94,15 +94,9 @@ } } - ALLOC2 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } + ALLOC2 (size: 8, align: 4) { .. } - ALLOC1 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } + ALLOC1 (size: 8, align: 4) { .. } - ALLOC0 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } + ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index 42b1be32387c4..ff44d0df5e3e9 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -98,15 +98,9 @@ } } - ALLOC2 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } + ALLOC2 (size: 8, align: 4) { .. } - ALLOC1 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } + ALLOC1 (size: 8, align: 4) { .. } - ALLOC0 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } + ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index 7b57b0db50c94..3662c3b59d271 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -94,15 +94,9 @@ } } - ALLOC2 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } + ALLOC2 (size: 16, align: 8) { .. } - ALLOC1 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } + ALLOC1 (size: 16, align: 8) { .. } - ALLOC0 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } + ALLOC0 (size: 16, align: 8) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 2e75a63e29052..68dee57dee9e0 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -98,15 +98,9 @@ } } - ALLOC2 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } + ALLOC2 (size: 16, align: 8) { .. } - ALLOC1 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } + ALLOC1 (size: 16, align: 8) { .. } - ALLOC0 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } + ALLOC0 (size: 16, align: 8) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index 06011f9d75967..9d96e895c8aa5 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -102,17 +102,11 @@ _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } -+ } + } + -+ ALLOC2 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ -+ } ++ ALLOC2 (size: 8, align: 4) { .. } + -+ ALLOC1 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ -+ } ++ ALLOC1 (size: 8, align: 4) { .. } + -+ ALLOC0 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ - } ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index eb4a3ffd91d2e..0bdff584b01ec 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -106,17 +106,11 @@ _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } -+ } + } + -+ ALLOC2 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ -+ } ++ ALLOC2 (size: 8, align: 4) { .. } + -+ ALLOC1 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ -+ } ++ ALLOC1 (size: 8, align: 4) { .. } + -+ ALLOC0 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ - } ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index a7cc243e548e9..99e96fe5d70fd 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -102,17 +102,11 @@ _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } -+ } + } + -+ ALLOC2 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ -+ } ++ ALLOC2 (size: 16, align: 8) { .. } + -+ ALLOC1 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ -+ } ++ ALLOC1 (size: 16, align: 8) { .. } + -+ ALLOC0 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } ++ ALLOC0 (size: 16, align: 8) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index c905a48862caa..5eefabeac3868 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -106,17 +106,11 @@ _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } -+ } + } + -+ ALLOC2 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ -+ } ++ ALLOC2 (size: 16, align: 8) { .. } + -+ ALLOC1 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ -+ } ++ ALLOC1 (size: 16, align: 8) { .. } + -+ ALLOC0 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } ++ ALLOC0 (size: 16, align: 8) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff index 89ed26f065b28..a64dda0d06c48 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff @@ -60,9 +60,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 00 00 00 00 00 00 00 00 │ ........ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff index 89ed26f065b28..a64dda0d06c48 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff @@ -60,9 +60,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 00 00 00 00 00 00 00 00 │ ........ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index fe8ed0114897d..b4d14f25fe2ab 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -43,7 +43,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {ALLOC1: &E}; + _2 = const {ALLOC0: &E}; - _1 = (*_2); + _1 = const E::V1(0_i32); StorageDead(_2); @@ -79,7 +79,7 @@ bb4: { StorageLive(_7); StorageLive(_8); - _8 = const {ALLOC2: &&E}; + _8 = const {ALLOC1: &&E}; _7 = (*_8); StorageDead(_8); StorageLive(_9); @@ -111,21 +111,14 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC3 (size: 8, align: 4) { -+ 00 00 00 00 00 00 00 00 │ ........ } - ALLOC2 (static: RC, size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ - } ++ ALLOC2 (size: 8, align: 4) { .. } ++ + ALLOC1 (static: RC, size: 4, align: 4) { .. } - ALLOC0 (size: 8, align: 4) { - 01 00 00 00 04 00 00 00 │ ........ - } +- ALLOC2 (size: 8, align: 4) { .. } ++ ALLOC3 (size: 8, align: 4) { .. } - ALLOC1 (static: statics::C, size: 8, align: 4) { - 00 00 00 00 00 00 00 00 │ ........ - } + ALLOC0 (static: statics::C, size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index df3a989d09eba..57d02b87d1369 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -43,7 +43,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {ALLOC1: &E}; + _2 = const {ALLOC0: &E}; - _1 = (*_2); + _1 = const E::V1(0_i32); StorageDead(_2); @@ -79,7 +79,7 @@ bb4: { StorageLive(_7); StorageLive(_8); - _8 = const {ALLOC2: &&E}; + _8 = const {ALLOC1: &&E}; _7 = (*_8); StorageDead(_8); StorageLive(_9); @@ -111,21 +111,14 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC3 (size: 8, align: 4) { -+ 00 00 00 00 00 00 00 00 │ ........ } - ALLOC2 (static: RC, size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ - } ++ ALLOC2 (size: 8, align: 4) { .. } ++ + ALLOC1 (static: RC, size: 8, align: 8) { .. } - ALLOC0 (size: 8, align: 4) { - 01 00 00 00 04 00 00 00 │ ........ - } +- ALLOC2 (size: 8, align: 4) { .. } ++ ALLOC3 (size: 8, align: 4) { .. } - ALLOC1 (static: statics::C, size: 8, align: 4) { - 00 00 00 00 00 00 00 00 │ ........ - } + ALLOC0 (static: statics::C, size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index f674169e28b26..a6da1483c1ac5 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -112,7 +112,7 @@ _9 = (_10.2: &[f32]); StorageDead(_10); StorageLive(_14); - _14 = const {ALLOC4: &&SmallStruct}; + _14 = const {ALLOC0: &&SmallStruct}; _31 = deref_copy (*_14); StorageLive(_11); _32 = deref_copy (*_14); @@ -149,7 +149,7 @@ _21 = (_22.2: &[f32]); StorageDead(_22); StorageLive(_26); - _26 = const {ALLOC5: &&BigStruct}; + _26 = const {ALLOC1: &&BigStruct}; _35 = deref_copy (*_26); StorageLive(_23); _36 = deref_copy (*_26); @@ -197,51 +197,31 @@ StorageDead(_1); return; } -+ } + } + ++ ALLOC2 (size: 8, align: 4) { .. } + -+ ALLOC6 (size: 8, align: 4) { -+ 01 00 00 00 23 00 00 00 │ ....#... -+ } ++ ALLOC3 (size: 8, align: 4) { .. } + -+ ALLOC7 (size: 8, align: 4) { -+ 01 00 00 00 23 00 00 00 │ ....#... -+ } ++ ALLOC4 (size: 8, align: 4) { .. } + -+ ALLOC8 (size: 8, align: 4) { -+ 01 00 00 00 23 00 00 00 │ ....#... -+ } ++ ALLOC5 (size: 8, align: 4) { .. } + -+ ALLOC9 (size: 8, align: 4) { -+ 01 00 00 00 01 00 00 00 │ ........ -+ } ++ ALLOC6 (size: 4, align: 4) { .. } + -+ ALLOC10 (size: 4, align: 4) { -+ 01 00 00 00 │ .... - } - - ALLOC5 (static: BIG_STAT, size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ - } + ALLOC1 (static: BIG_STAT, size: 4, align: 4) { .. } - ALLOC0 (size: 20, align: 4) { - 0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ 02 00 00 00 │ ....#...╾──╼.... - 0x10 │ 00 00 a4 42 │ ...B - } +- ALLOC2 (size: 20, align: 4) { .. } ++ ALLOC7 (size: 20, align: 4) { .. } - ALLOC1 (size: 8, align: 4) { - 00 00 34 42 00 00 90 42 │ ..4B...B - } +- ALLOC3 (size: 8, align: 4) { .. } ++ ALLOC8 (size: 8, align: 4) { .. } - ALLOC4 (static: SMALL_STAT, size: 4, align: 4) { - ╾ALLOC2╼ │ ╾──╼ - } + ALLOC0 (static: SMALL_STAT, size: 4, align: 4) { .. } - ALLOC2 (size: 20, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ 01 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 10 41 │ ...A - } +- ALLOC4 (size: 20, align: 4) { .. } ++ ALLOC9 (size: 20, align: 4) { .. } - ALLOC3 (size: 4, align: 4) { - 00 00 50 41 │ ..PA - } +- ALLOC5 (size: 4, align: 4) { .. } ++ ALLOC10 (size: 4, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index c2608190a6b97..7ca25e4429953 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -112,7 +112,7 @@ _9 = (_10.2: &[f32]); StorageDead(_10); StorageLive(_14); - _14 = const {ALLOC4: &&SmallStruct}; + _14 = const {ALLOC0: &&SmallStruct}; _31 = deref_copy (*_14); StorageLive(_11); _32 = deref_copy (*_14); @@ -149,7 +149,7 @@ _21 = (_22.2: &[f32]); StorageDead(_22); StorageLive(_26); - _26 = const {ALLOC5: &&BigStruct}; + _26 = const {ALLOC1: &&BigStruct}; _35 = deref_copy (*_26); StorageLive(_23); _36 = deref_copy (*_26); @@ -197,51 +197,31 @@ StorageDead(_1); return; } -+ } + } + ++ ALLOC2 (size: 8, align: 4) { .. } + -+ ALLOC6 (size: 8, align: 4) { -+ 01 00 00 00 23 00 00 00 │ ....#... -+ } ++ ALLOC3 (size: 8, align: 4) { .. } + -+ ALLOC7 (size: 8, align: 4) { -+ 01 00 00 00 23 00 00 00 │ ....#... -+ } ++ ALLOC4 (size: 8, align: 4) { .. } + -+ ALLOC8 (size: 8, align: 4) { -+ 01 00 00 00 23 00 00 00 │ ....#... -+ } ++ ALLOC5 (size: 8, align: 4) { .. } + -+ ALLOC9 (size: 8, align: 4) { -+ 01 00 00 00 01 00 00 00 │ ........ -+ } ++ ALLOC6 (size: 4, align: 4) { .. } + -+ ALLOC10 (size: 4, align: 4) { -+ 01 00 00 00 │ .... - } - - ALLOC5 (static: BIG_STAT, size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ - } + ALLOC1 (static: BIG_STAT, size: 8, align: 8) { .. } - ALLOC0 (size: 32, align: 8) { - 0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ │ ....#...╾──────╼ - 0x10 │ 02 00 00 00 00 00 00 00 00 00 a4 42 __ __ __ __ │ ...........B░░░░ - } +- ALLOC2 (size: 32, align: 8) { .. } ++ ALLOC7 (size: 32, align: 8) { .. } - ALLOC1 (size: 8, align: 4) { - 00 00 34 42 00 00 90 42 │ ..4B...B - } +- ALLOC3 (size: 8, align: 4) { .. } ++ ALLOC8 (size: 8, align: 4) { .. } - ALLOC4 (static: SMALL_STAT, size: 8, align: 8) { - ╾ALLOC2╼ │ ╾──────╼ - } + ALLOC0 (static: SMALL_STAT, size: 8, align: 8) { .. } - ALLOC2 (size: 32, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ │ ....░░░░╾──────╼ - 0x10 │ 01 00 00 00 00 00 00 00 00 00 10 41 __ __ __ __ │ ...........A░░░░ - } +- ALLOC4 (size: 32, align: 8) { .. } ++ ALLOC9 (size: 32, align: 8) { .. } - ALLOC3 (size: 4, align: 4) { - 00 00 50 41 │ ..PA - } +- ALLOC5 (size: 4, align: 4) { .. } ++ ALLOC10 (size: 4, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff index f5723cac7d9c8..e4031b65caafe 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff @@ -92,21 +92,13 @@ StorageDead(_1); return; } -+ } + } + -+ ALLOC0 (size: 8, align: 4) { -+ 02 00 00 00 03 00 00 00 │ ........ -+ } ++ ALLOC0 (size: 8, align: 4) { .. } + -+ ALLOC1 (size: 8, align: 4) { -+ 02 00 00 00 03 00 00 00 │ ........ -+ } ++ ALLOC1 (size: 8, align: 4) { .. } + -+ ALLOC2 (size: 8, align: 4) { -+ 02 00 00 00 03 00 00 00 │ ........ -+ } ++ ALLOC2 (size: 8, align: 4) { .. } + -+ ALLOC3 (size: 8, align: 4) { -+ 01 00 00 00 02 00 00 00 │ ........ - } ++ ALLOC3 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff index f5723cac7d9c8..e4031b65caafe 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff @@ -92,21 +92,13 @@ StorageDead(_1); return; } -+ } + } + -+ ALLOC0 (size: 8, align: 4) { -+ 02 00 00 00 03 00 00 00 │ ........ -+ } ++ ALLOC0 (size: 8, align: 4) { .. } + -+ ALLOC1 (size: 8, align: 4) { -+ 02 00 00 00 03 00 00 00 │ ........ -+ } ++ ALLOC1 (size: 8, align: 4) { .. } + -+ ALLOC2 (size: 8, align: 4) { -+ 02 00 00 00 03 00 00 00 │ ........ -+ } ++ ALLOC2 (size: 8, align: 4) { .. } + -+ ALLOC3 (size: 8, align: 4) { -+ 01 00 00 00 02 00 00 00 │ ........ - } ++ ALLOC3 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff index 775a60f1c9603..085c55caaa03c 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff @@ -64,9 +64,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 02 00 00 00 05 20 00 00 │ ..... .. } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff index c4b57579943d4..798b7c10fe8d5 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff @@ -64,9 +64,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 16, align: 8) { -+ 02 00 00 00 00 00 00 00 05 20 00 00 00 00 00 00 │ ......... ...... } ++ ++ ALLOC0 (size: 16, align: 8) { .. } diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff index f7d0d1fb56c3e..a04829af4b532 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff @@ -64,9 +64,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 05 20 00 00 01 00 00 00 │ . ...... } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff index 15f1bd0df51a2..f5521a1e22a47 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff @@ -64,9 +64,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 16, align: 8) { -+ 05 20 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ . .............. } ++ ++ ALLOC0 (size: 16, align: 8) { .. } diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff index 5bf22af6ae83d..0e3f2459fae35 100644 --- a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff @@ -140,9 +140,7 @@ _0 = const (); return; } -+ } -+ -+ ALLOC0 (size: 16, align: 8) { -+ 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ │ .........░░░░░░░ } ++ ++ ALLOC0 (size: 16, align: 8) { .. } diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff index 18d2029e44500..2873d7ef0ab13 100644 --- a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff @@ -140,9 +140,7 @@ _0 = const (); return; } -+ } -+ -+ ALLOC0 (size: 16, align: 8) { -+ 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ │ .........░░░░░░░ } ++ ++ ALLOC0 (size: 16, align: 8) { .. } diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index 0c49e706c9ecf..b5c0cee784688 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:614:19: 614:21}; + let mut _9: {closure@$DIR/gvn.rs:615:19: 615:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:614:19: 614:21}; + let mut _13: {closure@$DIR/gvn.rs:615:19: 615:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:614:19: 614:21}; + let _7: {closure@$DIR/gvn.rs:615:19: 615:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:614:19: 614:21}; +- _7 = {closure@$DIR/gvn.rs:615:19: 615:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; + nop; StorageLive(_9); - _9 = _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index e5f865b74b9f4..7bc6573c13d4d 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:614:19: 614:21}; + let mut _9: {closure@$DIR/gvn.rs:615:19: 615:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:614:19: 614:21}; + let mut _13: {closure@$DIR/gvn.rs:615:19: 615:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:614:19: 614:21}; + let _7: {closure@$DIR/gvn.rs:615:19: 615:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:614:19: 614:21}; +- _7 = {closure@$DIR/gvn.rs:615:19: 615:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; + nop; StorageLive(_9); - _9 = _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff b/tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff index f853942bbb664..e84f91e495d9c 100644 --- a/tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff @@ -13,7 +13,5 @@ } } - ALLOC0 (static: A, size: 2, align: 1) { - 00 __ │ .░ - } + ALLOC0 (static: A, size: 2, align: 1) { .. } diff --git a/tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff b/tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff index f853942bbb664..e84f91e495d9c 100644 --- a/tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff @@ -13,7 +13,5 @@ } } - ALLOC0 (static: A, size: 2, align: 1) { - 00 __ │ .░ - } + ALLOC0 (static: A, size: 2, align: 1) { .. } diff --git a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff index 07c4c7663c154..3eed0473f7fc2 100644 --- a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff @@ -176,13 +176,9 @@ + nop; return; } -+ } + } + -+ ALLOC1 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 │ ................ -+ } ++ ALLOC1 (size: 16, align: 8) { .. } + -+ ALLOC0 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ ................ - } ++ ALLOC0 (size: 16, align: 8) { .. } diff --git a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff index df0f93f1077ee..9a6e255a872ea 100644 --- a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff @@ -176,13 +176,9 @@ + nop; return; } -+ } + } + -+ ALLOC1 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 │ ................ -+ } ++ ALLOC1 (size: 16, align: 8) { .. } + -+ ALLOC0 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ ................ - } ++ ALLOC0 (size: 16, align: 8) { .. } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff index 2f34a62b3d136..45b8d89c0f4fa 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff @@ -61,9 +61,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 04 00 00 00 00 __ __ __ │ .....░░░ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff index da7add371a5bf..e6ee1e6f9a348 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff @@ -61,9 +61,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 04 00 00 00 00 __ __ __ │ .....░░░ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff index 2f34a62b3d136..45b8d89c0f4fa 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff @@ -61,9 +61,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 04 00 00 00 00 __ __ __ │ .....░░░ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff index da7add371a5bf..e6ee1e6f9a348 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff @@ -61,9 +61,7 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 04 00 00 00 00 __ __ __ │ .....░░░ } ++ ++ ALLOC0 (size: 8, align: 4) { .. } From 5e83fafd88c2b2f8510f7b9db8c2748be7eb239c Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 3 Jul 2024 13:02:47 -0500 Subject: [PATCH 07/22] Use libc::pause instead of std::thread::park in wait-for-exit loop --- library/std/src/sys/pal/common/exit_guard.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/pal/common/exit_guard.rs b/library/std/src/sys/pal/common/exit_guard.rs index 37c8f97e45d9d..06f62941db746 100644 --- a/library/std/src/sys/pal/common/exit_guard.rs +++ b/library/std/src/sys/pal/common/exit_guard.rs @@ -10,9 +10,9 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "linux")] { /// Mitigation for /// - /// On `unix` (where `libc::exit` may not be thread-safe), ensure that only one Rust thread - /// calls `libc::exit` (or returns from `main`) by calling this function before calling - /// `libc::exit` (or returning from `main`). + /// On UNIX-like platforms (where `libc::exit` may not be thread-safe), ensure that only one + /// Rust thread calls `libc::exit` (or returns from `main`) by calling this function before + /// calling `libc::exit` (or returning from `main`). /// /// Technically not enough to ensure soundness, since other code directly calling /// libc::exit will still race with this. @@ -23,7 +23,7 @@ cfg_if::cfg_if! { /// This function will return only the first time it is called in a process. /// /// * If it is called again on the same thread as the first call, it will abort. - /// * If it is called again on a different thread, it will `thread::park()` in a loop + /// * If it is called again on a different thread, it will wait in a loop /// (waiting for the process to exit). pub(crate) fn unique_thread_exit() { let this_thread_id = unsafe { libc::gettid() }; @@ -52,9 +52,10 @@ cfg_if::cfg_if! { } Err(_) => { // This is not the first thread to call `unique_thread_exit`. - // Park until the process exits. + // Pause until the process exits. loop { - crate::thread::park(); + // Safety: libc::pause is safe to call. + unsafe { libc::pause(); } } } } @@ -77,10 +78,12 @@ cfg_if::cfg_if! { core::panicking::panic_nounwind("std::process::exit called re-entrantly") } else { // This is not the first thread to call `unique_thread_exit`. + // Pause until the process exits. // Park until the process exits. drop(exiting_thread_id); loop { - crate::thread::park(); + // Safety: libc::pause is safe to call. + unsafe { libc::pause(); } } } } From 897fb6cb1ab30900a03a2806d312f9d22e43459c Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 3 Jul 2024 13:28:44 -0500 Subject: [PATCH 08/22] Use pthread_t instead of numeric thread id --- library/std/src/sys/pal/common/exit_guard.rs | 57 +++++--------------- 1 file changed, 12 insertions(+), 45 deletions(-) diff --git a/library/std/src/sys/pal/common/exit_guard.rs b/library/std/src/sys/pal/common/exit_guard.rs index 06f62941db746..0ea1faacee95d 100644 --- a/library/std/src/sys/pal/common/exit_guard.rs +++ b/library/std/src/sys/pal/common/exit_guard.rs @@ -26,60 +26,27 @@ cfg_if::cfg_if! { /// * If it is called again on a different thread, it will wait in a loop /// (waiting for the process to exit). pub(crate) fn unique_thread_exit() { - let this_thread_id = unsafe { libc::gettid() }; - debug_assert_ne!(this_thread_id, 0, "thread ID cannot be zero"); - #[cfg(target_has_atomic = "32")] - { - use crate::sync::atomic::{AtomicI32, Ordering}; - static EXITING_THREAD_ID: AtomicI32 = AtomicI32::new(0); - match EXITING_THREAD_ID.compare_exchange( - 0, - this_thread_id, - Ordering::Relaxed, - Ordering::Relaxed, - ) { - Ok(_zero) => { - // This is the first thread to call `unique_thread_exit`, - // and this is the first time it is called. - // Set EXITING_THREAD_ID to this thread's ID (done by the - // compare_exchange) and return. - } - Err(id) if id == this_thread_id => { - // This is the first thread to call `unique_thread_exit`, - // but this is the second time it is called. - // Abort the process. - core::panicking::panic_nounwind("std::process::exit called re-entrantly") - } - Err(_) => { - // This is not the first thread to call `unique_thread_exit`. - // Pause until the process exits. - loop { - // Safety: libc::pause is safe to call. - unsafe { libc::pause(); } - } - } - } - } - #[cfg(not(target_has_atomic = "32"))] - { - use crate::sync::{Mutex, PoisonError}; - static EXITING_THREAD_ID: Mutex = Mutex::new(0); - let mut exiting_thread_id = - EXITING_THREAD_ID.lock().unwrap_or_else(PoisonError::into_inner); - if *exiting_thread_id == 0 { + let this_thread_id = unsafe { libc::pthread_self() }; + use crate::sync::{Mutex, PoisonError}; + static EXITING_THREAD_ID: Mutex> = Mutex::new(None); + let mut exiting_thread_id = + EXITING_THREAD_ID.lock().unwrap_or_else(PoisonError::into_inner); + match *exiting_thread_id { + None => { // This is the first thread to call `unique_thread_exit`, // and this is the first time it is called. // Set EXITING_THREAD_ID to this thread's ID and return. - *exiting_thread_id = this_thread_id; - } else if *exiting_thread_id == this_thread_id { + *exiting_thread_id = Some(this_thread_id); + }, + Some(exiting_thread_id) if exiting_thread_id == this_thread_id => { // This is the first thread to call `unique_thread_exit`, // but this is the second time it is called. // Abort the process. core::panicking::panic_nounwind("std::process::exit called re-entrantly") - } else { + } + Some(_) => { // This is not the first thread to call `unique_thread_exit`. // Pause until the process exits. - // Park until the process exits. drop(exiting_thread_id); loop { // Safety: libc::pause is safe to call. From b512608275fed67cfccd05bea91d48d708ea7ae9 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 3 Jul 2024 13:33:32 -0500 Subject: [PATCH 09/22] Remove Miri special-case --- library/std/src/sys/pal/common/exit_guard.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/library/std/src/sys/pal/common/exit_guard.rs b/library/std/src/sys/pal/common/exit_guard.rs index 0ea1faacee95d..eb2c14cdecc71 100644 --- a/library/std/src/sys/pal/common/exit_guard.rs +++ b/library/std/src/sys/pal/common/exit_guard.rs @@ -1,13 +1,5 @@ cfg_if::cfg_if! { - if #[cfg(miri)] { - /// Mitigation for - /// - /// This mitigation is not necessary when running under Miri, so this function does nothing - /// when running under Miri. - pub(crate) fn unique_thread_exit() { - // Mitigation not required on Miri, where `exit` is thread-safe. - } - } else if #[cfg(target_os = "linux")] { + if #[cfg(target_os = "linux")] { /// Mitigation for /// /// On UNIX-like platforms (where `libc::exit` may not be thread-safe), ensure that only one From b4149c6ad479cb35006355a1f1a3c0992a9f8b0e Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 3 Jul 2024 13:45:37 -0500 Subject: [PATCH 10/22] Move unique_thread_exit call to lang_start_internal so it is not in a generic function, and wrap it in `catch_unwind` --- library/std/src/rt.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 376bf3440693e..8a6f3fe291a75 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -144,6 +144,10 @@ fn lang_start_internal( rtabort!("drop of the panic payload panicked"); }); panic::catch_unwind(cleanup).map_err(rt_abort)?; + // Guard against multple threads calling `libc::exit` concurrently. + // See the documentation for `unique_thread_exit` for more information. + panic::catch_unwind(|| crate::sys::common::exit_guard::unique_thread_exit()) + .map_err(rt_abort)?; ret_code } @@ -161,8 +165,5 @@ fn lang_start( argv, sigpipe, ); - // Guard against multple threads calling `libc::exit` concurrently. - // See the documentation for `unique_thread_exit` for more information. - crate::sys::common::exit_guard::unique_thread_exit(); v } From 81b1f929f346f404953b02f605506c0522bcf7ee Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Wed, 3 Jul 2024 18:00:42 +0000 Subject: [PATCH 11/22] CFI: Support provided methods on traits Provided methods currently don't get type erasure performed on them because they are not in an `impl` block. If we are instantiating a method that is an associated item, but *not* in an impl block, treat it as a provided method instead. --- .../cfi/typeid/itanium_cxx_abi/transform.rs | 93 +++++++++++-------- tests/ui/sanitizer/cfi-supertraits.rs | 6 ++ 2 files changed, 62 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index f0f2d1fefd2f3..d4b4e27d5286e 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -9,10 +9,10 @@ use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{ - self, ExistentialPredicateStableCmpExt as _, Instance, IntTy, List, Ty, TyCtxt, TypeFoldable, - TypeVisitableExt, UintTy, + self, ExistentialPredicateStableCmpExt as _, Instance, IntTy, List, TraitRef, Ty, TyCtxt, + TypeFoldable, TypeVisitableExt, UintTy, }; -use rustc_span::sym; +use rustc_span::{def_id::DefId, sym}; use rustc_trait_selection::traits; use std::iter; use tracing::{debug, instrument}; @@ -360,41 +360,29 @@ pub fn transform_instance<'tcx>( if !options.contains(TransformTyOptions::USE_CONCRETE_SELF) { // Perform type erasure for calls on trait objects by transforming self into a trait object // of the trait that defines the method. - if let Some(impl_id) = tcx.impl_of_method(instance.def_id()) - && let Some(trait_ref) = tcx.impl_trait_ref(impl_id) - { - let impl_method = tcx.associated_item(instance.def_id()); - let method_id = impl_method - .trait_item_def_id - .expect("Part of a trait implementation, but not linked to the def_id?"); - let trait_method = tcx.associated_item(method_id); - let trait_id = trait_ref.skip_binder().def_id; - if traits::is_vtable_safe_method(tcx, trait_id, trait_method) - && tcx.is_object_safe(trait_id) - { - // Trait methods will have a Self polymorphic parameter, where the concreteized - // implementatation will not. We need to walk back to the more general trait method - let trait_ref = tcx.instantiate_and_normalize_erasing_regions( - instance.args, - ty::ParamEnv::reveal_all(), - trait_ref, - ); - let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref)); + if let Some((trait_ref, method_id, ancestor)) = implemented_method(tcx, instance) { + // Trait methods will have a Self polymorphic parameter, where the concreteized + // implementatation will not. We need to walk back to the more general trait method + let trait_ref = tcx.instantiate_and_normalize_erasing_regions( + instance.args, + ty::ParamEnv::reveal_all(), + trait_ref, + ); + let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref)); - // At the call site, any call to this concrete function through a vtable will be - // `Virtual(method_id, idx)` with appropriate arguments for the method. Since we have the - // original method id, and we've recovered the trait arguments, we can make the callee - // instance we're computing the alias set for match the caller instance. - // - // Right now, our code ignores the vtable index everywhere, so we use 0 as a placeholder. - // If we ever *do* start encoding the vtable index, we will need to generate an alias set - // based on which vtables we are putting this method into, as there will be more than one - // index value when supertraits are involved. - instance.def = ty::InstanceKind::Virtual(method_id, 0); - let abstract_trait_args = - tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1)); - instance.args = instance.args.rebase_onto(tcx, impl_id, abstract_trait_args); - } + // At the call site, any call to this concrete function through a vtable will be + // `Virtual(method_id, idx)` with appropriate arguments for the method. Since we have the + // original method id, and we've recovered the trait arguments, we can make the callee + // instance we're computing the alias set for match the caller instance. + // + // Right now, our code ignores the vtable index everywhere, so we use 0 as a placeholder. + // If we ever *do* start encoding the vtable index, we will need to generate an alias set + // based on which vtables we are putting this method into, as there will be more than one + // index value when supertraits are involved. + instance.def = ty::InstanceKind::Virtual(method_id, 0); + let abstract_trait_args = + tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1)); + instance.args = instance.args.rebase_onto(tcx, ancestor, abstract_trait_args); } else if tcx.is_closure_like(instance.def_id()) { // We're either a closure or a coroutine. Our goal is to find the trait we're defined on, // instantiate it, and take the type of its only method as our own. @@ -452,3 +440,34 @@ pub fn transform_instance<'tcx>( instance } + +fn implemented_method<'tcx>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, +) -> Option<(ty::EarlyBinder<'tcx, TraitRef<'tcx>>, DefId, DefId)> { + let trait_ref; + let method_id; + let trait_id; + let trait_method; + let ancestor = if let Some(impl_id) = tcx.impl_of_method(instance.def_id()) { + // Implementation in an `impl` block + trait_ref = tcx.impl_trait_ref(impl_id)?; + let impl_method = tcx.associated_item(instance.def_id()); + method_id = impl_method.trait_item_def_id?; + trait_method = tcx.associated_item(method_id); + trait_id = trait_ref.skip_binder().def_id; + impl_id + } else if let Some(trait_method_bound) = tcx.opt_associated_item(instance.def_id()) { + // Provided method in a `trait` block + trait_method = trait_method_bound; + method_id = instance.def_id(); + trait_id = tcx.trait_of_item(method_id)?; + trait_ref = ty::EarlyBinder::bind(TraitRef::from_method(tcx, trait_id, instance.args)); + trait_id + } else { + return None; + }; + let vtable_possible = + traits::is_vtable_safe_method(tcx, trait_id, trait_method) && tcx.is_object_safe(trait_id); + vtable_possible.then_some((trait_ref, method_id, ancestor)) +} diff --git a/tests/ui/sanitizer/cfi-supertraits.rs b/tests/ui/sanitizer/cfi-supertraits.rs index ed3d722ebb78e..4bb6177577f7c 100644 --- a/tests/ui/sanitizer/cfi-supertraits.rs +++ b/tests/ui/sanitizer/cfi-supertraits.rs @@ -16,6 +16,9 @@ trait Parent1 { type P1; fn p1(&self) -> Self::P1; + fn d(&self) -> i32 { + 42 + } } trait Parent2 { @@ -60,14 +63,17 @@ fn main() { x.c(); x.p1(); x.p2(); + x.d(); // Parents can be created and access their methods. let y = &Foo as &dyn Parent1; y.p1(); + y.d(); let z = &Foo as &dyn Parent2; z.p2(); // Trait upcasting works let x1 = x as &dyn Parent1; x1.p1(); + x1.d(); let x2 = x as &dyn Parent2; x2.p2(); } From fe5581dd31eb1b86c915e5c3eaae9ebfdea28037 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 4 Jul 2024 09:55:00 +0000 Subject: [PATCH 12/22] Fix import suggestion ice --- compiler/rustc_resolve/src/diagnostics.rs | 10 ++--- ...import-ice-issue-127302.edition2015.stderr | 41 +++++++++++++++++++ ...import-ice-issue-127302.edition2021.stderr | 41 +++++++++++++++++++ .../suggest-import-ice-issue-127302.rs | 12 ++++++ ...st-import-issue-120074.edition2015.stderr} | 2 +- ...est-import-issue-120074.edition2021.stderr | 23 +++++++++++ .../ui/imports/suggest-import-issue-120074.rs | 2 + 7 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 tests/ui/imports/suggest-import-ice-issue-127302.edition2015.stderr create mode 100644 tests/ui/imports/suggest-import-ice-issue-127302.edition2021.stderr create mode 100644 tests/ui/imports/suggest-import-ice-issue-127302.rs rename tests/ui/imports/{suggest-import-issue-120074.stderr => suggest-import-issue-120074.edition2015.stderr} (93%) create mode 100644 tests/ui/imports/suggest-import-issue-120074.edition2021.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 50a4e03d233a7..7e1251b3a3a5d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1989,12 +1989,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(candidate) = candidates.get(0) { let path = { // remove the possible common prefix of the path - let start_index = (0..failed_segment_idx) - .find(|&i| path[i].ident != candidate.path.segments[i].ident) + let len = candidate.path.segments.len(); + let start_index = (0..=failed_segment_idx.min(len - 1)) + .find(|&i| path[i].ident.name != candidate.path.segments[i].ident.name) .unwrap_or_default(); - let segments = (start_index..=failed_segment_idx) - .map(|s| candidate.path.segments[s].clone()) - .collect(); + let segments = + (start_index..len).map(|s| candidate.path.segments[s].clone()).collect(); Path { segments, span: Span::default(), tokens: None } }; ( diff --git a/tests/ui/imports/suggest-import-ice-issue-127302.edition2015.stderr b/tests/ui/imports/suggest-import-ice-issue-127302.edition2015.stderr new file mode 100644 index 0000000000000..24574c8796b9d --- /dev/null +++ b/tests/ui/imports/suggest-import-ice-issue-127302.edition2015.stderr @@ -0,0 +1,41 @@ +error[E0583]: file not found for module `config` + --> $DIR/suggest-import-ice-issue-127302.rs:3:1 + | +LL | mod config; + | ^^^^^^^^^^^ + | + = help: to create the module `config`, create file "$DIR/config.rs" or "$DIR/config/mod.rs" + = note: if there is a `mod config` elsewhere in the crate already, import it with `use crate::...` instead + +error: format argument must be a string literal + --> $DIR/suggest-import-ice-issue-127302.rs:10:14 + | +LL | println!(args.ctx.compiler.display()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: you might be missing a string literal to format with + | +LL | println!("{}", args.ctx.compiler.display()); + | +++++ + +error[E0425]: cannot find value `args` in this scope + --> $DIR/suggest-import-ice-issue-127302.rs:6:12 + | +LL | match &args.cmd { + | ^^^^ not found in this scope + | +help: consider importing this function + | +LL + use std::env::args; + | + +error[E0532]: expected unit struct, unit variant or constant, found module `crate::config` + --> $DIR/suggest-import-ice-issue-127302.rs:7:9 + | +LL | crate::config => {} + | ^^^^^^^^^^^^^ not a unit struct, unit variant or constant + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0425, E0532, E0583. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/suggest-import-ice-issue-127302.edition2021.stderr b/tests/ui/imports/suggest-import-ice-issue-127302.edition2021.stderr new file mode 100644 index 0000000000000..24574c8796b9d --- /dev/null +++ b/tests/ui/imports/suggest-import-ice-issue-127302.edition2021.stderr @@ -0,0 +1,41 @@ +error[E0583]: file not found for module `config` + --> $DIR/suggest-import-ice-issue-127302.rs:3:1 + | +LL | mod config; + | ^^^^^^^^^^^ + | + = help: to create the module `config`, create file "$DIR/config.rs" or "$DIR/config/mod.rs" + = note: if there is a `mod config` elsewhere in the crate already, import it with `use crate::...` instead + +error: format argument must be a string literal + --> $DIR/suggest-import-ice-issue-127302.rs:10:14 + | +LL | println!(args.ctx.compiler.display()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: you might be missing a string literal to format with + | +LL | println!("{}", args.ctx.compiler.display()); + | +++++ + +error[E0425]: cannot find value `args` in this scope + --> $DIR/suggest-import-ice-issue-127302.rs:6:12 + | +LL | match &args.cmd { + | ^^^^ not found in this scope + | +help: consider importing this function + | +LL + use std::env::args; + | + +error[E0532]: expected unit struct, unit variant or constant, found module `crate::config` + --> $DIR/suggest-import-ice-issue-127302.rs:7:9 + | +LL | crate::config => {} + | ^^^^^^^^^^^^^ not a unit struct, unit variant or constant + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0425, E0532, E0583. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/suggest-import-ice-issue-127302.rs b/tests/ui/imports/suggest-import-ice-issue-127302.rs new file mode 100644 index 0000000000000..6b8d4c718310e --- /dev/null +++ b/tests/ui/imports/suggest-import-ice-issue-127302.rs @@ -0,0 +1,12 @@ +//@ revisions: edition2015 edition2021 + +mod config; //~ ERROR file not found for module + +fn main() { + match &args.cmd { //~ ERROR cannot find value `args` in this scope + crate::config => {} //~ ERROR expected unit struct, unit variant or constant, found module `crate::config` + } + + println!(args.ctx.compiler.display()); + //~^ ERROR format argument must be a string literal +} diff --git a/tests/ui/imports/suggest-import-issue-120074.stderr b/tests/ui/imports/suggest-import-issue-120074.edition2015.stderr similarity index 93% rename from tests/ui/imports/suggest-import-issue-120074.stderr rename to tests/ui/imports/suggest-import-issue-120074.edition2015.stderr index c1dff93bbdbff..414eeee0fedc8 100644 --- a/tests/ui/imports/suggest-import-issue-120074.stderr +++ b/tests/ui/imports/suggest-import-issue-120074.edition2015.stderr @@ -1,5 +1,5 @@ error[E0433]: failed to resolve: unresolved import - --> $DIR/suggest-import-issue-120074.rs:10:35 + --> $DIR/suggest-import-issue-120074.rs:12:35 | LL | println!("Hello, {}!", crate::bar::do_the_thing); | ^^^ unresolved import diff --git a/tests/ui/imports/suggest-import-issue-120074.edition2021.stderr b/tests/ui/imports/suggest-import-issue-120074.edition2021.stderr new file mode 100644 index 0000000000000..414eeee0fedc8 --- /dev/null +++ b/tests/ui/imports/suggest-import-issue-120074.edition2021.stderr @@ -0,0 +1,23 @@ +error[E0433]: failed to resolve: unresolved import + --> $DIR/suggest-import-issue-120074.rs:12:35 + | +LL | println!("Hello, {}!", crate::bar::do_the_thing); + | ^^^ unresolved import + | +help: a similar path exists + | +LL | println!("Hello, {}!", crate::foo::bar::do_the_thing); + | ~~~~~~~~ +help: consider importing this module + | +LL + use foo::bar; + | +help: if you import `bar`, refer to it directly + | +LL - println!("Hello, {}!", crate::bar::do_the_thing); +LL + println!("Hello, {}!", bar::do_the_thing); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/imports/suggest-import-issue-120074.rs b/tests/ui/imports/suggest-import-issue-120074.rs index a798e9eeeb809..7b6b5c73103a1 100644 --- a/tests/ui/imports/suggest-import-issue-120074.rs +++ b/tests/ui/imports/suggest-import-issue-120074.rs @@ -1,3 +1,5 @@ +//@ revisions: edition2015 edition2021 + pub mod foo { pub mod bar { pub fn do_the_thing() -> usize { From 9de76e3201a557f0ea9b076c8b38629c5f2b60d0 Mon Sep 17 00:00:00 2001 From: zachs18 <8355914+zachs18@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:45:03 -0500 Subject: [PATCH 13/22] Update library/std/src/sys/pal/common/exit_guard.rs Co-authored-by: Ralf Jung --- library/std/src/sys/pal/common/exit_guard.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/common/exit_guard.rs b/library/std/src/sys/pal/common/exit_guard.rs index eb2c14cdecc71..a1b0309b003ea 100644 --- a/library/std/src/sys/pal/common/exit_guard.rs +++ b/library/std/src/sys/pal/common/exit_guard.rs @@ -2,12 +2,14 @@ cfg_if::cfg_if! { if #[cfg(target_os = "linux")] { /// Mitigation for /// - /// On UNIX-like platforms (where `libc::exit` may not be thread-safe), ensure that only one + /// On glibc, `libc::exit` has been observed to not always be thread-safe. + /// It is currently unclear whether that is a glibc bug or allowed by the standard. + /// To mitigate this problem, we ensure that only one /// Rust thread calls `libc::exit` (or returns from `main`) by calling this function before /// calling `libc::exit` (or returning from `main`). /// - /// Technically not enough to ensure soundness, since other code directly calling - /// libc::exit will still race with this. + /// Technically, this is not enough to ensure soundness, since other code directly calling + /// `libc::exit` will still race with this. /// /// *This function does not itself call `libc::exit`.* This is so it can also be used /// to guard returning from `main`. From a6093701437be909614bc49d63406dfaa63d3b13 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Fri, 5 Jul 2024 16:59:57 -0500 Subject: [PATCH 14/22] Move exit guard from sys::common::exit_guard to sys::exit_guard. --- library/std/src/rt.rs | 3 +-- library/std/src/sys/{pal/common => }/exit_guard.rs | 0 library/std/src/sys/mod.rs | 1 + library/std/src/sys/pal/common/mod.rs | 1 - library/std/src/sys/pal/unix/os.rs | 2 +- 5 files changed, 3 insertions(+), 4 deletions(-) rename library/std/src/sys/{pal/common => }/exit_guard.rs (100%) diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 8a6f3fe291a75..c0a1c5f5594ae 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -146,8 +146,7 @@ fn lang_start_internal( panic::catch_unwind(cleanup).map_err(rt_abort)?; // Guard against multple threads calling `libc::exit` concurrently. // See the documentation for `unique_thread_exit` for more information. - panic::catch_unwind(|| crate::sys::common::exit_guard::unique_thread_exit()) - .map_err(rt_abort)?; + panic::catch_unwind(|| crate::sys::exit_guard::unique_thread_exit()).map_err(rt_abort)?; ret_code } diff --git a/library/std/src/sys/pal/common/exit_guard.rs b/library/std/src/sys/exit_guard.rs similarity index 100% rename from library/std/src/sys/pal/common/exit_guard.rs rename to library/std/src/sys/exit_guard.rs diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 8aa35c40fe052..22ebc979bf7e4 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -3,6 +3,7 @@ /// descriptors. mod pal; +pub(crate) mod exit_guard; mod personality; pub mod backtrace; diff --git a/library/std/src/sys/pal/common/mod.rs b/library/std/src/sys/pal/common/mod.rs index cc1dceb63e2f5..29fc0835d7666 100644 --- a/library/std/src/sys/pal/common/mod.rs +++ b/library/std/src/sys/pal/common/mod.rs @@ -11,7 +11,6 @@ #![allow(dead_code)] pub mod alloc; -pub mod exit_guard; pub mod small_c_string; #[cfg(test)] diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 3f598a095c156..397a0debe58c3 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -758,7 +758,7 @@ pub fn home_dir() -> Option { } pub fn exit(code: i32) -> ! { - crate::sys::common::exit_guard::unique_thread_exit(); + crate::sys::exit_guard::unique_thread_exit(); unsafe { libc::exit(code as c_int) } } From 5db165504ada6fde86f93d275a0d6380263ee381 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Fri, 5 Jul 2024 17:59:46 -0500 Subject: [PATCH 15/22] Attempt to fix CI --- library/std/src/sys/exit_guard.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/sys/exit_guard.rs b/library/std/src/sys/exit_guard.rs index a1b0309b003ea..ad6246cc83180 100644 --- a/library/std/src/sys/exit_guard.rs +++ b/library/std/src/sys/exit_guard.rs @@ -19,6 +19,7 @@ cfg_if::cfg_if! { /// * If it is called again on the same thread as the first call, it will abort. /// * If it is called again on a different thread, it will wait in a loop /// (waiting for the process to exit). + #[cfg_attr(any(test, doctest), allow(dead_code))] pub(crate) fn unique_thread_exit() { let this_thread_id = unsafe { libc::pthread_self() }; use crate::sync::{Mutex, PoisonError}; @@ -54,6 +55,7 @@ cfg_if::cfg_if! { /// /// Mitigation is ***NOT*** implemented on this platform, either because this platform /// is not affected, or because mitigation is not yet implemented for this platform. + #[cfg_attr(any(test, doctest), allow(dead_code))] pub(crate) fn unique_thread_exit() { // Mitigation not required on platforms where `exit` is thread-safe. } From 98010765f949307bf53ebb692e45e428ba318aa1 Mon Sep 17 00:00:00 2001 From: zachs18 <8355914+zachs18@users.noreply.github.com> Date: Sun, 7 Jul 2024 10:44:47 -0500 Subject: [PATCH 16/22] Move/change declaration of `mod exit_guard;` --- library/std/src/sys/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 22ebc979bf7e4..4092e6080d548 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -3,11 +3,11 @@ /// descriptors. mod pal; -pub(crate) mod exit_guard; mod personality; pub mod backtrace; pub mod cmath; +pub mod exit_guard; pub mod os_str; pub mod path; pub mod sync; From 8bcbab5dd1c6449c2acd3ea6a94b245c0936722d Mon Sep 17 00:00:00 2001 From: zachs18 <8355914+zachs18@users.noreply.github.com> Date: Mon, 8 Jul 2024 09:19:25 -0500 Subject: [PATCH 17/22] Attempt to fix CI --- library/std/src/sys/exit_guard.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/exit_guard.rs b/library/std/src/sys/exit_guard.rs index ad6246cc83180..5a090f506661d 100644 --- a/library/std/src/sys/exit_guard.rs +++ b/library/std/src/sys/exit_guard.rs @@ -1,5 +1,14 @@ cfg_if::cfg_if! { if #[cfg(target_os = "linux")] { + /// pthread_t is a pointer on some platforms, + /// so we wrap it in this to impl Send + Sync. + #[derive(Clone, Copy)] + #[repr(transparent)] + struct PThread(libc::pthread_t); + // Safety: pthread_t is safe to send between threads + unsafe impl Send for PThread {} + // Safety: pthread_t is safe to share between threads + unsafe impl Sync for PThread {} /// Mitigation for /// /// On glibc, `libc::exit` has been observed to not always be thread-safe. @@ -23,7 +32,7 @@ cfg_if::cfg_if! { pub(crate) fn unique_thread_exit() { let this_thread_id = unsafe { libc::pthread_self() }; use crate::sync::{Mutex, PoisonError}; - static EXITING_THREAD_ID: Mutex> = Mutex::new(None); + static EXITING_THREAD_ID: Mutex> = Mutex::new(None); let mut exiting_thread_id = EXITING_THREAD_ID.lock().unwrap_or_else(PoisonError::into_inner); match *exiting_thread_id { @@ -31,9 +40,9 @@ cfg_if::cfg_if! { // This is the first thread to call `unique_thread_exit`, // and this is the first time it is called. // Set EXITING_THREAD_ID to this thread's ID and return. - *exiting_thread_id = Some(this_thread_id); + *exiting_thread_id = Some(PThread(this_thread_id)); }, - Some(exiting_thread_id) if exiting_thread_id == this_thread_id => { + Some(exiting_thread_id) if exiting_thread_id.0 == this_thread_id => { // This is the first thread to call `unique_thread_exit`, // but this is the second time it is called. // Abort the process. From 87856c4461c29eb8c8ef7e3fb28ccfcbd41e4120 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Mon, 24 Jun 2024 22:37:44 +0000 Subject: [PATCH 18/22] add lint for inline asm labels that look like binary --- compiler/rustc_lint/messages.ftl | 17 +- compiler/rustc_lint/src/builtin.rs | 131 +++++++++++---- compiler/rustc_lint/src/lib.rs | 2 +- compiler/rustc_lint/src/lints.rs | 30 +++- tests/ui/asm/binary_asm_labels.rs | 17 ++ tests/ui/asm/binary_asm_labels.stderr | 43 +++++ tests/ui/asm/named-asm-labels.rs | 24 ++- tests/ui/asm/named-asm-labels.stderr | 224 ++++++++++++++++++++------ 8 files changed, 397 insertions(+), 91 deletions(-) create mode 100644 tests/ui/asm/binary_asm_labels.rs create mode 100644 tests/ui/asm/binary_asm_labels.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 3e952558d29d3..9d8271a6acb36 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -52,10 +52,6 @@ lint_builtin_allow_internal_unsafe = lint_builtin_anonymous_params = anonymous parameters are deprecated and will be removed in the next edition .suggestion = try naming the parameter or explicitly ignoring it -lint_builtin_asm_labels = avoid using named labels in inline assembly - .help = only local labels of the form `:` should be used in inline asm - .note = see the asm section of Rust By Example for more information - lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature .previous_decl_label = `{$orig}` previously declared here .mismatch_label = this signature doesn't match the previous declaration @@ -399,6 +395,19 @@ lint_incomplete_include = lint_inner_macro_attribute_unstable = inner macro attributes are unstable +lint_invalid_asm_label_binary = avoid using labels containing only the digits `0` and `1` in inline assembly + .label = use a different label that doesn't start with `0` or `1` + .note = an LLVM bug makes these labels ambiguous with a binary literal number + .note = see for more information + +lint_invalid_asm_label_format_arg = avoid using named labels in inline assembly + .help = only local labels of the form `:` should be used in inline asm + .note1 = format arguments may expand to a non-numeric value + .note2 = see the asm section of Rust By Example for more information +lint_invalid_asm_label_named = avoid using named labels in inline assembly + .help = only local labels of the form `:` should be used in inline asm + .note = see the asm section of Rust By Example for more information +lint_invalid_asm_label_no_span = the label may be declared in the expansion of a macro lint_invalid_crate_type_value = invalid `crate_type` value .suggestion = did you mean diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 79c8046f9b741..a661c74cf91d9 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -30,13 +30,13 @@ use crate::{ BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, - BuiltinMutablesTransmutes, BuiltinNamedAsmLabel, BuiltinNoMangleGeneric, - BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, - BuiltinTypeAliasGenericBounds, BuiltinTypeAliasGenericBoundsSuggestion, - BuiltinTypeAliasWhereClause, BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, + BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, + BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasGenericBounds, + BuiltinTypeAliasGenericBoundsSuggestion, BuiltinTypeAliasWhereClause, + BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, - BuiltinWhileTrue, SuggestChangingAssocTypes, + BuiltinWhileTrue, InvalidAsmLabel, SuggestChangingAssocTypes, }, EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext, }; @@ -45,7 +45,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::{self, expr_to_string}; -use rustc_errors::{Applicability, LintDiagnostic, MultiSpan}; +use rustc_errors::{Applicability, LintDiagnostic}; use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -69,7 +69,6 @@ use rustc_target::abi::Abi; use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy}; -use tracing::debug; use crate::nonstandard_style::{method_context, MethodLateContext}; @@ -2728,10 +2727,52 @@ declare_lint! { "named labels in inline assembly", } -declare_lint_pass!(NamedAsmLabels => [NAMED_ASM_LABELS]); +declare_lint! { + /// The `binary_asm_labels` lint detects the use of numeric labels containing only binary + /// digits in the inline `asm!` macro. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// # #![feature(asm_experimental_arch)] + /// use std::arch::asm; + /// + /// fn main() { + /// unsafe { + /// asm!("0: jmp 0b"); + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// A [LLVM bug] causes this code to fail to compile because it interprets the `0b` as a binary + /// literal instead of a reference to the previous local label `0`. Note that even though the + /// bug is marked as fixed, it only fixes a specific usage of intel syntax within standalone + /// files, not inline assembly. To work around this bug, don't use labels that could be + /// confused with a binary literal. + /// + /// See the explanation in [Rust By Example] for more details. + /// + /// [LLVM bug]: https://bugs.llvm.org/show_bug.cgi?id=36144 + /// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels + pub BINARY_ASM_LABELS, + Deny, + "labels in inline assembly containing only 0 or 1 digits", +} -impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { - #[allow(rustc::diagnostic_outside_of_impl)] +declare_lint_pass!(AsmLabels => [NAMED_ASM_LABELS, BINARY_ASM_LABELS]); + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum AsmLabelKind { + Named, + FormatArg, + Binary, +} + +impl<'tcx> LateLintPass<'tcx> for AsmLabels { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { if let hir::Expr { kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, options, .. }), @@ -2759,7 +2800,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { None }; - let mut found_labels = Vec::new(); + // diagnostics are emitted per-template, so this is created here as opposed to the outer loop + let mut spans = Vec::new(); // A semicolon might not actually be specified as a separator for all targets, but // it seems like LLVM accepts it always. @@ -2782,16 +2824,21 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { // Whether a { bracket has been seen and its } hasn't been found yet. let mut in_bracket = false; + let mut label_kind = AsmLabelKind::Named; - // A label starts with an ASCII alphabetic character or . or _ // A label can also start with a format arg, if it's not a raw asm block. if !raw && start == '{' { in_bracket = true; + label_kind = AsmLabelKind::FormatArg; + } else if matches!(start, '0' | '1') { + // Binary labels have only the characters `0` or `1`. + label_kind = AsmLabelKind::Binary; } else if !(start.is_ascii_alphabetic() || matches!(start, '.' | '_')) { + // Named labels start with ASCII letters, `.` or `_`. + // anything else is not a label break 'label_loop; } - // Labels continue with ASCII alphanumeric characters, _, or $ for c in chars { // Inside a template format arg, any character is permitted for the // puproses of label detection because we assume that it can be @@ -2812,8 +2859,18 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { } else if !raw && c == '{' { // Start of a format arg. in_bracket = true; + label_kind = AsmLabelKind::FormatArg; } else { - if !(c.is_ascii_alphanumeric() || matches!(c, '_' | '$')) { + let can_continue = match label_kind { + // Format arg labels are considered to be named labels for the purposes + // of continuing outside of their {} pair. + AsmLabelKind::Named | AsmLabelKind::FormatArg => { + c.is_ascii_alphanumeric() || matches!(c, '_' | '$') + } + AsmLabelKind::Binary => matches!(c, '0' | '1'), + }; + + if !can_continue { // The potential label had an invalid character inside it, it // cannot be a label. break 'label_loop; @@ -2821,25 +2878,41 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { } } - // If all characters passed the label checks, this is likely a label. - found_labels.push(possible_label); + // If all characters passed the label checks, this is a label. + spans.push((find_label_span(possible_label), label_kind)); start_idx = idx + 1; } } - debug!("NamedAsmLabels::check_expr(): found_labels: {:#?}", &found_labels); - - if found_labels.len() > 0 { - let spans = found_labels - .into_iter() - .filter_map(|label| find_label_span(label)) - .collect::>(); - // If there were labels but we couldn't find a span, combine the warnings and - // use the template span. - let target_spans: MultiSpan = - if spans.len() > 0 { spans.into() } else { (*template_span).into() }; - - cx.emit_span_lint(NAMED_ASM_LABELS, target_spans, BuiltinNamedAsmLabel); + for (span, label_kind) in spans { + let missing_precise_span = span.is_none(); + let span = span.unwrap_or(*template_span); + match label_kind { + AsmLabelKind::Named => { + cx.emit_span_lint( + NAMED_ASM_LABELS, + span, + InvalidAsmLabel::Named { missing_precise_span }, + ); + } + AsmLabelKind::FormatArg => { + cx.emit_span_lint( + NAMED_ASM_LABELS, + span, + InvalidAsmLabel::FormatArg { missing_precise_span }, + ); + } + AsmLabelKind::Binary => { + // the binary asm issue only occurs when using intel syntax + if !options.contains(InlineAsmOptions::ATT_SYNTAX) { + cx.emit_span_lint( + BINARY_ASM_LABELS, + span, + InvalidAsmLabel::Binary { missing_precise_span, span }, + ) + } + } + }; } } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 17f9d4421aef2..31b76b7c6ff82 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -220,7 +220,7 @@ late_lint_methods!( NoopMethodCall: NoopMethodCall, EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums, InvalidAtomicOrdering: InvalidAtomicOrdering, - NamedAsmLabels: NamedAsmLabels, + AsmLabels: AsmLabels, OpaqueHiddenInferredBound: OpaqueHiddenInferredBound, MultipleSupertraitUpcastable: MultipleSupertraitUpcastable, MapUnitFn: MapUnitFn, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 7c5640f5959a0..b3f715c217475 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2040,10 +2040,32 @@ pub struct UnitBindingsDiag { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_asm_labels)] -#[help] -#[note] -pub struct BuiltinNamedAsmLabel; +pub enum InvalidAsmLabel { + #[diag(lint_invalid_asm_label_named)] + #[help] + #[note] + Named { + #[note(lint_invalid_asm_label_no_span)] + missing_precise_span: bool, + }, + #[diag(lint_invalid_asm_label_format_arg)] + #[help] + #[note(lint_note1)] + #[note(lint_note2)] + FormatArg { + #[note(lint_invalid_asm_label_no_span)] + missing_precise_span: bool, + }, + #[diag(lint_invalid_asm_label_binary)] + #[note] + Binary { + #[note(lint_invalid_asm_label_no_span)] + missing_precise_span: bool, + // hack to get a label on the whole span, must match the emitted span + #[label] + span: Span, + }, +} #[derive(Subdiagnostic)] pub enum UnexpectedCfgCargoHelp { diff --git a/tests/ui/asm/binary_asm_labels.rs b/tests/ui/asm/binary_asm_labels.rs new file mode 100644 index 0000000000000..3f545880254c2 --- /dev/null +++ b/tests/ui/asm/binary_asm_labels.rs @@ -0,0 +1,17 @@ +//@ needs-asm-support +//@ only-x86_64 + +// tests that labels containing only the digits 0 and 1 are rejected +// uses of such labels can sometimes be interpreted as a binary literal + +use std::arch::{asm, global_asm}; + +fn main() { + unsafe { + asm!("0: jmp 0b"); //~ ERROR avoid using labels containing only the digits + asm!("1: jmp 1b"); //~ ERROR avoid using labels containing only the digits + asm!("10: jmp 10b"); //~ ERROR avoid using labels containing only the digits + asm!("01: jmp 01b"); //~ ERROR avoid using labels containing only the digits + asm!("1001101: jmp 1001101b"); //~ ERROR avoid using labels containing only the digits + } +} diff --git a/tests/ui/asm/binary_asm_labels.stderr b/tests/ui/asm/binary_asm_labels.stderr new file mode 100644 index 0000000000000..1f2943084f1eb --- /dev/null +++ b/tests/ui/asm/binary_asm_labels.stderr @@ -0,0 +1,43 @@ +error: avoid using labels containing only the digits `0` and `1` in inline assembly + --> $DIR/binary_asm_labels.rs:11:15 + | +LL | asm!("0: jmp 0b"); + | ^ use a different label that doesn't start with `0` or `1` + | + = note: an LLVM bug makes these labels ambiguous with a binary literal number + = note: `#[deny(binary_asm_labels)]` on by default + +error: avoid using labels containing only the digits `0` and `1` in inline assembly + --> $DIR/binary_asm_labels.rs:12:15 + | +LL | asm!("1: jmp 1b"); + | ^ use a different label that doesn't start with `0` or `1` + | + = note: an LLVM bug makes these labels ambiguous with a binary literal number + +error: avoid using labels containing only the digits `0` and `1` in inline assembly + --> $DIR/binary_asm_labels.rs:13:15 + | +LL | asm!("10: jmp 10b"); + | ^^ use a different label that doesn't start with `0` or `1` + | + = note: an LLVM bug makes these labels ambiguous with a binary literal number + +error: avoid using labels containing only the digits `0` and `1` in inline assembly + --> $DIR/binary_asm_labels.rs:14:15 + | +LL | asm!("01: jmp 01b"); + | ^^ use a different label that doesn't start with `0` or `1` + | + = note: an LLVM bug makes these labels ambiguous with a binary literal number + +error: avoid using labels containing only the digits `0` and `1` in inline assembly + --> $DIR/binary_asm_labels.rs:15:15 + | +LL | asm!("1001101: jmp 1001101b"); + | ^^^^^^^ use a different label that doesn't start with `0` or `1` + | + = note: an LLVM bug makes these labels ambiguous with a binary literal number + +error: aborting due to 5 previous errors + diff --git a/tests/ui/asm/named-asm-labels.rs b/tests/ui/asm/named-asm-labels.rs index 96ccdef75b0ce..d2ca6fe8808bc 100644 --- a/tests/ui/asm/named-asm-labels.rs +++ b/tests/ui/asm/named-asm-labels.rs @@ -28,11 +28,13 @@ fn main() { // Multiple labels on one line asm!("foo: bar1: nop"); //~^ ERROR avoid using named labels + //~^^ ERROR avoid using named labels // Multiple lines asm!("foo1: nop", "nop"); //~ ERROR avoid using named labels asm!("foo2: foo3: nop", "nop"); //~^ ERROR avoid using named labels + //~^^ ERROR avoid using named labels asm!("nop", "foo4: nop"); //~ ERROR avoid using named labels asm!("foo5: nop", "foo6: nop"); //~^ ERROR avoid using named labels @@ -41,16 +43,19 @@ fn main() { // Statement separator asm!("foo7: nop; foo8: nop"); //~^ ERROR avoid using named labels + //~^^ ERROR avoid using named labels asm!("foo9: nop; nop"); //~ ERROR avoid using named labels asm!("nop; foo10: nop"); //~ ERROR avoid using named labels // Escaped newline asm!("bar2: nop\n bar3: nop"); //~^ ERROR avoid using named labels + //~^^ ERROR avoid using named labels asm!("bar4: nop\n nop"); //~ ERROR avoid using named labels asm!("nop\n bar5: nop"); //~ ERROR avoid using named labels asm!("nop\n bar6: bar7: nop"); //~^ ERROR avoid using named labels + //~^^ ERROR avoid using named labels // Raw strings asm!( @@ -60,6 +65,7 @@ fn main() { " ); //~^^^^ ERROR avoid using named labels + //~^^^^ ERROR avoid using named labels asm!( r###" @@ -81,9 +87,15 @@ fn main() { asm!("blah1: 2bar: nop"); //~ ERROR avoid using named labels // Duplicate labels - asm!("def: def: nop"); //~ ERROR avoid using named labels - asm!("def: nop\ndef: nop"); //~ ERROR avoid using named labels - asm!("def: nop; def: nop"); //~ ERROR avoid using named labels + asm!("def: def: nop"); + //~^ ERROR avoid using named labels + //~^^ ERROR avoid using named labels + asm!("def: nop\ndef: nop"); + //~^ ERROR avoid using named labels + //~^^ ERROR avoid using named labels + asm!("def: nop; def: nop"); + //~^ ERROR avoid using named labels + //~^^ ERROR avoid using named labels // Trying to break parsing asm!(":"); @@ -141,7 +153,11 @@ fn main() { asm!("{1}: nop", "/* {0} */", const 10, const 20); //~ ERROR avoid using named labels // Test include_str in asm - asm!(include_str!("named-asm-labels.s")); //~ ERROR avoid using named labels + asm!(include_str!("named-asm-labels.s")); + //~^ ERROR avoid using named labels + //~^^ ERROR avoid using named labels + //~^^^ ERROR avoid using named labels + //~^^^^ ERROR avoid using named labels // Test allowing or warning on the lint instead #[allow(named_asm_labels)] diff --git a/tests/ui/asm/named-asm-labels.stderr b/tests/ui/asm/named-asm-labels.stderr index 36fd69839518f..20b7d64f9e752 100644 --- a/tests/ui/asm/named-asm-labels.stderr +++ b/tests/ui/asm/named-asm-labels.stderr @@ -21,13 +21,22 @@ error: avoid using named labels in inline assembly --> $DIR/named-asm-labels.rs:29:15 | LL | asm!("foo: bar1: nop"); - | ^^^ ^^^^ + | ^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:33:15 + --> $DIR/named-asm-labels.rs:29:20 + | +LL | asm!("foo: bar1: nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:34:15 | LL | asm!("foo1: nop", "nop"); | ^^^^ @@ -36,16 +45,25 @@ LL | asm!("foo1: nop", "nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:34:15 + --> $DIR/named-asm-labels.rs:35:15 | LL | asm!("foo2: foo3: nop", "nop"); - | ^^^^ ^^^^ + | ^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:36:22 + --> $DIR/named-asm-labels.rs:35:21 + | +LL | asm!("foo2: foo3: nop", "nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:38:22 | LL | asm!("nop", "foo4: nop"); | ^^^^ @@ -54,7 +72,7 @@ LL | asm!("nop", "foo4: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:37:15 + --> $DIR/named-asm-labels.rs:39:15 | LL | asm!("foo5: nop", "foo6: nop"); | ^^^^ @@ -63,7 +81,7 @@ LL | asm!("foo5: nop", "foo6: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:37:28 + --> $DIR/named-asm-labels.rs:39:28 | LL | asm!("foo5: nop", "foo6: nop"); | ^^^^ @@ -72,16 +90,25 @@ LL | asm!("foo5: nop", "foo6: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:42:15 + --> $DIR/named-asm-labels.rs:44:15 | LL | asm!("foo7: nop; foo8: nop"); - | ^^^^ ^^^^ + | ^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:44:15 + --> $DIR/named-asm-labels.rs:44:26 + | +LL | asm!("foo7: nop; foo8: nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:47:15 | LL | asm!("foo9: nop; nop"); | ^^^^ @@ -90,7 +117,7 @@ LL | asm!("foo9: nop; nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:45:20 + --> $DIR/named-asm-labels.rs:48:20 | LL | asm!("nop; foo10: nop"); | ^^^^^ @@ -99,16 +126,25 @@ LL | asm!("nop; foo10: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:48:15 + --> $DIR/named-asm-labels.rs:51:15 | LL | asm!("bar2: nop\n bar3: nop"); - | ^^^^ ^^^^ + | ^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:50:15 + --> $DIR/named-asm-labels.rs:51:27 + | +LL | asm!("bar2: nop\n bar3: nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:54:15 | LL | asm!("bar4: nop\n nop"); | ^^^^ @@ -117,7 +153,7 @@ LL | asm!("bar4: nop\n nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:51:21 + --> $DIR/named-asm-labels.rs:55:21 | LL | asm!("nop\n bar5: nop"); | ^^^^ @@ -126,19 +162,35 @@ LL | asm!("nop\n bar5: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:52:21 + --> $DIR/named-asm-labels.rs:56:21 | LL | asm!("nop\n bar6: bar7: nop"); - | ^^^^ ^^^^ + | ^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:58:13 + --> $DIR/named-asm-labels.rs:56:27 + | +LL | asm!("nop\n bar6: bar7: nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:63:13 | LL | blah2: nop | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:64:13 + | LL | blah3: nop | ^^^^^ | @@ -146,7 +198,7 @@ LL | blah3: nop = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:67:19 + --> $DIR/named-asm-labels.rs:73:19 | LL | nop ; blah4: nop | ^^^^^ @@ -155,7 +207,7 @@ LL | nop ; blah4: nop = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:81:15 + --> $DIR/named-asm-labels.rs:87:15 | LL | asm!("blah1: 2bar: nop"); | ^^^^^ @@ -164,7 +216,7 @@ LL | asm!("blah1: 2bar: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:84:15 + --> $DIR/named-asm-labels.rs:90:15 | LL | asm!("def: def: nop"); | ^^^ @@ -173,7 +225,17 @@ LL | asm!("def: def: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:85:15 + --> $DIR/named-asm-labels.rs:90:15 + | +LL | asm!("def: def: nop"); + | ^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:93:15 | LL | asm!("def: nop\ndef: nop"); | ^^^ @@ -182,16 +244,36 @@ LL | asm!("def: nop\ndef: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:86:15 + --> $DIR/named-asm-labels.rs:93:15 + | +LL | asm!("def: nop\ndef: nop"); + | ^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:96:15 + | +LL | asm!("def: nop; def: nop"); + | ^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:96:15 | LL | asm!("def: nop; def: nop"); | ^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:94:15 + --> $DIR/named-asm-labels.rs:106:15 | LL | asm!("fooo\u{003A} nop"); | ^^^^^^^^^^^^^^^^ @@ -200,7 +282,7 @@ LL | asm!("fooo\u{003A} nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:95:15 + --> $DIR/named-asm-labels.rs:107:15 | LL | asm!("foooo\x3A nop"); | ^^^^^^^^^^^^^ @@ -209,7 +291,7 @@ LL | asm!("foooo\x3A nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:98:15 + --> $DIR/named-asm-labels.rs:110:15 | LL | asm!("fooooo:\u{000A} nop"); | ^^^^^^ @@ -218,7 +300,7 @@ LL | asm!("fooooo:\u{000A} nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:99:15 + --> $DIR/named-asm-labels.rs:111:15 | LL | asm!("foooooo:\x0A nop"); | ^^^^^^^ @@ -227,16 +309,17 @@ LL | asm!("foooooo:\x0A nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:103:14 + --> $DIR/named-asm-labels.rs:115:14 | LL | asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information + = note: the label may be declared in the expansion of a macro error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:111:13 + --> $DIR/named-asm-labels.rs:123:13 | LL | ab: nop // ab: does foo | ^^ @@ -245,97 +328,140 @@ LL | ab: nop // ab: does foo = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:131:19 + --> $DIR/named-asm-labels.rs:143:19 | LL | asm!("test_{}: nop", in(reg) 10); | ^^^^^^^ | = help: only local labels of the form `:` should be used in inline asm + = note: format arguments may expand to a non-numeric value = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:133:15 + --> $DIR/named-asm-labels.rs:145:15 | LL | asm!("test_{}: nop", const 10); | ^^^^^^^ | = help: only local labels of the form `:` should be used in inline asm + = note: format arguments may expand to a non-numeric value = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:134:15 + --> $DIR/named-asm-labels.rs:146:15 | LL | asm!("test_{}: nop", sym main); | ^^^^^^^ | = help: only local labels of the form `:` should be used in inline asm + = note: format arguments may expand to a non-numeric value = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:135:15 + --> $DIR/named-asm-labels.rs:147:15 | LL | asm!("{}_test: nop", const 10); | ^^^^^^^ | = help: only local labels of the form `:` should be used in inline asm + = note: format arguments may expand to a non-numeric value = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:136:15 + --> $DIR/named-asm-labels.rs:148:15 | LL | asm!("test_{}_test: nop", const 10); | ^^^^^^^^^^^^ | = help: only local labels of the form `:` should be used in inline asm + = note: format arguments may expand to a non-numeric value = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:137:15 + --> $DIR/named-asm-labels.rs:149:15 | LL | asm!("{}: nop", const 10); | ^^ | = help: only local labels of the form `:` should be used in inline asm + = note: format arguments may expand to a non-numeric value = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:139:15 + --> $DIR/named-asm-labels.rs:151:15 | LL | asm!("{uwu}: nop", uwu = const 10); | ^^^^^ | = help: only local labels of the form `:` should be used in inline asm + = note: format arguments may expand to a non-numeric value = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:140:15 + --> $DIR/named-asm-labels.rs:152:15 | LL | asm!("{0}: nop", const 10); | ^^^ | = help: only local labels of the form `:` should be used in inline asm + = note: format arguments may expand to a non-numeric value = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:141:15 + --> $DIR/named-asm-labels.rs:153:15 | LL | asm!("{1}: nop", "/* {0} */", const 10, const 20); | ^^^ | = help: only local labels of the form `:` should be used in inline asm + = note: format arguments may expand to a non-numeric value + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:156:14 + | +LL | asm!(include_str!("named-asm-labels.s")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + = note: the label may be declared in the expansion of a macro + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:156:14 + | +LL | asm!(include_str!("named-asm-labels.s")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + = note: the label may be declared in the expansion of a macro + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:156:14 + | +LL | asm!(include_str!("named-asm-labels.s")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information + = note: the label may be declared in the expansion of a macro + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:144:14 + --> $DIR/named-asm-labels.rs:156:14 | LL | asm!(include_str!("named-asm-labels.s")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information + = note: the label may be declared in the expansion of a macro + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:154:19 + --> $DIR/named-asm-labels.rs:170:19 | LL | asm!("warned: nop"); | ^^^^^^ @@ -343,13 +469,13 @@ LL | asm!("warned: nop"); = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information note: the lint level is defined here - --> $DIR/named-asm-labels.rs:152:16 + --> $DIR/named-asm-labels.rs:168:16 | LL | #[warn(named_asm_labels)] | ^^^^^^^^^^^^^^^^ error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:163:20 + --> $DIR/named-asm-labels.rs:179:20 | LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } | ^^^^^ @@ -358,7 +484,7 @@ LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noret = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:169:20 + --> $DIR/named-asm-labels.rs:185:20 | LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } | ^^^^^ @@ -367,7 +493,7 @@ LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noret = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:177:20 + --> $DIR/named-asm-labels.rs:193:20 | LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } | ^^^^^ @@ -376,7 +502,7 @@ LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:187:24 + --> $DIR/named-asm-labels.rs:203:24 | LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } | ^^^^^ @@ -385,7 +511,7 @@ LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:196:15 + --> $DIR/named-asm-labels.rs:212:15 | LL | asm!("closure1: nop"); | ^^^^^^^^ @@ -394,7 +520,7 @@ LL | asm!("closure1: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:200:15 + --> $DIR/named-asm-labels.rs:216:15 | LL | asm!("closure2: nop"); | ^^^^^^^^ @@ -403,7 +529,7 @@ LL | asm!("closure2: nop"); = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:210:19 + --> $DIR/named-asm-labels.rs:226:19 | LL | asm!("closure3: nop"); | ^^^^^^^^ @@ -411,5 +537,5 @@ LL | asm!("closure3: nop"); = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information -error: aborting due to 44 previous errors; 1 warning emitted +error: aborting due to 56 previous errors; 1 warning emitted From a3ef94e80e0ec7bacd42a70bd8a2203c5cc3fab8 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 9 Jul 2024 17:35:51 -0300 Subject: [PATCH 19/22] Fire unsafe_code lint on unsafe extern blocks --- compiler/rustc_lint/messages.ftl | 2 ++ compiler/rustc_lint/src/builtin.rs | 6 ++++++ compiler/rustc_lint/src/lints.rs | 2 ++ .../ui/lint/unsafe_code/unsafe-extern-blocks.rs | 14 ++++++++++++++ .../unsafe_code/unsafe-extern-blocks.stderr | 17 +++++++++++++++++ 5 files changed, 41 insertions(+) create mode 100644 tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs create mode 100644 tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 3e952558d29d3..9d429d5131ec1 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -163,6 +163,8 @@ lint_builtin_unreachable_pub = unreachable `pub` {$what} lint_builtin_unsafe_block = usage of an `unsafe` block +lint_builtin_unsafe_extern_block = usage of an `unsafe extern` block + lint_builtin_unsafe_impl = implementation of an `unsafe` trait lint_builtin_unsafe_trait = declaration of an `unsafe` trait diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 79c8046f9b741..2d596564d52ca 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -326,6 +326,12 @@ impl EarlyLintPass for UnsafeCode { self.report_unsafe(cx, it.span, BuiltinUnsafe::GlobalAsm); } + ast::ItemKind::ForeignMod(ForeignMod { safety, .. }) => { + if let Safety::Unsafe(_) = safety { + self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeExternBlock); + } + } + _ => {} } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 7c5640f5959a0..eacc66b197aa7 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -81,6 +81,8 @@ pub enum BuiltinUnsafe { AllowInternalUnsafe, #[diag(lint_builtin_unsafe_block)] UnsafeBlock, + #[diag(lint_builtin_unsafe_extern_block)] + UnsafeExternBlock, #[diag(lint_builtin_unsafe_trait)] UnsafeTrait, #[diag(lint_builtin_unsafe_impl)] diff --git a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs new file mode 100644 index 0000000000000..6f2ead70db80c --- /dev/null +++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs @@ -0,0 +1,14 @@ +#![feature(unsafe_extern_blocks)] +#![deny(unsafe_code)] + +#[allow(unsafe_code)] +unsafe extern "C" { + fn foo(); +} + +unsafe extern "C" { + //~^ ERROR usage of an `unsafe extern` block [unsafe_code] + fn bar(); +} + +fn main() {} diff --git a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr new file mode 100644 index 0000000000000..5439a3112560e --- /dev/null +++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr @@ -0,0 +1,17 @@ +error: usage of an `unsafe extern` block + --> $DIR/unsafe-extern-blocks.rs:9:1 + | +LL | / unsafe extern "C" { +LL | | +LL | | fn bar(); +LL | | } + | |_^ + | +note: the lint level is defined here + --> $DIR/unsafe-extern-blocks.rs:2:9 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: aborting due to 1 previous error + From 2c8bbeebf1c630d06e44fa131d1cb0908b5ad56c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 11 Jul 2024 19:15:00 -0400 Subject: [PATCH 20/22] Remove fully_normalize --- .../src/opaque_hidden_inferred_bound.rs | 27 +++++------ .../rustc_trait_selection/src/traits/mod.rs | 46 ++++--------------- .../src/traits/normalize.rs | 8 ++-- .../src/traits/specialize/mod.rs | 29 +++++------- 4 files changed, 36 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 5ee73dbfdc658..fdb71ad41a754 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -5,8 +5,7 @@ use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifie use rustc_middle::ty::{self, fold::BottomUpFolder, Ty, TypeFoldable}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{symbol::kw, Span}; -use rustc_trait_selection::traits; -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::{self, ObligationCtxt}; use crate::{LateContext, LateLintPass, LintContext}; @@ -130,24 +129,26 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { .iter_instantiated_copied(cx.tcx, proj.projection_term.args) { let assoc_pred = assoc_pred.fold_with(proj_replacer); - let Ok(assoc_pred) = traits::fully_normalize( - infcx, + + let ocx = ObligationCtxt::new(infcx); + let assoc_pred = + ocx.normalize(&traits::ObligationCause::dummy(), cx.param_env, assoc_pred); + if !ocx.select_all_or_error().is_empty() { + // Can't normalize for some reason...? + continue; + } + + ocx.register_obligation(traits::Obligation::new( + cx.tcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred, - ) else { - continue; - }; + )); // If that predicate doesn't hold modulo regions (but passed during type-check), // then we must've taken advantage of the hack in `project_and_unify_types` where // we replace opaques with inference vars. Emit a warning! - if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new( - cx.tcx, - traits::ObligationCause::dummy(), - cx.param_env, - assoc_pred, - )) { + if !ocx.select_all_or_error().is_empty() { // If it's a trait bound and an opaque that doesn't satisfy it, // then we can emit a suggestion to add the bound. let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 703ff2f7f1698..d28982ed84925 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -271,13 +271,14 @@ fn do_normalize_predicates<'tcx>( // them here too, and we will remove this function when // we move over to lazy normalization *anyway*. let infcx = tcx.infer_ctxt().ignoring_regions().build(); - let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) { - Ok(predicates) => predicates, - Err(errors) => { - let reported = infcx.err_ctxt().report_fulfillment_errors(errors); - return Err(reported); - } - }; + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); + let predicates = ocx.normalize(&cause, elaborated_env, predicates); + + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + let reported = infcx.err_ctxt().report_fulfillment_errors(errors); + return Err(reported); + } debug!("do_normalize_predicates: normalized predicates = {:?}", predicates); @@ -465,37 +466,6 @@ pub fn normalize_param_env_or_error<'tcx>( ty::ParamEnv::new(tcx.mk_clauses(&predicates), unnormalized_env.reveal()) } -/// Normalize a type and process all resulting obligations, returning any errors. -/// -/// FIXME(-Znext-solver): This should be replaced by `At::deeply_normalize` -/// which has the same behavior with the new solver. Because using a separate -/// fulfillment context worsens caching in the old solver, `At::deeply_normalize` -/// is still lazy with the old solver as it otherwise negatively impacts perf. -#[instrument(skip_all)] -pub fn fully_normalize<'tcx, T>( - infcx: &InferCtxt<'tcx>, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - value: T, -) -> Result>> -where - T: TypeFoldable>, -{ - let ocx = ObligationCtxt::new_with_diagnostics(infcx); - debug!(?value); - let normalized_value = ocx.normalize(&cause, param_env, value); - debug!(?normalized_value); - debug!("select_all_or_error start"); - let errors = ocx.select_all_or_error(); - if !errors.is_empty() { - return Err(errors); - } - debug!("select_all_or_error complete"); - let resolved_value = infcx.resolve_vars_if_possible(normalized_value); - debug!(?resolved_value); - Ok(resolved_value) -} - /// Normalizes the predicates and checks whether they hold in an empty environment. If this /// returns true, then either normalize encountered an error or one of the predicates did not /// hold. Used when creating vtables to check for unsatisfiable methods. diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 3a7481acbafd3..01ba8c02ea6eb 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -42,11 +42,9 @@ impl<'tcx> At<'_, 'tcx> { /// same goals in both a temporary and the shared context which negatively impacts /// performance as these don't share caching. /// - /// FIXME(-Znext-solver): This has the same behavior as `traits::fully_normalize` - /// in the new solver, but because of performance reasons, we currently reuse an - /// existing fulfillment context in the old solver. Once we also eagerly prove goals with - /// the old solver or have removed the old solver, remove `traits::fully_normalize` and - /// rename this function to `At::fully_normalize`. + /// FIXME(-Znext-solver): For performance reasons, we currently reuse an existing + /// fulfillment context in the old solver. Once we have removed the old solver, we + /// can remove the `fulfill_cx` parameter on this function. fn deeply_normalize( self, value: T, diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 6a904ef487eae..3c33d13567d78 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -18,9 +18,7 @@ use crate::error_reporting::traits::to_pretty_impl_header; use crate::errors::NegativePositiveConflict; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; -use crate::traits::{ - self, coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt, -}; +use crate::traits::{coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt}; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{codes::*, Diag, EmissionGuarantee}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -219,19 +217,17 @@ fn fulfill_implication<'tcx>( param_env, source_trait_ref, target_impl ); - let source_trait_ref = - match traits::fully_normalize(infcx, ObligationCause::dummy(), param_env, source_trait_ref) - { - Ok(source_trait_ref) => source_trait_ref, - Err(_errors) => { - infcx.dcx().span_delayed_bug( - infcx.tcx.def_span(source_impl), - format!("failed to fully normalize {source_trait_ref}"), - ); - source_trait_ref - } - }; + let ocx = ObligationCtxt::new(infcx); + let source_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, source_trait_ref); + if !ocx.select_all_or_error().is_empty() { + infcx.dcx().span_delayed_bug( + infcx.tcx.def_span(source_impl), + format!("failed to fully normalize {source_trait_ref}"), + ); + } + + let source_trait_ref = infcx.resolve_vars_if_possible(source_trait_ref); let source_trait = ImplSubject::Trait(source_trait_ref); let selcx = SelectionContext::new(infcx); @@ -253,9 +249,6 @@ fn fulfill_implication<'tcx>( return Err(()); }; - // Needs to be `in_snapshot` because this function is used to rebase - // generic parameters, which may happen inside of a select within a probe. - let ocx = ObligationCtxt::new(infcx); // attempt to prove all of the predicates for impl2 given those for impl1 // (which are packed up in penv) ocx.register_obligations(obligations.chain(more_obligations)); From 843f5dd93b3edc65034eb8b9e16673c2bf8e28f2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 11 Jul 2024 19:49:51 -0400 Subject: [PATCH 21/22] Add rustdoc support for use<> in (local) RPITs --- compiler/rustc_hir/src/hir.rs | 7 +++++++ src/librustdoc/clean/mod.rs | 5 +++-- src/librustdoc/clean/simplify.rs | 2 +- src/librustdoc/clean/types.rs | 2 ++ src/librustdoc/html/format.rs | 14 ++++++++++++++ tests/rustdoc/impl-trait-precise-capturing.rs | 14 ++++++++++++++ 6 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 tests/rustdoc/impl-trait-precise-capturing.rs diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d57fad6ba4c2d..4561f9d9b49df 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2708,6 +2708,13 @@ impl PreciseCapturingArg<'_> { PreciseCapturingArg::Param(param) => param.hir_id, } } + + pub fn name(self) -> Symbol { + match self { + PreciseCapturingArg::Lifetime(lt) => lt.ident.name, + PreciseCapturingArg::Param(param) => param.ident.name, + } + } } /// We need to have a [`Node`] for the [`HirId`] that we attach the type/const param diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index aa596897fc42f..98ce268a77466 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -228,8 +228,9 @@ fn clean_generic_bound<'tcx>( GenericBound::TraitBound(clean_poly_trait_ref(t, cx), modifier) } - // FIXME(precise_capturing): Implement rustdoc support - hir::GenericBound::Use(..) => return None, + hir::GenericBound::Use(args, ..) => { + GenericBound::Use(args.iter().map(|arg| arg.name()).collect()) + } }) } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 58eef36677b23..1b7d84add1f85 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -79,7 +79,7 @@ pub(crate) fn merge_bounds( !bounds.iter_mut().any(|b| { let trait_ref = match *b { clean::GenericBound::TraitBound(ref mut tr, _) => tr, - clean::GenericBound::Outlives(..) => return false, + clean::GenericBound::Outlives(..) | clean::GenericBound::Use(_) => return false, }; // If this QPath's trait `trait_did` is the same as, or a supertrait // of, the bound's trait `did` then we can keep going, otherwise diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index fe01d17b08a8c..a31adc9949a3f 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1244,6 +1244,8 @@ impl Eq for Attributes {} pub(crate) enum GenericBound { TraitBound(PolyTrait, hir::TraitBoundModifier), Outlives(Lifetime), + /// `use<'a, T>` precise-capturing bound syntax + Use(Vec), } impl GenericBound { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 4268fadd6c59c..9b0b2571ec115 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -412,6 +412,20 @@ impl clean::GenericBound { })?; ty.print(cx).fmt(f) } + clean::GenericBound::Use(args) => { + if f.alternate() { + f.write_str("use<")?; + } else { + f.write_str("use<")?; + } + for (i, arg) in args.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + arg.fmt(f)?; + } + if f.alternate() { f.write_str(">") } else { f.write_str(">") } + } }) } } diff --git a/tests/rustdoc/impl-trait-precise-capturing.rs b/tests/rustdoc/impl-trait-precise-capturing.rs new file mode 100644 index 0000000000000..d1987a555c151 --- /dev/null +++ b/tests/rustdoc/impl-trait-precise-capturing.rs @@ -0,0 +1,14 @@ +#![crate_name = "foo"] +#![feature(precise_capturing)] + +//@ has foo/fn.two.html '//section[@id="main-content"]//pre' "-> impl Sized + use<'b, 'a>" +pub fn two<'a, 'b, 'c>() -> impl Sized + use<'b, 'a /* no 'c */> {} + +//@ has foo/fn.params.html '//section[@id="main-content"]//pre' "-> impl Sized + use<'a, T, N>" +pub fn params<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {} + +//@ has foo/fn.none.html '//section[@id="main-content"]//pre' "-> impl Sized + use<>" +pub fn none() -> impl Sized + use<> {} + +//@ has foo/fn.first.html '//section[@id="main-content"]//pre' "-> impl use<> + Sized" +pub fn first() -> impl use<> + Sized {} From bd135e487f904e757f6c3d2ebcc2d216ac4d9aaf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 11 Jul 2024 19:50:03 -0400 Subject: [PATCH 22/22] Add rustdoc-json support for use<> --- rustfmt.toml | 2 ++ src/librustdoc/json/conversions.rs | 1 + src/rustdoc-json-types/lib.rs | 4 +++- src/tools/jsondoclint/src/validator.rs | 1 + tests/rustdoc-json/impl-trait-precise-capturing.rs | 6 ++++++ 5 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-json/impl-trait-precise-capturing.rs diff --git a/rustfmt.toml b/rustfmt.toml index b15ffdca38a06..e060fd8fe8bfa 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -22,6 +22,8 @@ ignore = [ "/tests/rustdoc-ui/", # Some have syntax errors, some are whitespace-sensitive. "/tests/ui/", # Some have syntax errors, some are whitespace-sensitive. "/tests/ui-fulldeps/", # Some are whitespace-sensitive (e.g. `// ~ERROR` comments). + # #[cfg(bootstrap)] so that t-release sees this when they search for it + "/tests/rustdoc-json/impl-trait-precise-capturing.rs", # Do not format submodules. # FIXME: sync submodule list with tidy/bootstrap/etc diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 5111e363c522e..4ab0df3670859 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -542,6 +542,7 @@ impl FromWithTcx for GenericBound { } } Outlives(lifetime) => GenericBound::Outlives(convert_lifetime(lifetime)), + Use(args) => GenericBound::Use(args.into_iter().map(|arg| arg.to_string()).collect()), } } } diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 89115d4d7d667..6fd23b60c8ad6 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 31; +pub const FORMAT_VERSION: u32 = 32; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -538,6 +538,8 @@ pub enum GenericBound { modifier: TraitBoundModifier, }, Outlives(String), + /// `use<'a, T>` precise-capturing bound syntax + Use(Vec), } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index cd011dce7844e..ea1e573384b82 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -298,6 +298,7 @@ impl<'a> Validator<'a> { generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd)); } GenericBound::Outlives(_) => {} + GenericBound::Use(_) => {} } } diff --git a/tests/rustdoc-json/impl-trait-precise-capturing.rs b/tests/rustdoc-json/impl-trait-precise-capturing.rs new file mode 100644 index 0000000000000..bf98868d1453d --- /dev/null +++ b/tests/rustdoc-json/impl-trait-precise-capturing.rs @@ -0,0 +1,6 @@ +#![feature(precise_capturing)] + +// @is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[0]" \"\'a\" +// @is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[1]" \"T\" +// @is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[2]" \"N\" +pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {}