Skip to content

Commit

Permalink
Update TransparentWrapper asserts (Lokathor#232)
Browse files Browse the repository at this point in the history
* Update TransparentWrapper asserts.

* Update TransparentWrapperAlloc assert comments.
  • Loading branch information
zachs18 committed Jun 6, 2024
1 parent 8bf4231 commit ec3172d
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 26 deletions.
30 changes: 30 additions & 0 deletions bytemuck/src/allocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,11 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>:
/// type.
#[inline]
fn wrap_box(s: Box<Inner>) -> Box<Self> {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is the best we can do to assert their metadata is the same type
// on stable.
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());

unsafe {
Expand All @@ -554,6 +559,11 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>:
/// wrapper type.
#[inline]
fn wrap_rc(s: Rc<Inner>) -> Rc<Self> {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is the best we can do to assert their metadata is the same type
// on stable.
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());

unsafe {
Expand All @@ -578,6 +588,11 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>:
#[cfg(target_has_atomic = "ptr")]
#[cfg_attr(feature = "nightly_docs", doc(cfg(target_has_atomic = "ptr")))]
fn wrap_arc(s: Arc<Inner>) -> Arc<Self> {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is the best we can do to assert their metadata is the same type
// on stable.
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());

unsafe {
Expand Down Expand Up @@ -621,6 +636,11 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>:
/// type.
#[inline]
fn peel_box(s: Box<Self>) -> Box<Inner> {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is the best we can do to assert their metadata is the same type
// on stable.
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());

unsafe {
Expand All @@ -645,6 +665,11 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>:
/// inner type.
#[inline]
fn peel_rc(s: Rc<Self>) -> Rc<Inner> {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is the best we can do to assert their metadata is the same type
// on stable.
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());

unsafe {
Expand All @@ -669,6 +694,11 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>:
#[cfg(target_has_atomic = "ptr")]
#[cfg_attr(feature = "nightly_docs", doc(cfg(target_has_atomic = "ptr")))]
fn peel_arc(s: Arc<Self>) -> Arc<Inner> {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is the best we can do to assert their metadata is the same type
// on stable.
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());

unsafe {
Expand Down
65 changes: 39 additions & 26 deletions bytemuck/src/transparent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,10 @@ pub unsafe trait TransparentWrapper<Inner: ?Sized> {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is about the best we can do on stable.
// which is the best we can do to assert their metadata is the same type
// on stable.
assert!(Layout::new::<*const Inner>() == Layout::new::<*const Self>());
unsafe {
assert!(size_of::<*const Inner>() == size_of::<*const Self>());
// A pointer cast doesn't work here because rustc can't tell that
// the vtables match (because of the `?Sized` restriction relaxation).
// A `transmute` doesn't work because the sizes are unspecified.
Expand All @@ -167,8 +167,13 @@ pub unsafe trait TransparentWrapper<Inner: ?Sized> {
/// the wrapper type.
#[inline]
fn wrap_mut(s: &mut Inner) -> &mut Self {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is the best we can do to assert their metadata is the same type
// on stable.
assert!(Layout::new::<*const Inner>() == Layout::new::<*const Self>());
unsafe {
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
// A pointer cast doesn't work here because rustc can't tell that
// the vtables match (because of the `?Sized` restriction relaxation).
// A `transmute` doesn't work because the sizes are unspecified.
Expand All @@ -188,12 +193,10 @@ pub unsafe trait TransparentWrapper<Inner: ?Sized> {
Self: Sized,
Inner: Sized,
{
unsafe {
assert!(Layout::new::<Inner>() == Layout::new::<Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
core::slice::from_raw_parts(s.as_ptr() as *const Self, s.len())
}
assert!(Layout::new::<Inner>() == Layout::new::<Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
unsafe { core::slice::from_raw_parts(s.as_ptr() as *const Self, s.len()) }
}

/// Convert a mutable slice to the inner type into a mutable slice to the
Expand All @@ -204,11 +207,10 @@ pub unsafe trait TransparentWrapper<Inner: ?Sized> {
Self: Sized,
Inner: Sized,
{
assert!(Layout::new::<Inner>() == Layout::new::<Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
unsafe {
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
assert!(align_of::<*mut Inner>() == align_of::<*mut Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Self, s.len())
}
}
Expand All @@ -220,15 +222,23 @@ pub unsafe trait TransparentWrapper<Inner: ?Sized> {
Self: Sized,
Inner: Sized,
{
assert!(Layout::new::<Inner>() == Layout::new::<Self>());
// SAFETY: The unsafe contract requires that `Self` and `Inner` have
// identical representations.
unsafe { transmute!(s) }
}

/// Convert a reference to the wrapper type into a reference to the inner
/// type.
#[inline]
fn peel_ref(s: &Self) -> &Inner {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is the best we can do to assert their metadata is the same type
// on stable.
assert!(Layout::new::<*const Inner>() == Layout::new::<*const Self>());
unsafe {
assert!(size_of::<*const Inner>() == size_of::<*const Self>());
// A pointer cast doesn't work here because rustc can't tell that
// the vtables match (because of the `?Sized` restriction relaxation).
// A `transmute` doesn't work because the sizes are unspecified.
Expand All @@ -245,8 +255,13 @@ pub unsafe trait TransparentWrapper<Inner: ?Sized> {
/// to the inner type.
#[inline]
fn peel_mut(s: &mut Self) -> &mut Inner {
// The unsafe contract requires that these two have
// identical representations, and thus identical pointer metadata.
// Assert that Self and Inner have the same pointer size,
// which is the best we can do to assert their metadata is the same type
// on stable.
assert!(Layout::new::<*const Inner>() == Layout::new::<*const Self>());
unsafe {
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
// A pointer cast doesn't work here because rustc can't tell that
// the vtables match (because of the `?Sized` restriction relaxation).
// A `transmute` doesn't work because the sizes are unspecified.
Expand All @@ -266,13 +281,11 @@ pub unsafe trait TransparentWrapper<Inner: ?Sized> {
Self: Sized,
Inner: Sized,
{
unsafe {
assert!(size_of::<*const Inner>() == size_of::<*const Self>());
assert!(align_of::<*const Inner>() == align_of::<*const Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
core::slice::from_raw_parts(s.as_ptr() as *const Inner, s.len())
}
assert!(size_of::<Inner>() == size_of::<Self>());
assert!(align_of::<Inner>() == align_of::<Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
unsafe { core::slice::from_raw_parts(s.as_ptr() as *const Inner, s.len()) }
}

/// Convert a mutable slice to the wrapped type into a mutable slice to the
Expand All @@ -283,11 +296,11 @@ pub unsafe trait TransparentWrapper<Inner: ?Sized> {
Self: Sized,
Inner: Sized,
{
assert!(size_of::<Inner>() == size_of::<Self>());
assert!(align_of::<Inner>() == align_of::<Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
unsafe {
assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
assert!(align_of::<*mut Inner>() == align_of::<*mut Self>());
// SAFETY: The unsafe contract requires that these two have
// identical representations (size and alignment).
core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Inner, s.len())
}
}
Expand Down

0 comments on commit ec3172d

Please sign in to comment.