From 9d1f82ebfcc0925631c2a09273b88e3cadb1b318 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Tue, 22 Mar 2022 11:13:56 +0900 Subject: [PATCH 1/7] kmc-solid: Use `abort` to abort a program The current implementation uses a `hlt` instruction, which is the most direct way to notify a connected debugger but is not the most flexible way. This commit changes it to a call to the `abort` libc function, making it possible for a system designer to override its behavior as they see fit. --- library/panic_abort/src/lib.rs | 3 +-- library/std/src/sys/solid/abi/mod.rs | 26 -------------------------- library/std/src/sys/solid/mod.rs | 15 ++------------- library/std/src/sys/solid/os.rs | 9 +++------ 4 files changed, 6 insertions(+), 47 deletions(-) diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index 2bcb3182a7bf2..1e210ffb41f62 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -38,12 +38,11 @@ pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMe abort(); cfg_if::cfg_if! { - if #[cfg(unix)] { + if #[cfg(any(unix, target_os = "solid_asp3"))] { unsafe fn abort() -> ! { libc::abort(); } } else if #[cfg(any(target_os = "hermit", - target_os = "solid_asp3", all(target_vendor = "fortanix", target_env = "sgx") ))] { unsafe fn abort() -> ! { diff --git a/library/std/src/sys/solid/abi/mod.rs b/library/std/src/sys/solid/abi/mod.rs index 1afc83f766df3..8440d572cfbd3 100644 --- a/library/std/src/sys/solid/abi/mod.rs +++ b/library/std/src/sys/solid/abi/mod.rs @@ -4,32 +4,6 @@ mod fs; pub mod sockets; pub use self::fs::*; -#[inline(always)] -pub fn breakpoint_program_exited(tid: usize) { - unsafe { - match () { - // SOLID_BP_PROGRAM_EXITED = 15 - #[cfg(target_arch = "arm")] - () => core::arch::asm!("bkpt #15", in("r0") tid), - #[cfg(target_arch = "aarch64")] - () => core::arch::asm!("hlt #15", in("x0") tid), - } - } -} - -#[inline(always)] -pub fn breakpoint_abort() { - unsafe { - match () { - // SOLID_BP_CSABORT = 16 - #[cfg(target_arch = "arm")] - () => core::arch::asm!("bkpt #16"), - #[cfg(target_arch = "aarch64")] - () => core::arch::asm!("hlt #16"), - } - } -} - // `solid_types.h` pub use super::itron::abi::{ER, ER_ID, E_TMOUT, ID}; diff --git a/library/std/src/sys/solid/mod.rs b/library/std/src/sys/solid/mod.rs index 492b1a55475a2..43e3fcfd4686f 100644 --- a/library/std/src/sys/solid/mod.rs +++ b/library/std/src/sys/solid/mod.rs @@ -74,20 +74,9 @@ pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind { error::decode_error_kind(code) } -#[inline(always)] +#[inline] pub fn abort_internal() -> ! { - loop { - abi::breakpoint_abort(); - } -} - -// This function is needed by the panic runtime. The symbol is named in -// pre-link args for the target specification, so keep that in sync. -#[cfg(not(test))] -#[no_mangle] -// NB. used by both libunwind and libpanic_abort -pub extern "C" fn __rust_abort() { - abort_internal(); + unsafe { libc::abort() } } pub fn hashmap_random_keys() -> (u64, u64) { diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs index 719d95bbe50a8..b5649d6e0ffb0 100644 --- a/library/std/src/sys/solid/os.rs +++ b/library/std/src/sys/solid/os.rs @@ -11,7 +11,7 @@ use crate::path::{self, PathBuf}; use crate::sys_common::rwlock::StaticRwLock; use crate::vec; -use super::{abi, error, itron, memchr}; +use super::{error, itron, memchr}; // `solid` directly maps `errno`s to μITRON error codes. impl itron::error::ItronError { @@ -184,11 +184,8 @@ pub fn home_dir() -> Option { None } -pub fn exit(_code: i32) -> ! { - let tid = itron::task::try_current_task_id().unwrap_or(0); - loop { - abi::breakpoint_program_exited(tid as usize); - } +pub fn exit(code: i32) -> ! { + rtabort!("exit({}) called", code); } pub fn getpid() -> u32 { From 64ac04567ba397f8600952e3875b9a197f7b2910 Mon Sep 17 00:00:00 2001 From: Frank King Date: Thu, 17 Mar 2022 23:11:49 +0800 Subject: [PATCH 2/7] protect `std::io::Take::limit` from overflow in `read` fixs #94981 --- library/std/src/io/mod.rs | 1 + library/std/src/io/tests.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 6005270a75fec..004f18bbfcbc6 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2559,6 +2559,7 @@ impl Read for Take { let max = cmp::min(buf.len() as u64, self.limit) as usize; let n = self.inner.read(&mut buf[..max])?; + assert!(n as u64 <= self.limit, "number of read bytes exceeds limit"); self.limit -= n as u64; Ok(n) } diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index eb62634856462..b11292ed82d7f 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -583,6 +583,25 @@ fn test_write_all_vectored() { } } +// Issue 94981 +#[test] +#[should_panic = "number of read bytes exceeds limit"] +fn test_take_wrong_length() { + struct LieAboutSize(bool); + + impl Read for LieAboutSize { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + // Lie about the read size at first time of read. + if core::mem::take(&mut self.0) { Ok(buf.len() + 1) } else { Ok(buf.len()) } + } + } + + let mut buffer = vec![0; 4]; + let mut reader = LieAboutSize(true).take(4); + // Primed the `Limit` by lying about the read size. + let _ = reader.read(&mut buffer[..]); +} + #[bench] fn bench_take_read(b: &mut test::Bencher) { b.iter(|| { From 1e832266def75c3d813af39c67367ff31c7a2410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 20 Jul 2022 00:00:00 +0000 Subject: [PATCH 3/7] Use non-relocatable code in nofile-limit.rs test To avoid using static-pie which is not essential to the test but which was reported to cause problems on Void Linux where glibc is build without support for static-pie. --- src/test/ui/process/nofile-limit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/process/nofile-limit.rs b/src/test/ui/process/nofile-limit.rs index 549135a46cf10..3ddf8d6ef2405 100644 --- a/src/test/ui/process/nofile-limit.rs +++ b/src/test/ui/process/nofile-limit.rs @@ -6,7 +6,7 @@ // dont-check-compiler-stderr // only-linux // no-prefer-dynamic -// compile-flags: -Ctarget-feature=+crt-static -Crpath=no +// compile-flags: -Ctarget-feature=+crt-static -Crpath=no -Crelocation-model=static #![feature(exit_status_error)] #![feature(rustc_private)] extern crate libc; From a5de4eeafc3f4371205ca97685033a2ab98a66df Mon Sep 17 00:00:00 2001 From: dAxpeDDa Date: Sat, 23 Jul 2022 16:58:10 +0200 Subject: [PATCH 4/7] Add `sign-ext` target feature to the WASM target --- compiler/rustc_codegen_ssa/src/target_features.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index bfdef2dc0e80c..ecad0518533ec 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -249,6 +249,7 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("bulk-memory", Some(sym::wasm_target_feature)), ("mutable-globals", Some(sym::wasm_target_feature)), ("reference-types", Some(sym::wasm_target_feature)), + ("sign-ext", Some(sym::wasm_target_feature)), ]; const BPF_ALLOWED_FEATURES: &[(&str, Option)] = &[("alu32", Some(sym::bpf_target_feature))]; From f7326989e63ab8944493e8ff03447bb9a7d83141 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 24 Jul 2022 05:51:03 +0000 Subject: [PATCH 5/7] Use VecMap::get in ConstraintLocator::check --- compiler/rustc_typeck/src/collect/type_of.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index faa4f3700bba8..1d7406e00ad0a 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -538,9 +538,9 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { impl ConstraintLocator<'_> { #[instrument(skip(self), level = "debug")] - fn check(&mut self, def_id: LocalDefId) { + fn check(&mut self, item_def_id: LocalDefId) { // Don't try to check items that cannot possibly constrain the type. - if !self.tcx.has_typeck_results(def_id) { + if !self.tcx.has_typeck_results(item_def_id) { debug!("no constraint: no typeck results"); return; } @@ -555,26 +555,20 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { // // because we again need to reveal `Foo` so we can check whether the // // constant does not contain interior mutability. // ``` - let tables = self.tcx.typeck(def_id); + let tables = self.tcx.typeck(item_def_id); if let Some(_) = tables.tainted_by_errors { self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error() }); return; } - if tables.concrete_opaque_types.get(&self.def_id).is_none() { + if !tables.concrete_opaque_types.contains_key(&self.def_id) { debug!("no constraints in typeck results"); return; } // Use borrowck to get the type with unerased regions. - let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; + let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types; debug!(?concrete_opaque_types); - for &(def_id, concrete_type) in concrete_opaque_types { - if def_id != self.def_id { - // Ignore constraints for other opaque types. - continue; - } - + if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) { debug!(?concrete_type, "found constraint"); - if let Some(prev) = self.found { if concrete_type.ty != prev.ty && !(concrete_type, prev).references_error() { prev.report_mismatch(&concrete_type, self.tcx); From d10a7b124378ac71f87ce271ddc33c36974d99a3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 24 Jul 2022 14:28:30 -0400 Subject: [PATCH 6/7] add miri-track-caller to some intrinsic-exposing methods --- library/core/src/hint.rs | 1 + library/core/src/intrinsics.rs | 2 ++ library/core/src/mem/mod.rs | 1 + library/core/src/num/int_macros.rs | 5 +++++ library/core/src/num/uint_macros.rs | 5 +++++ library/core/src/ptr/const_ptr.rs | 11 +++++++++++ library/core/src/ptr/mut_ptr.rs | 13 +++++++++++++ 7 files changed, 38 insertions(+) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 7ae1bfd4f351a..81b6d5737ea75 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -96,6 +96,7 @@ use crate::intrinsics; #[inline] #[stable(feature = "unreachable", since = "1.27.0")] #[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unreachable_unchecked() -> ! { // SAFETY: the safety contract for `intrinsics::unreachable` must // be upheld by the caller. diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 9ae31a31aaad3..4a595902282db 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2449,6 +2449,7 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - #[cfg_attr(not(bootstrap), rustc_allowed_through_unstable_modules)] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] #[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] @@ -2535,6 +2536,7 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[cfg_attr(not(bootstrap), rustc_allowed_through_unstable_modules)] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] #[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 66af491607435..6dc8563c421fc 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1124,6 +1124,7 @@ impl fmt::Debug for Discriminant { #[stable(feature = "discriminant_value", since = "1.21.0")] #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_discriminant")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const fn discriminant(v: &T) -> Discriminant { Discriminant(intrinsics::discriminant_value(v)) } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index eb458f3866e63..a66de19bad0ed 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -449,6 +449,7 @@ macro_rules! int_impl { without modifying the original"] #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_add(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_add`. @@ -517,6 +518,7 @@ macro_rules! int_impl { without modifying the original"] #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_sub`. @@ -585,6 +587,7 @@ macro_rules! int_impl { without modifying the original"] #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_mul`. @@ -757,6 +760,7 @@ macro_rules! int_impl { without modifying the original"] #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_shl`. @@ -803,6 +807,7 @@ macro_rules! int_impl { without modifying the original"] #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_shr`. diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 715e78350a499..73365544233eb 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -459,6 +459,7 @@ macro_rules! uint_impl { without modifying the original"] #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_add(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_add`. @@ -528,6 +529,7 @@ macro_rules! uint_impl { without modifying the original"] #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_sub`. @@ -574,6 +576,7 @@ macro_rules! uint_impl { without modifying the original"] #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_mul`. @@ -933,6 +936,7 @@ macro_rules! uint_impl { without modifying the original"] #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_shl`. @@ -979,6 +983,7 @@ macro_rules! uint_impl { without modifying the original"] #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_shr`. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 6cdbab3058941..e289a8e6bd5f9 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -449,6 +449,7 @@ impl *const T { #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn offset(self, count: isize) -> *const T where T: Sized, @@ -471,6 +472,7 @@ impl *const T { #[inline(always)] #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset(self, count: isize) -> Self { // SAFETY: the caller must uphold the safety contract for `offset`. let this = unsafe { self.cast::().offset(count).cast::<()>() }; @@ -641,6 +643,7 @@ impl *const T { #[stable(feature = "ptr_offset_from", since = "1.47.0")] #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")] #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized, @@ -663,6 +666,7 @@ impl *const T { #[inline(always)] #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset_from(self, origin: *const T) -> isize { // SAFETY: the caller must uphold the safety contract for `offset_from`. unsafe { self.cast::().offset_from(origin.cast::()) } @@ -731,6 +735,7 @@ impl *const T { #[unstable(feature = "ptr_sub_ptr", issue = "95892")] #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub_ptr(self, origin: *const T) -> usize where T: Sized, @@ -862,6 +867,7 @@ impl *const T { #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn add(self, count: usize) -> Self where T: Sized, @@ -884,6 +890,7 @@ impl *const T { #[inline(always)] #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_add(self, count: usize) -> Self { // SAFETY: the caller must uphold the safety contract for `add`. let this = unsafe { self.cast::().add(count).cast::<()>() }; @@ -946,6 +953,7 @@ impl *const T { #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub(self, count: usize) -> Self where T: Sized, @@ -969,6 +977,7 @@ impl *const T { #[inline(always)] #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_sub(self, count: usize) -> Self { // SAFETY: the caller must uphold the safety contract for `sub`. let this = unsafe { self.cast::().sub(count).cast::<()>() }; @@ -1205,6 +1214,7 @@ impl *const T { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn copy_to(self, dest: *mut T, count: usize) where T: Sized, @@ -1224,6 +1234,7 @@ impl *const T { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize) where T: Sized, diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index e323f63115b85..fc3dd2a9b25a9 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -461,6 +461,7 @@ impl *mut T { #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn offset(self, count: isize) -> *mut T where T: Sized, @@ -485,6 +486,7 @@ impl *mut T { #[inline(always)] #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset(self, count: isize) -> Self { // SAFETY: the caller must uphold the safety contract for `offset`. let this = unsafe { self.cast::().offset(count).cast::<()>() }; @@ -824,6 +826,7 @@ impl *mut T { #[stable(feature = "ptr_offset_from", since = "1.47.0")] #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized, @@ -844,6 +847,7 @@ impl *mut T { #[inline(always)] #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset_from(self, origin: *const T) -> isize { // SAFETY: the caller must uphold the safety contract for `offset_from`. unsafe { self.cast::().offset_from(origin.cast::()) } @@ -913,6 +917,7 @@ impl *mut T { #[unstable(feature = "ptr_sub_ptr", issue = "95892")] #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub_ptr(self, origin: *const T) -> usize where T: Sized, @@ -976,6 +981,7 @@ impl *mut T { #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn add(self, count: usize) -> Self where T: Sized, @@ -998,6 +1004,7 @@ impl *mut T { #[inline(always)] #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_add(self, count: usize) -> Self { // SAFETY: the caller must uphold the safety contract for `add`. let this = unsafe { self.cast::().add(count).cast::<()>() }; @@ -1060,6 +1067,7 @@ impl *mut T { #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub(self, count: usize) -> Self where T: Sized, @@ -1083,6 +1091,7 @@ impl *mut T { #[inline(always)] #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_sub(self, count: usize) -> Self { // SAFETY: the caller must uphold the safety contract for `sub`. let this = unsafe { self.cast::().sub(count).cast::<()>() }; @@ -1319,6 +1328,7 @@ impl *mut T { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn copy_to(self, dest: *mut T, count: usize) where T: Sized, @@ -1338,6 +1348,7 @@ impl *mut T { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize) where T: Sized, @@ -1357,6 +1368,7 @@ impl *mut T { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn copy_from(self, src: *const T, count: usize) where T: Sized, @@ -1376,6 +1388,7 @@ impl *mut T { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize) where T: Sized, From 168c5b18392271abe6156350f0952e2b57fff9c5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 22 Jul 2022 10:04:37 +1000 Subject: [PATCH 7/7] Improve error messages involving `derive` and `packed`. There are two errors involving `derive` and `packed`. ``` `#[derive]` can't be derived on a `#[repr(packed)]` struct with type or const parameters `#[derive]` can't be derived on a `#[repr(packed)]` struct that does not derive Copy ``` The second one overstates things. It is possible to use derive on a repr(packed) struct that doesn't derive Copy in two cases. - If all the fields within the struct meet the required alignment: 1 for `repr(packed)`, or `N` for `repr(packed(N))`. - If `Default` is the only trait derived. This commit improves things in a few ways. - Changes the errors to say `$TRAIT can't be derived on this ...`. This is more accurate, because it's just $TRAIT and *this* packed struct that are a problem, not *all* derived traits on *all* packed structs. - Adds more details to the "ERROR" lines in the test case, enough to distinguish between the two error messages. - Adds more cases to the test case that don't cause errors, e.g. `Default` derives. - Uses a wider variety of builtin traits in the test case, for better coverage. --- .../src/check_packed_ref.rs | 13 ++-- .../ui/derives/deriving-with-repr-packed.rs | 38 +++++++---- .../derives/deriving-with-repr-packed.stderr | 68 +++++++++---------- 3 files changed, 68 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index 2eb38941f1a50..c21c1efe99112 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -36,13 +36,16 @@ fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) { tcx.struct_span_lint_hir(UNALIGNED_REFERENCES, lint_hir_id, tcx.def_span(def_id), |lint| { // FIXME: when we make this a hard error, this should have its // own error code. - let message = if tcx.generics_of(def_id).own_requires_monomorphization() { - "`#[derive]` can't be used on a `#[repr(packed)]` struct with \ - type or const parameters (error E0133)" + let extra = if tcx.generics_of(def_id).own_requires_monomorphization() { + "with type or const parameters" } else { - "`#[derive]` can't be used on a `#[repr(packed)]` struct that \ - does not derive Copy (error E0133)" + "that does not derive `Copy`" }; + let message = format!( + "`{}` can't be derived on this `#[repr(packed)]` struct {} (error E0133)", + tcx.item_name(tcx.trait_id_of_impl(def_id.to_def_id()).expect("derived trait name")), + extra + ); lint.build(message).emit(); }); } diff --git a/src/test/ui/derives/deriving-with-repr-packed.rs b/src/test/ui/derives/deriving-with-repr-packed.rs index b78eeaa90551b..3884e397764e7 100644 --- a/src/test/ui/derives/deriving-with-repr-packed.rs +++ b/src/test/ui/derives/deriving-with-repr-packed.rs @@ -1,29 +1,43 @@ #![deny(unaligned_references)] -// check that derive on a packed struct with non-Copy fields -// correctly. This can't be made to work perfectly because -// we can't just use the field from the struct as it might -// not be aligned. +// Check that deriving certain builtin traits on certain packed structs cause +// errors. This happens when the derived trait would need to use a potentially +// misaligned reference. But there are two cases that are allowed: +// - If all the fields within the struct meet the required alignment: 1 for +// `repr(packed)`, or `N` for `repr(packed(N))`. +// - If `Default` is the only trait derived, because it doesn't involve any +// references. -#[derive(Copy, Clone, PartialEq, Eq)] -//~^ ERROR `#[derive]` can't be used +#[derive(Copy, Clone, Default, PartialEq, Eq)] +//~^ ERROR `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters //~| hard error -//~^^^ ERROR `#[derive]` can't be used +//~^^^ ERROR `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters //~| hard error #[repr(packed)] pub struct Foo(T, T, T); -#[derive(PartialEq, Eq)] -//~^ ERROR `#[derive]` can't be used +#[derive(Default, Hash)] +//~^ ERROR `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` //~| hard error #[repr(packed)] pub struct Bar(u32, u32, u32); -#[derive(PartialEq)] +// This one is fine because the field alignment is 1. +#[derive(Default, Hash)] +#[repr(packed)] +pub struct Bar2(u8, i8, bool); + +// This one is fine because the field alignment is 2, matching `packed(2)`. +#[derive(Default, Hash)] +#[repr(packed(2))] +pub struct Bar3(u16, i16, bool); + +// This one is fine because it's not packed. +#[derive(Debug, Default)] struct Y(usize); -#[derive(PartialEq)] -//~^ ERROR `#[derive]` can't be used +#[derive(Debug, Default)] +//~^ ERROR `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` //~| hard error #[repr(packed)] struct X(Y); diff --git a/src/test/ui/derives/deriving-with-repr-packed.stderr b/src/test/ui/derives/deriving-with-repr-packed.stderr index 1002b359f60ba..1f98da5b70e9f 100644 --- a/src/test/ui/derives/deriving-with-repr-packed.stderr +++ b/src/test/ui/derives/deriving-with-repr-packed.stderr @@ -1,7 +1,7 @@ -error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133) - --> $DIR/deriving-with-repr-packed.rs:8:16 +error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133) + --> $DIR/deriving-with-repr-packed.rs:11:16 | -LL | #[derive(Copy, Clone, PartialEq, Eq)] +LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] | ^^^^^ | note: the lint level is defined here @@ -13,43 +13,43 @@ LL | #![deny(unaligned_references)] = note: for more information, see issue #82523 = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133) - --> $DIR/deriving-with-repr-packed.rs:8:23 +error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133) + --> $DIR/deriving-with-repr-packed.rs:11:32 | -LL | #[derive(Copy, Clone, PartialEq, Eq)] - | ^^^^^^^^^ +LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] + | ^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133) - --> $DIR/deriving-with-repr-packed.rs:16:10 +error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133) + --> $DIR/deriving-with-repr-packed.rs:19:19 | -LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ +LL | #[derive(Default, Hash)] + | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) -error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133) - --> $DIR/deriving-with-repr-packed.rs:25:10 +error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133) + --> $DIR/deriving-with-repr-packed.rs:39:10 | -LL | #[derive(PartialEq)] - | ^^^^^^^^^ +LL | #[derive(Debug, Default)] + | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors Future incompatibility report: Future breakage diagnostic: -error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133) - --> $DIR/deriving-with-repr-packed.rs:8:16 +error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133) + --> $DIR/deriving-with-repr-packed.rs:11:16 | -LL | #[derive(Copy, Clone, PartialEq, Eq)] +LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] | ^^^^^ | note: the lint level is defined here @@ -62,11 +62,11 @@ LL | #![deny(unaligned_references)] = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: -error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133) - --> $DIR/deriving-with-repr-packed.rs:8:23 +error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133) + --> $DIR/deriving-with-repr-packed.rs:11:32 | -LL | #[derive(Copy, Clone, PartialEq, Eq)] - | ^^^^^^^^^ +LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] + | ^^^^^^^^^ | note: the lint level is defined here --> $DIR/deriving-with-repr-packed.rs:1:9 @@ -78,11 +78,11 @@ LL | #![deny(unaligned_references)] = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: -error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133) - --> $DIR/deriving-with-repr-packed.rs:16:10 +error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133) + --> $DIR/deriving-with-repr-packed.rs:19:19 | -LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ +LL | #[derive(Default, Hash)] + | ^^^^ | note: the lint level is defined here --> $DIR/deriving-with-repr-packed.rs:1:9 @@ -91,14 +91,14 @@ LL | #![deny(unaligned_references)] | ^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: -error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133) - --> $DIR/deriving-with-repr-packed.rs:25:10 +error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133) + --> $DIR/deriving-with-repr-packed.rs:39:10 | -LL | #[derive(PartialEq)] - | ^^^^^^^^^ +LL | #[derive(Debug, Default)] + | ^^^^^ | note: the lint level is defined here --> $DIR/deriving-with-repr-packed.rs:1:9 @@ -107,5 +107,5 @@ LL | #![deny(unaligned_references)] | ^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)