Skip to content

Commit c1009fc

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

File tree

5 files changed

+178
-112
lines changed

5 files changed

+178
-112
lines changed

src/impls.rs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use core::{
1414
};
1515

1616
use super::*;
17-
use crate::pointer::PtrInner;
1817

1918
safety_comment! {
2019
/// SAFETY:
@@ -115,7 +114,7 @@ safety_comment! {
115114
});
116115
}
117116

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

120119
safety_comment! {
121120
/// SAFETY:
@@ -146,7 +145,7 @@ safety_comment! {
146145
});
147146
}
148147

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

151150
safety_comment! {
152151
/// SAFETY:
@@ -180,14 +179,13 @@ safety_comment! {
180179
});
181180
}
182181

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

185184
macro_rules! unsafe_impl_try_from_bytes_for_nonzero {
186185
($($nonzero:ident[$prim:ty]),*) => {
187186
$(
188187
unsafe_impl!(=> TryFromBytes for $nonzero; |n| {
189-
impl_size_eq!($nonzero, Unalign<$prim>);
190-
188+
impl_size_compat!($nonzero, Unalign<$prim>);
191189
let n = n.transmute::<Unalign<$prim>, invariant::Valid, _>();
192190
$nonzero::new(n.read_unaligned().into_inner()).is_some()
193191
});
@@ -405,23 +403,27 @@ mod atomics {
405403
macro_rules! unsafe_impl_transmute_from_for_atomic {
406404
($($($tyvar:ident)? => $atomic:ty [$prim:ty]),*) => {
407405
const _: () = {
408-
use core::cell::UnsafeCell;
409-
use crate::pointer::{TransmuteFrom, SizeEq, invariant::Valid};
406+
use core::{cell::UnsafeCell};
407+
use crate::pointer::{TransmuteFrom, PtrInner, SizeCompat, invariant::Valid};
410408

411409
$(
412410
#[allow(unused_unsafe)] // Force the caller to call this macro inside `safety_comment!`.
413411
const _: () = unsafe {};
414412

415-
// SAFETY: The caller promised that `$atomic` and `$prim` have
416-
// 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.
417417
unsafe impl<$($tyvar)?> TransmuteFrom<$atomic, Valid, Valid> for $prim {}
418-
// SAFETY: The caller promised that `$atomic` and `$prim` have
419-
// 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.
420422
unsafe impl<$($tyvar)?> TransmuteFrom<$prim, Valid, Valid> for $atomic {}
421423

422-
// SAFETY: The caller promised that `$atomic` and `$prim`
423-
// have the same size.
424-
unsafe impl<$($tyvar)?> SizeEq<$atomic> for $prim {
424+
// SAFETY: See inline safety comment.
425+
unsafe impl<$($tyvar)?> SizeCompat<$atomic> for $prim {
426+
#[inline(always)]
425427
fn cast_from_raw(a: PtrInner<'_, $atomic>) -> PtrInner<'_, $prim> {
426428
// SAFETY: The caller promised that `$atomic` and `$prim`
427429
// have the same size. Thus, this cast preserves
@@ -430,29 +432,34 @@ 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 {
436+
#[inline(always)]
434437
fn cast_from_raw(p: PtrInner<'_, $prim>) -> PtrInner<'_, $atomic> {
435438
// SAFETY: See previous safety comment.
436439
unsafe { cast!(p) }
437440
}
438441
}
442+
439443
// SAFETY: The caller promised that `$atomic` and `$prim`
440444
// have the same size. `UnsafeCell<T>` has the same size as
441-
// `T` [1].
445+
// `T` [1]. Thus, this cast preserves address, referent
446+
// size, and provenance.
442447
//
443448
// [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.UnsafeCell.html#memory-layout:
444449
//
445450
// `UnsafeCell<T>` has the same in-memory representation as
446451
// its inner type `T`. A consequence of this guarantee is that
447452
// it is possible to convert between `T` and `UnsafeCell<T>`.
448-
unsafe impl<$($tyvar)?> SizeEq<$atomic> for UnsafeCell<$prim> {
453+
unsafe impl<$($tyvar)?> SizeCompat<$atomic> for UnsafeCell<$prim> {
454+
#[inline(always)]
449455
fn cast_from_raw(a: PtrInner<'_, $atomic>) -> PtrInner<'_, UnsafeCell<$prim>> {
450456
// SAFETY: See previous safety comment.
451457
unsafe { cast!(a) }
452458
}
453459
}
454460
// SAFETY: See previous safety comment.
455-
unsafe impl<$($tyvar)?> SizeEq<UnsafeCell<$prim>> for $atomic {
461+
unsafe impl<$($tyvar)?> SizeCompat<UnsafeCell<$prim>> for $atomic {
462+
#[inline(always)]
456463
fn cast_from_raw(p: PtrInner<'_, UnsafeCell<$prim>>) -> PtrInner<'_, $atomic> {
457464
// SAFETY: See previous safety comment.
458465
unsafe { cast!(p) }
@@ -461,7 +468,10 @@ mod atomics {
461468

462469
// SAFETY: The caller promised that `$atomic` and `$prim`
463470
// have the same bit validity. `UnsafeCell<T>` has the same
464-
// 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.
465475
//
466476
// [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.UnsafeCell.html#memory-layout:
467477
//

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)