Skip to content

Commit 2115a6d

Browse files
joshlfjswrenn
andcommitted
[WIP] Generalize SizeEq to SizeCompat
Co-authored-by: Jack Wrenn <[email protected]> gherrit-pr-id: I6c793a9620ad75bdc0d26ab7c7cd1a0c7bef1b8b
1 parent bb9b06d commit 2115a6d

File tree

6 files changed

+177
-114
lines changed

6 files changed

+177
-114
lines changed

src/impls.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ safety_comment! {
114114
});
115115
}
116116

117-
impl_size_eq!(bool, u8);
117+
impl_size_compat!(bool, u8);
118118

119119
safety_comment! {
120120
/// SAFETY:
@@ -145,7 +145,7 @@ safety_comment! {
145145
});
146146
}
147147

148-
impl_size_eq!(char, Unalign<u32>);
148+
impl_size_compat!(char, Unalign<u32>);
149149

150150
safety_comment! {
151151
/// SAFETY:
@@ -179,14 +179,13 @@ safety_comment! {
179179
});
180180
}
181181

182-
impl_size_eq!(str, [u8]);
182+
impl_size_compat!(str, [u8]);
183183

184184
macro_rules! unsafe_impl_try_from_bytes_for_nonzero {
185185
($($nonzero:ident[$prim:ty]),*) => {
186186
$(
187187
unsafe_impl!(=> TryFromBytes for $nonzero; |n| {
188-
impl_size_eq!($nonzero, Unalign<$prim>);
189-
188+
impl_size_compat!($nonzero, Unalign<$prim>);
190189
let n = n.transmute::<Unalign<$prim>, invariant::Valid, _>();
191190
$nonzero::new(n.read_unaligned().into_inner()).is_some()
192191
});
@@ -404,23 +403,26 @@ mod atomics {
404403
macro_rules! unsafe_impl_transmute_from_for_atomic {
405404
($($($tyvar:ident)? => $atomic:ty [$prim:ty]),*) => {
406405
const _: () = {
407-
use core::cell::UnsafeCell;
408-
use crate::pointer::{PtrInner, SizeEq, TransmuteFrom, invariant::Valid};
406+
use core::{cell::UnsafeCell};
407+
use crate::pointer::{TransmuteFrom, PtrInner, SizeCompat, invariant::Valid};
409408

410409
$(
411410
#[allow(unused_unsafe)] // Force the caller to call this macro inside `safety_comment!`.
412411
const _: () = unsafe {};
413412

414-
// SAFETY: The caller promised that `$atomic` and `$prim` have
415-
// the same size and bit validity.
413+
// SAFETY: The caller promised that `$atomic` and `$prim`
414+
// have the same size and bit validity. As a result of size
415+
// equality, both impls of `SizeCompat::cast_from_raw`
416+
// preserve referent size exactly.
416417
unsafe impl<$($tyvar)?> TransmuteFrom<$atomic, Valid, Valid> for $prim {}
417-
// SAFETY: The caller promised that `$atomic` and `$prim` have
418-
// the same size and bit validity.
418+
// SAFETY: The caller promised that `$atomic` and `$prim`
419+
// have the same size and bit validity. As a result of size
420+
// equality, both impls of `SizeCompat::cast_from_raw`
421+
// preserve referent size exactly.
419422
unsafe impl<$($tyvar)?> TransmuteFrom<$prim, Valid, Valid> for $atomic {}
420423

421-
// SAFETY: The caller promised that `$atomic` and `$prim`
422-
// have the same size.
423-
unsafe impl<$($tyvar)?> SizeEq<$atomic> for $prim {
424+
// SAFETY: See inline safety comment.
425+
unsafe impl<$($tyvar)?> SizeCompat<$atomic> for $prim {
424426
#[inline]
425427
fn cast_from_raw(a: PtrInner<'_, $atomic>) -> PtrInner<'_, $prim> {
426428
// SAFETY: The caller promised that `$atomic` and `$prim`
@@ -430,31 +432,33 @@ mod atomics {
430432
}
431433
}
432434
// SAFETY: See previous safety comment.
433-
unsafe impl<$($tyvar)?> SizeEq<$prim> for $atomic {
435+
unsafe impl<$($tyvar)?> SizeCompat<$prim> for $atomic {
434436
#[inline]
435437
fn cast_from_raw(p: PtrInner<'_, $prim>) -> PtrInner<'_, $atomic> {
436438
// SAFETY: See previous safety comment.
437439
unsafe { cast!(p) }
438440
}
439441
}
442+
440443
// SAFETY: The caller promised that `$atomic` and `$prim`
441444
// have the same size. `UnsafeCell<T>` has the same size as
442-
// `T` [1].
445+
// `T` [1]. Thus, this cast preserves address, referent
446+
// size, and provenance.
443447
//
444448
// [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.UnsafeCell.html#memory-layout:
445449
//
446450
// `UnsafeCell<T>` has the same in-memory representation as
447451
// its inner type `T`. A consequence of this guarantee is that
448452
// it is possible to convert between `T` and `UnsafeCell<T>`.
449-
unsafe impl<$($tyvar)?> SizeEq<$atomic> for UnsafeCell<$prim> {
453+
unsafe impl<$($tyvar)?> SizeCompat<$atomic> for UnsafeCell<$prim> {
450454
#[inline]
451455
fn cast_from_raw(a: PtrInner<'_, $atomic>) -> PtrInner<'_, UnsafeCell<$prim>> {
452456
// SAFETY: See previous safety comment.
453457
unsafe { cast!(a) }
454458
}
455459
}
456460
// SAFETY: See previous safety comment.
457-
unsafe impl<$($tyvar)?> SizeEq<UnsafeCell<$prim>> for $atomic {
461+
unsafe impl<$($tyvar)?> SizeCompat<UnsafeCell<$prim>> for $atomic {
458462
#[inline]
459463
fn cast_from_raw(p: PtrInner<'_, UnsafeCell<$prim>>) -> PtrInner<'_, $atomic> {
460464
// SAFETY: See previous safety comment.
@@ -464,7 +468,10 @@ mod atomics {
464468

465469
// SAFETY: The caller promised that `$atomic` and `$prim`
466470
// have the same bit validity. `UnsafeCell<T>` has the same
467-
// bit validity as `T` [1].
471+
// bit validity as `T` [1]. `UnsafeCell<T>` also has the
472+
// same size as `T` [1], and so both impls of
473+
// `SizeCompat::cast_from_raw` preserve referent size
474+
// exactly.
468475
//
469476
// [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.UnsafeCell.html#memory-layout:
470477
//

src/layout.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -612,15 +612,15 @@ pub(crate) use cast_from_raw::cast_from_raw;
612612
mod cast_from_raw {
613613
use crate::{pointer::PtrInner, *};
614614

615-
/// Implements [`<Dst as SizeEq<Src>>::cast_from_raw`][cast_from_raw].
615+
/// Implements [`<Dst as SizeCompat<Src>>::cast_from_raw`][cast_from_raw].
616616
///
617617
/// # PME
618618
///
619619
/// Generates a post-monomorphization error if it is not possible to satisfy
620-
/// the soundness conditions of [`SizeEq::cast_from_raw`][cast_from_raw]
620+
/// the soundness conditions of [`SizeCompat::cast_from_raw`][cast_from_raw]
621621
/// for `Src` and `Dst`.
622622
///
623-
/// [cast_from_raw]: crate::pointer::SizeEq::cast_from_raw
623+
/// [cast_from_raw]: crate::pointer::SizeCompat::cast_from_raw
624624
//
625625
// TODO(#1817): Support Sized->Unsized and Unsized->Sized casts
626626
pub(crate) fn cast_from_raw<Src, Dst>(src: PtrInner<'_, Src>) -> PtrInner<'_, Dst>

src/pointer/ptr.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::{
1616
pointer::{
1717
inner::PtrInner,
1818
invariant::*,
19-
transmute::{MutationCompatible, SizeEq, TransmuteFromPtr},
19+
transmute::{MutationCompatible, SizeCompat, TransmuteFromPtr},
2020
},
2121
AlignmentError, CastError, CastType, KnownLayout, SizeError, TryFromBytes, ValidityError,
2222
};
@@ -388,10 +388,10 @@ mod _conversions {
388388
pub(crate) fn transmute<U, V, R>(self) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)>
389389
where
390390
V: Validity,
391-
U: TransmuteFromPtr<T, I::Aliasing, I::Validity, V, R> + SizeEq<T> + ?Sized,
391+
U: TransmuteFromPtr<T, I::Aliasing, I::Validity, V, R> + SizeCompat<T> + ?Sized,
392392
{
393393
// SAFETY:
394-
// - `SizeEq::cast_from_raw` promises to preserve address,
394+
// - `SizeCompat::cast_from_raw` promises to preserve address,
395395
// provenance, and the number of bytes in the referent
396396
// - If aliasing is `Shared`, then by `U: TransmuteFromPtr<T>`, at
397397
// least one of the following holds:
@@ -402,7 +402,7 @@ mod _conversions {
402402
// operate on these references simultaneously
403403
// - By `U: TransmuteFromPtr<T, I::Aliasing, I::Validity, V>`, it is
404404
// sound to perform this transmute.
405-
unsafe { self.transmute_unchecked(|ptr| SizeEq::cast_from_raw(ptr).as_non_null()) }
405+
unsafe { self.transmute_unchecked(|ptr| SizeCompat::cast_from_raw(ptr).as_non_null()) }
406406
}
407407

408408
#[doc(hidden)]

0 commit comments

Comments
 (0)