add track_caller feature (#276)

closes #68
This commit is contained in:
Christofer Nolander 2024-10-13 06:06:43 +02:00 committed by GitHub
parent 1c09edf7b0
commit da9b1874d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 51 additions and 16 deletions

View File

@ -45,6 +45,9 @@ const_zeroed = [] # MSRV 1.75.0: support const `zeroed()`
# Do not use if you can avoid it, because this is **unsound**!!!! # Do not use if you can avoid it, because this is **unsound**!!!!
unsound_ptr_pod_impl = [] unsound_ptr_pod_impl = []
# MSRV 1.46.0: adds the `#[track_caller]` attribute to functions which may panic
track_caller = []
# Enables all features that are both sound and supported on the latest stable # Enables all features that are both sound and supported on the latest stable
# version of Rust, with the exception of `extern_crate_alloc` and # version of Rust, with the exception of `extern_crate_alloc` and
# `extern_crate_std`. # `extern_crate_std`.
@ -57,6 +60,7 @@ latest_stable_rust = [
"derive", "derive",
"min_const_generics", "min_const_generics",
"must_cast", "must_cast",
"track_caller",
"wasm_simd", "wasm_simd",
"zeroable_atomics", "zeroable_atomics",
"zeroable_maybe_uninit", "zeroable_maybe_uninit",

View File

@ -891,6 +891,7 @@ pub fn box_bytes_of<T: sealed::BoxBytesOf + ?Sized>(input: Box<T>) -> BoxBytes {
/// This is [`try_from_box_bytes`] but will panic on error and the input will be /// This is [`try_from_box_bytes`] but will panic on error and the input will be
/// dropped. /// dropped.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn from_box_bytes<T: sealed::FromBoxBytes + ?Sized>( pub fn from_box_bytes<T: sealed::FromBoxBytes + ?Sized>(
input: BoxBytes, input: BoxBytes,
) -> Box<T> { ) -> Box<T> {

View File

@ -413,6 +413,7 @@ pub fn try_cast_slice_mut<
/// ///
/// This is [`try_from_bytes`] but will panic on error. /// This is [`try_from_bytes`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn from_bytes<T: CheckedBitPattern>(s: &[u8]) -> &T { pub fn from_bytes<T: CheckedBitPattern>(s: &[u8]) -> &T {
match try_from_bytes(s) { match try_from_bytes(s) {
Ok(t) => t, Ok(t) => t,
@ -426,6 +427,7 @@ pub fn from_bytes<T: CheckedBitPattern>(s: &[u8]) -> &T {
/// ///
/// This is [`try_from_bytes_mut`] but will panic on error. /// This is [`try_from_bytes_mut`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn from_bytes_mut<T: NoUninit + CheckedBitPattern>(s: &mut [u8]) -> &mut T { pub fn from_bytes_mut<T: NoUninit + CheckedBitPattern>(s: &mut [u8]) -> &mut T {
match try_from_bytes_mut(s) { match try_from_bytes_mut(s) {
Ok(t) => t, Ok(t) => t,
@ -438,6 +440,7 @@ pub fn from_bytes_mut<T: NoUninit + CheckedBitPattern>(s: &mut [u8]) -> &mut T {
/// ## Panics /// ## Panics
/// * This is like `try_pod_read_unaligned` but will panic on failure. /// * This is like `try_pod_read_unaligned` but will panic on failure.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn pod_read_unaligned<T: CheckedBitPattern>(bytes: &[u8]) -> T { pub fn pod_read_unaligned<T: CheckedBitPattern>(bytes: &[u8]) -> T {
match try_pod_read_unaligned(bytes) { match try_pod_read_unaligned(bytes) {
Ok(t) => t, Ok(t) => t,
@ -451,6 +454,7 @@ pub fn pod_read_unaligned<T: CheckedBitPattern>(bytes: &[u8]) -> T {
/// ///
/// * This is like [`try_cast`], but will panic on a size mismatch. /// * This is like [`try_cast`], but will panic on a size mismatch.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast<A: NoUninit, B: CheckedBitPattern>(a: A) -> B { pub fn cast<A: NoUninit, B: CheckedBitPattern>(a: A) -> B {
match try_cast(a) { match try_cast(a) {
Ok(t) => t, Ok(t) => t,
@ -464,6 +468,7 @@ pub fn cast<A: NoUninit, B: CheckedBitPattern>(a: A) -> B {
/// ///
/// This is [`try_cast_mut`] but will panic on error. /// This is [`try_cast_mut`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_mut< pub fn cast_mut<
A: NoUninit + AnyBitPattern, A: NoUninit + AnyBitPattern,
B: NoUninit + CheckedBitPattern, B: NoUninit + CheckedBitPattern,
@ -482,6 +487,7 @@ pub fn cast_mut<
/// ///
/// This is [`try_cast_ref`] but will panic on error. /// This is [`try_cast_ref`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_ref<A: NoUninit, B: CheckedBitPattern>(a: &A) -> &B { pub fn cast_ref<A: NoUninit, B: CheckedBitPattern>(a: &A) -> &B {
match try_cast_ref(a) { match try_cast_ref(a) {
Ok(t) => t, Ok(t) => t,
@ -495,6 +501,7 @@ pub fn cast_ref<A: NoUninit, B: CheckedBitPattern>(a: &A) -> &B {
/// ///
/// This is [`try_cast_slice`] but will panic on error. /// This is [`try_cast_slice`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_slice<A: NoUninit, B: CheckedBitPattern>(a: &[A]) -> &[B] { pub fn cast_slice<A: NoUninit, B: CheckedBitPattern>(a: &[A]) -> &[B] {
match try_cast_slice(a) { match try_cast_slice(a) {
Ok(t) => t, Ok(t) => t,
@ -508,6 +515,7 @@ pub fn cast_slice<A: NoUninit, B: CheckedBitPattern>(a: &[A]) -> &[B] {
/// ///
/// This is [`try_cast_slice_mut`] but will panic on error. /// This is [`try_cast_slice_mut`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_slice_mut< pub fn cast_slice_mut<
A: NoUninit + AnyBitPattern, A: NoUninit + AnyBitPattern,
B: NoUninit + CheckedBitPattern, B: NoUninit + CheckedBitPattern,

View File

@ -118,6 +118,7 @@ pub unsafe trait Contiguous: Copy + 'static {
/// This is undefined behavior regardless, so it could have been the nasal /// This is undefined behavior regardless, so it could have been the nasal
/// demons at that point anyway ;). /// demons at that point anyway ;).
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
fn from_integer(value: Self::Int) -> Option<Self> { fn from_integer(value: Self::Int) -> Option<Self> {
// Guard against an illegal implementation of Contiguous. Annoyingly we // Guard against an illegal implementation of Contiguous. Annoyingly we
// can't rely on `transmute` to do this for us (see below), but // can't rely on `transmute` to do this for us (see below), but
@ -153,6 +154,7 @@ pub unsafe trait Contiguous: Copy + 'static {
/// This is undefined behavior regardless, so it could have been the nasal /// This is undefined behavior regardless, so it could have been the nasal
/// demons at that point anyway ;). /// demons at that point anyway ;).
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
fn into_integer(self) -> Self::Int { fn into_integer(self) -> Self::Int {
// Guard against an illegal implementation of Contiguous. Annoyingly we // Guard against an illegal implementation of Contiguous. Annoyingly we
// can't rely on `transmute` to do the size check for us (see // can't rely on `transmute` to do the size check for us (see

View File

@ -23,6 +23,7 @@ possibility code branch.
#[cfg(not(target_arch = "spirv"))] #[cfg(not(target_arch = "spirv"))]
#[cold] #[cold]
#[inline(never)] #[inline(never)]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) fn something_went_wrong<D: core::fmt::Display>( pub(crate) fn something_went_wrong<D: core::fmt::Display>(
_src: &str, _err: D, _src: &str, _err: D,
) -> ! { ) -> ! {
@ -75,6 +76,7 @@ pub(crate) unsafe fn bytes_of_mut<T: Copy>(t: &mut T) -> &mut [u8] {
/// ///
/// This is [`try_from_bytes`] but will panic on error. /// This is [`try_from_bytes`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn from_bytes<T: Copy>(s: &[u8]) -> &T { pub(crate) unsafe fn from_bytes<T: Copy>(s: &[u8]) -> &T {
match try_from_bytes(s) { match try_from_bytes(s) {
Ok(t) => t, Ok(t) => t,
@ -88,6 +90,7 @@ pub(crate) unsafe fn from_bytes<T: Copy>(s: &[u8]) -> &T {
/// ///
/// This is [`try_from_bytes_mut`] but will panic on error. /// This is [`try_from_bytes_mut`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn from_bytes_mut<T: Copy>(s: &mut [u8]) -> &mut T { pub(crate) unsafe fn from_bytes_mut<T: Copy>(s: &mut [u8]) -> &mut T {
match try_from_bytes_mut(s) { match try_from_bytes_mut(s) {
Ok(t) => t, Ok(t) => t,
@ -115,6 +118,7 @@ pub(crate) unsafe fn try_pod_read_unaligned<T: Copy>(
/// ## Panics /// ## Panics
/// * This is like `try_pod_read_unaligned` but will panic on failure. /// * This is like `try_pod_read_unaligned` but will panic on failure.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn pod_read_unaligned<T: Copy>(bytes: &[u8]) -> T { pub(crate) unsafe fn pod_read_unaligned<T: Copy>(bytes: &[u8]) -> T {
match try_pod_read_unaligned(bytes) { match try_pod_read_unaligned(bytes) {
Ok(t) => t, Ok(t) => t,
@ -127,6 +131,7 @@ pub(crate) unsafe fn pod_read_unaligned<T: Copy>(bytes: &[u8]) -> T {
/// ## Panics /// ## Panics
/// * If `align` is not a power of two. This includes when `align` is zero. /// * If `align` is not a power of two. This includes when `align` is zero.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) fn is_aligned_to(ptr: *const (), align: usize) -> bool { pub(crate) fn is_aligned_to(ptr: *const (), align: usize) -> bool {
#[cfg(feature = "align_offset")] #[cfg(feature = "align_offset")]
{ {
@ -186,6 +191,7 @@ pub(crate) unsafe fn try_from_bytes_mut<T: Copy>(
/// ///
/// * This is like [`try_cast`](try_cast), but will panic on a size mismatch. /// * This is like [`try_cast`](try_cast), but will panic on a size mismatch.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn cast<A: Copy, B: Copy>(a: A) -> B { pub(crate) unsafe fn cast<A: Copy, B: Copy>(a: A) -> B {
if size_of::<A>() == size_of::<B>() { if size_of::<A>() == size_of::<B>() {
unsafe { transmute!(a) } unsafe { transmute!(a) }
@ -200,6 +206,7 @@ pub(crate) unsafe fn cast<A: Copy, B: Copy>(a: A) -> B {
/// ///
/// This is [`try_cast_mut`] but will panic on error. /// This is [`try_cast_mut`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn cast_mut<A: Copy, B: Copy>(a: &mut A) -> &mut B { pub(crate) unsafe fn cast_mut<A: Copy, B: Copy>(a: &mut A) -> &mut B {
if size_of::<A>() == size_of::<B>() && align_of::<A>() >= align_of::<B>() { if size_of::<A>() == size_of::<B>() && align_of::<A>() >= align_of::<B>() {
// Plz mr compiler, just notice that we can't ever hit Err in this case. // Plz mr compiler, just notice that we can't ever hit Err in this case.
@ -221,6 +228,7 @@ pub(crate) unsafe fn cast_mut<A: Copy, B: Copy>(a: &mut A) -> &mut B {
/// ///
/// This is [`try_cast_ref`] but will panic on error. /// This is [`try_cast_ref`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn cast_ref<A: Copy, B: Copy>(a: &A) -> &B { pub(crate) unsafe fn cast_ref<A: Copy, B: Copy>(a: &A) -> &B {
if size_of::<A>() == size_of::<B>() && align_of::<A>() >= align_of::<B>() { if size_of::<A>() == size_of::<B>() && align_of::<A>() >= align_of::<B>() {
// Plz mr compiler, just notice that we can't ever hit Err in this case. // Plz mr compiler, just notice that we can't ever hit Err in this case.
@ -242,6 +250,7 @@ pub(crate) unsafe fn cast_ref<A: Copy, B: Copy>(a: &A) -> &B {
/// ///
/// This is [`try_cast_slice`] but will panic on error. /// This is [`try_cast_slice`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn cast_slice<A: Copy, B: Copy>(a: &[A]) -> &[B] { pub(crate) unsafe fn cast_slice<A: Copy, B: Copy>(a: &[A]) -> &[B] {
match try_cast_slice(a) { match try_cast_slice(a) {
Ok(b) => b, Ok(b) => b,
@ -255,6 +264,7 @@ pub(crate) unsafe fn cast_slice<A: Copy, B: Copy>(a: &[A]) -> &[B] {
/// ///
/// This is [`try_cast_slice_mut`] but will panic on error. /// This is [`try_cast_slice_mut`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn cast_slice_mut<A: Copy, B: Copy>(a: &mut [A]) -> &mut [B] { pub(crate) unsafe fn cast_slice_mut<A: Copy, B: Copy>(a: &mut [A]) -> &mut [B] {
match try_cast_slice_mut(a) { match try_cast_slice_mut(a) {
Ok(b) => b, Ok(b) => b,

View File

@ -123,18 +123,20 @@ macro_rules! transmute {
($val:expr) => { ($val:expr) => {
::core::mem::transmute_copy(&::core::mem::ManuallyDrop::new($val)) ::core::mem::transmute_copy(&::core::mem::ManuallyDrop::new($val))
}; };
// This arm is for use in const contexts, where the borrow required to use transmute_copy poses an issue // This arm is for use in const contexts, where the borrow required to use
// since the compiler hedges that the type being borrowed could have interior mutability. // transmute_copy poses an issue since the compiler hedges that the type
($srcty:ty; $dstty:ty; $val:expr) => { // being borrowed could have interior mutability.
{ ($srcty:ty; $dstty:ty; $val:expr) => {{
#[repr(C)] #[repr(C)]
union Transmute<A, B> { union Transmute<A, B> {
src: ::core::mem::ManuallyDrop<A>, src: ::core::mem::ManuallyDrop<A>,
dst: ::core::mem::ManuallyDrop<B>, dst: ::core::mem::ManuallyDrop<B>,
}
::core::mem::ManuallyDrop::into_inner(Transmute::<$srcty, $dstty> { src: ::core::mem::ManuallyDrop::new($val) }.dst)
} }
} ::core::mem::ManuallyDrop::into_inner(
Transmute::<$srcty, $dstty> { src: ::core::mem::ManuallyDrop::new($val) }
.dst,
)
}};
} }
/// A macro to implement marker traits for various simd types. /// A macro to implement marker traits for various simd types.
@ -210,12 +212,12 @@ pub use bytemuck_derive::{
/// The things that can go wrong when casting between [`Pod`] data forms. /// The things that can go wrong when casting between [`Pod`] data forms.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PodCastError { pub enum PodCastError {
/// You tried to cast a reference into a reference to a type with a higher alignment /// You tried to cast a reference into a reference to a type with a higher
/// requirement but the input reference wasn't aligned. /// alignment requirement but the input reference wasn't aligned.
TargetAlignmentGreaterAndInputNotAligned, TargetAlignmentGreaterAndInputNotAligned,
/// If the element size of a slice changes, then the output slice changes length /// If the element size of a slice changes, then the output slice changes
/// accordingly. If the output slice wouldn't be a whole number of elements, /// length accordingly. If the output slice wouldn't be a whole number of
/// then the conversion fails. /// elements, then the conversion fails.
OutputSliceWouldHaveSlop, OutputSliceWouldHaveSlop,
/// When casting an individual `T`, `&T`, or `&mut T` value the /// When casting an individual `T`, `&T`, or `&mut T` value the
/// source size and destination size must be an exact match. /// source size and destination size must be an exact match.
@ -262,6 +264,7 @@ pub fn bytes_of_mut<T: NoUninit + AnyBitPattern>(t: &mut T) -> &mut [u8] {
/// ///
/// This is like [`try_from_bytes`] but will panic on error. /// This is like [`try_from_bytes`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn from_bytes<T: AnyBitPattern>(s: &[u8]) -> &T { pub fn from_bytes<T: AnyBitPattern>(s: &[u8]) -> &T {
unsafe { internal::from_bytes(s) } unsafe { internal::from_bytes(s) }
} }
@ -272,6 +275,7 @@ pub fn from_bytes<T: AnyBitPattern>(s: &[u8]) -> &T {
/// ///
/// This is like [`try_from_bytes_mut`] but will panic on error. /// This is like [`try_from_bytes_mut`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn from_bytes_mut<T: NoUninit + AnyBitPattern>(s: &mut [u8]) -> &mut T { pub fn from_bytes_mut<T: NoUninit + AnyBitPattern>(s: &mut [u8]) -> &mut T {
unsafe { internal::from_bytes_mut(s) } unsafe { internal::from_bytes_mut(s) }
} }
@ -298,6 +302,7 @@ pub fn try_pod_read_unaligned<T: AnyBitPattern>(
/// ## Panics /// ## Panics
/// * This is like `try_pod_read_unaligned` but will panic on failure. /// * This is like `try_pod_read_unaligned` but will panic on failure.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn pod_read_unaligned<T: AnyBitPattern>(bytes: &[u8]) -> T { pub fn pod_read_unaligned<T: AnyBitPattern>(bytes: &[u8]) -> T {
unsafe { internal::pod_read_unaligned(bytes) } unsafe { internal::pod_read_unaligned(bytes) }
} }
@ -332,6 +337,7 @@ pub fn try_from_bytes_mut<T: NoUninit + AnyBitPattern>(
/// ///
/// * This is like [`try_cast`], but will panic on a size mismatch. /// * This is like [`try_cast`], but will panic on a size mismatch.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast<A: NoUninit, B: AnyBitPattern>(a: A) -> B { pub fn cast<A: NoUninit, B: AnyBitPattern>(a: A) -> B {
unsafe { internal::cast(a) } unsafe { internal::cast(a) }
} }
@ -342,6 +348,7 @@ pub fn cast<A: NoUninit, B: AnyBitPattern>(a: A) -> B {
/// ///
/// This is [`try_cast_mut`] but will panic on error. /// This is [`try_cast_mut`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>( pub fn cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(
a: &mut A, a: &mut A,
) -> &mut B { ) -> &mut B {
@ -354,6 +361,7 @@ pub fn cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(
/// ///
/// This is [`try_cast_ref`] but will panic on error. /// This is [`try_cast_ref`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_ref<A: NoUninit, B: AnyBitPattern>(a: &A) -> &B { pub fn cast_ref<A: NoUninit, B: AnyBitPattern>(a: &A) -> &B {
unsafe { internal::cast_ref(a) } unsafe { internal::cast_ref(a) }
} }
@ -364,6 +372,7 @@ pub fn cast_ref<A: NoUninit, B: AnyBitPattern>(a: &A) -> &B {
/// ///
/// This is [`try_cast_slice`] but will panic on error. /// This is [`try_cast_slice`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_slice<A: NoUninit, B: AnyBitPattern>(a: &[A]) -> &[B] { pub fn cast_slice<A: NoUninit, B: AnyBitPattern>(a: &[A]) -> &[B] {
unsafe { internal::cast_slice(a) } unsafe { internal::cast_slice(a) }
} }
@ -374,6 +383,7 @@ pub fn cast_slice<A: NoUninit, B: AnyBitPattern>(a: &[A]) -> &[B] {
/// ///
/// This is [`try_cast_slice_mut`] but will panic on error. /// This is [`try_cast_slice_mut`] but will panic on error.
#[inline] #[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_slice_mut< pub fn cast_slice_mut<
A: NoUninit + AnyBitPattern, A: NoUninit + AnyBitPattern,
B: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern,