Skip to content

Commit

Permalink
add track_caller feature (#276)
Browse files Browse the repository at this point in the history
closes #68
  • Loading branch information
nolanderc authored Oct 13, 2024
1 parent 1c09edf commit da9b187
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 16 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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**!!!!
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
# version of Rust, with the exception of `extern_crate_alloc` and
# `extern_crate_std`.
Expand All @@ -57,6 +60,7 @@ latest_stable_rust = [
"derive",
"min_const_generics",
"must_cast",
"track_caller",
"wasm_simd",
"zeroable_atomics",
"zeroable_maybe_uninit",
Expand Down
1 change: 1 addition & 0 deletions src/allocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
/// dropped.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn from_box_bytes<T: sealed::FromBoxBytes + ?Sized>(
input: BoxBytes,
) -> Box<T> {
Expand Down
8 changes: 8 additions & 0 deletions src/checked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ pub fn try_cast_slice_mut<
///
/// This is [`try_from_bytes`] but will panic on error.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn from_bytes<T: CheckedBitPattern>(s: &[u8]) -> &T {
match try_from_bytes(s) {
Ok(t) => t,
Expand All @@ -426,6 +427,7 @@ pub fn from_bytes<T: CheckedBitPattern>(s: &[u8]) -> &T {
///
/// This is [`try_from_bytes_mut`] but will panic on error.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn from_bytes_mut<T: NoUninit + CheckedBitPattern>(s: &mut [u8]) -> &mut T {
match try_from_bytes_mut(s) {
Ok(t) => t,
Expand All @@ -438,6 +440,7 @@ pub fn from_bytes_mut<T: NoUninit + CheckedBitPattern>(s: &mut [u8]) -> &mut T {
/// ## Panics
/// * This is like `try_pod_read_unaligned` but will panic on failure.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn pod_read_unaligned<T: CheckedBitPattern>(bytes: &[u8]) -> T {
match try_pod_read_unaligned(bytes) {
Ok(t) => t,
Expand All @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast<A: NoUninit, B: CheckedBitPattern>(a: A) -> B {
match try_cast(a) {
Ok(t) => t,
Expand All @@ -464,6 +468,7 @@ pub fn cast<A: NoUninit, B: CheckedBitPattern>(a: A) -> B {
///
/// This is [`try_cast_mut`] but will panic on error.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_mut<
A: NoUninit + AnyBitPattern,
B: NoUninit + CheckedBitPattern,
Expand All @@ -482,6 +487,7 @@ pub fn cast_mut<
///
/// This is [`try_cast_ref`] but will panic on error.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_ref<A: NoUninit, B: CheckedBitPattern>(a: &A) -> &B {
match try_cast_ref(a) {
Ok(t) => t,
Expand All @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_slice<A: NoUninit, B: CheckedBitPattern>(a: &[A]) -> &[B] {
match try_cast_slice(a) {
Ok(t) => t,
Expand All @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_slice_mut<
A: NoUninit + AnyBitPattern,
B: NoUninit + CheckedBitPattern,
Expand Down
2 changes: 2 additions & 0 deletions src/contiguous.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ pub unsafe trait Contiguous: Copy + 'static {
/// This is undefined behavior regardless, so it could have been the nasal
/// demons at that point anyway ;).
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
fn from_integer(value: Self::Int) -> Option<Self> {
// Guard against an illegal implementation of Contiguous. Annoyingly we
// can't rely on `transmute` to do this for us (see below), but
Expand Down Expand Up @@ -153,6 +154,7 @@ pub unsafe trait Contiguous: Copy + 'static {
/// This is undefined behavior regardless, so it could have been the nasal
/// demons at that point anyway ;).
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
fn into_integer(self) -> Self::Int {
// Guard against an illegal implementation of Contiguous. Annoyingly we
// can't rely on `transmute` to do the size check for us (see
Expand Down
10 changes: 10 additions & 0 deletions src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ possibility code branch.
#[cfg(not(target_arch = "spirv"))]
#[cold]
#[inline(never)]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) fn something_went_wrong<D: core::fmt::Display>(
_src: &str, _err: D,
) -> ! {
Expand Down Expand Up @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn from_bytes<T: Copy>(s: &[u8]) -> &T {
match try_from_bytes(s) {
Ok(t) => t,
Expand All @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn from_bytes_mut<T: Copy>(s: &mut [u8]) -> &mut T {
match try_from_bytes_mut(s) {
Ok(t) => t,
Expand Down Expand Up @@ -115,6 +118,7 @@ pub(crate) unsafe fn try_pod_read_unaligned<T: Copy>(
/// ## Panics
/// * This is like `try_pod_read_unaligned` but will panic on failure.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn pod_read_unaligned<T: Copy>(bytes: &[u8]) -> T {
match try_pod_read_unaligned(bytes) {
Ok(t) => t,
Expand All @@ -127,6 +131,7 @@ pub(crate) unsafe fn pod_read_unaligned<T: Copy>(bytes: &[u8]) -> T {
/// ## Panics
/// * If `align` is not a power of two. This includes when `align` is zero.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) fn is_aligned_to(ptr: *const (), align: usize) -> bool {
#[cfg(feature = "align_offset")]
{
Expand Down Expand Up @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn cast<A: Copy, B: Copy>(a: A) -> B {
if size_of::<A>() == size_of::<B>() {
unsafe { transmute!(a) }
Expand All @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
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>() {
// Plz mr compiler, just notice that we can't ever hit Err in this case.
Expand All @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
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>() {
// Plz mr compiler, just notice that we can't ever hit Err in this case.
Expand All @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn cast_slice<A: Copy, B: Copy>(a: &[A]) -> &[B] {
match try_cast_slice(a) {
Ok(b) => b,
Expand All @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub(crate) unsafe fn cast_slice_mut<A: Copy, B: Copy>(a: &mut [A]) -> &mut [B] {
match try_cast_slice_mut(a) {
Ok(b) => b,
Expand Down
42 changes: 26 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,20 @@ macro_rules! transmute {
($val:expr) => {
::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
// since the compiler hedges that the type being borrowed could have interior mutability.
($srcty:ty; $dstty:ty; $val:expr) => {
{
#[repr(C)]
union Transmute<A, B> {
src: ::core::mem::ManuallyDrop<A>,
dst: ::core::mem::ManuallyDrop<B>,
}
::core::mem::ManuallyDrop::into_inner(Transmute::<$srcty, $dstty> { src: ::core::mem::ManuallyDrop::new($val) }.dst)
// This arm is for use in const contexts, where the borrow required to use
// transmute_copy poses an issue since the compiler hedges that the type
// being borrowed could have interior mutability.
($srcty:ty; $dstty:ty; $val:expr) => {{
#[repr(C)]
union Transmute<A, B> {
src: ::core::mem::ManuallyDrop<A>,
dst: ::core::mem::ManuallyDrop<B>,
}
}
::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.
Expand Down Expand Up @@ -210,12 +212,12 @@ pub use bytemuck_derive::{
/// The things that can go wrong when casting between [`Pod`] data forms.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PodCastError {
/// You tried to cast a reference into a reference to a type with a higher alignment
/// requirement but the input reference wasn't aligned.
/// You tried to cast a reference into a reference to a type with a higher
/// alignment requirement but the input reference wasn't aligned.
TargetAlignmentGreaterAndInputNotAligned,
/// If the element size of a slice changes, then the output slice changes length
/// accordingly. If the output slice wouldn't be a whole number of elements,
/// then the conversion fails.
/// If the element size of a slice changes, then the output slice changes
/// length accordingly. If the output slice wouldn't be a whole number of
/// elements, then the conversion fails.
OutputSliceWouldHaveSlop,
/// When casting an individual `T`, `&T`, or `&mut T` value the
/// source size and destination size must be an exact match.
Expand Down Expand Up @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn from_bytes<T: AnyBitPattern>(s: &[u8]) -> &T {
unsafe { internal::from_bytes(s) }
}
Expand All @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn from_bytes_mut<T: NoUninit + AnyBitPattern>(s: &mut [u8]) -> &mut T {
unsafe { internal::from_bytes_mut(s) }
}
Expand All @@ -298,6 +302,7 @@ pub fn try_pod_read_unaligned<T: AnyBitPattern>(
/// ## Panics
/// * This is like `try_pod_read_unaligned` but will panic on failure.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn pod_read_unaligned<T: AnyBitPattern>(bytes: &[u8]) -> T {
unsafe { internal::pod_read_unaligned(bytes) }
}
Expand Down Expand Up @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast<A: NoUninit, B: AnyBitPattern>(a: A) -> B {
unsafe { internal::cast(a) }
}
Expand All @@ -342,6 +348,7 @@ pub fn cast<A: NoUninit, B: AnyBitPattern>(a: A) -> B {
///
/// This is [`try_cast_mut`] but will panic on error.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(
a: &mut A,
) -> &mut B {
Expand All @@ -354,6 +361,7 @@ pub fn cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(
///
/// This is [`try_cast_ref`] but will panic on error.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_ref<A: NoUninit, B: AnyBitPattern>(a: &A) -> &B {
unsafe { internal::cast_ref(a) }
}
Expand All @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_slice<A: NoUninit, B: AnyBitPattern>(a: &[A]) -> &[B] {
unsafe { internal::cast_slice(a) }
}
Expand All @@ -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.
#[inline]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn cast_slice_mut<
A: NoUninit + AnyBitPattern,
B: NoUninit + AnyBitPattern,
Expand Down

0 comments on commit da9b187

Please sign in to comment.