Skip to content

Commit a2f2308

Browse files
committed
[WIP] Break TransmuteFrom into Shrink vs Overwrite
Also, only implement TryTransmuteFromPtr once in terms of MutationCompatible. gherrit-pr-id: I1e15473bf871e5b53a6c093e6a79f48e6498aa04
1 parent 9728eab commit a2f2308

File tree

9 files changed

+276
-264
lines changed

9 files changed

+276
-264
lines changed

src/impls.rs

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,13 @@ assert_unaligned!(bool);
105105
// pattern 0x01.
106106
const _: () = unsafe {
107107
unsafe_impl!(=> TryFromBytes for bool; |byte| {
108-
let byte = byte.transmute::<u8, invariant::Valid, _>();
108+
let mut byte = byte;
109+
let byte = byte.reborrow().into_shared().transmute::<u8, invariant::Valid, _>();
109110
*byte.unaligned_as_ref() < 2
110111
})
111112
};
112113

113-
impl_size_compat!(bool, u8);
114+
impl_size_from!(bool, u8);
114115

115116
// SAFETY:
116117
// - `Immutable`: `char` self-evidently does not contain any `UnsafeCell`s.
@@ -135,13 +136,14 @@ const _: () = unsafe { unsafe_impl!(char: Immutable, FromZeros, IntoBytes) };
135136
// `char`.
136137
const _: () = unsafe {
137138
unsafe_impl!(=> TryFromBytes for char; |c| {
138-
let c = c.transmute::<Unalign<u32>, invariant::Valid, _>();
139+
let mut c = c;
140+
let c = c.reborrow().into_shared().transmute::<Unalign<u32>, invariant::Valid, _>();
139141
let c = c.read_unaligned().into_inner();
140142
char::from_u32(c).is_some()
141143
});
142144
};
143145

144-
impl_size_compat!(char, Unalign<u32>);
146+
impl_size_from!(char, Unalign<u32>);
145147

146148
// SAFETY: Per the Reference [1], `str` has the same layout as `[u8]`.
147149
// - `Immutable`: `[u8]` does not contain any `UnsafeCell`s.
@@ -168,20 +170,22 @@ const _: () = unsafe { unsafe_impl!(str: Immutable, FromZeros, IntoBytes, Unalig
168170
// Returns `Err` if the slice is not UTF-8.
169171
const _: () = unsafe {
170172
unsafe_impl!(=> TryFromBytes for str; |c| {
171-
let c = c.transmute::<[u8], invariant::Valid, _>();
173+
let mut c = c;
174+
let c = c.reborrow().into_shared().transmute::<[u8], invariant::Valid, _>();
172175
let c = c.unaligned_as_ref();
173176
core::str::from_utf8(c).is_ok()
174177
})
175178
};
176179

177-
impl_size_compat!(str, [u8]);
180+
impl_size_from!(str, [u8]);
178181

179182
macro_rules! unsafe_impl_try_from_bytes_for_nonzero {
180183
($($nonzero:ident[$prim:ty]),*) => {
181184
$(
182185
unsafe_impl!(=> TryFromBytes for $nonzero; |n| {
183-
impl_size_compat!($nonzero, Unalign<$prim>);
184-
let n = n.transmute::<Unalign<$prim>, invariant::Valid, _>();
186+
impl_size_from!($nonzero, Unalign<$prim>);
187+
let mut n = n;
188+
let n = n.reborrow().into_shared().transmute::<Unalign<$prim>, invariant::Valid, _>();
185189
$nonzero::new(n.read_unaligned().into_inner()).is_some()
186190
});
187191
)*
@@ -397,22 +401,22 @@ mod atomics {
397401
crate::util::macros::__unsafe();
398402

399403
use core::{cell::UnsafeCell};
400-
use crate::pointer::{TransmuteFrom, PtrInner, SizeCompat, invariant::Valid};
404+
use crate::pointer::{TransmuteFrom, PtrInner, SizeFrom, invariant::Valid};
401405

402406
$(
403-
// SAFETY: The caller promised that `$atomic` and `$prim`
404-
// have the same size and bit validity. As a result of size
405-
// equality, both impls of `SizeCompat::cast_from_raw`
406-
// preserve referent size exactly.
407+
// SAFETY: The caller promised that `$atomic` and `$prim` have
408+
// the same size and bit validity. As a result of size equality,
409+
// both impls of `SizeFrom::cast_from_raw` preserve referent
410+
// size exactly.
407411
unsafe impl<$($tyvar)?> TransmuteFrom<$atomic, Valid, Valid> for $prim {}
408-
// SAFETY: The caller promised that `$atomic` and `$prim`
409-
// have the same size and bit validity. As a result of size
410-
// equality, both impls of `SizeCompat::cast_from_raw`
411-
// preserve referent size exactly.
412+
// SAFETY: The caller promised that `$atomic` and `$prim` have
413+
// the same size and bit validity. As a result of size equality,
414+
// both impls of `SizeFrom::cast_from_raw` preserve referent
415+
// size exactly.
412416
unsafe impl<$($tyvar)?> TransmuteFrom<$prim, Valid, Valid> for $atomic {}
413417

414418
// SAFETY: See inline safety comment.
415-
unsafe impl<$($tyvar)?> SizeCompat<$atomic> for $prim {
419+
unsafe impl<$($tyvar)?> SizeFrom<$atomic> for $prim {
416420
#[inline]
417421
fn cast_from_raw(a: PtrInner<'_, $atomic>) -> PtrInner<'_, $prim> {
418422
// SAFETY: The caller promised that `$atomic` and `$prim`
@@ -422,7 +426,7 @@ mod atomics {
422426
}
423427
}
424428
// SAFETY: See previous safety comment.
425-
unsafe impl<$($tyvar)?> SizeCompat<$prim> for $atomic {
429+
unsafe impl<$($tyvar)?> SizeFrom<$prim> for $atomic {
426430
#[inline]
427431
fn cast_from_raw(p: PtrInner<'_, $prim>) -> PtrInner<'_, $atomic> {
428432
// SAFETY: See previous safety comment.
@@ -440,28 +444,27 @@ mod atomics {
440444
// `UnsafeCell<T>` has the same in-memory representation as
441445
// its inner type `T`. A consequence of this guarantee is that
442446
// it is possible to convert between `T` and `UnsafeCell<T>`.
443-
unsafe impl<$($tyvar)?> SizeCompat<$atomic> for UnsafeCell<$prim> {
447+
unsafe impl<$($tyvar)?> SizeFrom<$atomic> for UnsafeCell<$prim> {
444448
#[inline]
445449
fn cast_from_raw(a: PtrInner<'_, $atomic>) -> PtrInner<'_, UnsafeCell<$prim>> {
446450
// SAFETY: See previous safety comment.
447451
unsafe { cast!(a) }
448452
}
449453
}
450454
// SAFETY: See previous safety comment.
451-
unsafe impl<$($tyvar)?> SizeCompat<UnsafeCell<$prim>> for $atomic {
455+
unsafe impl<$($tyvar)?> SizeFrom<UnsafeCell<$prim>> for $atomic {
452456
#[inline]
453457
fn cast_from_raw(p: PtrInner<'_, UnsafeCell<$prim>>) -> PtrInner<'_, $atomic> {
454458
// SAFETY: See previous safety comment.
455459
unsafe { cast!(p) }
456460
}
457461
}
458462

459-
// SAFETY: The caller promised that `$atomic` and `$prim`
460-
// have the same bit validity. `UnsafeCell<T>` has the same
461-
// bit validity as `T` [1]. `UnsafeCell<T>` also has the
462-
// same size as `T` [1], and so both impls of
463-
// `SizeCompat::cast_from_raw` preserve referent size
464-
// exactly.
463+
// SAFETY: The caller promised that `$atomic` and `$prim` have
464+
// the same bit validity. `UnsafeCell<T>` has the same bit
465+
// validity as `T` [1]. `UnsafeCell<T>` also has the same size
466+
// as `T` [1], and so both impls of `SizeFrom::cast_from_raw`
467+
// preserve referent size exactly.
465468
//
466469
// [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.UnsafeCell.html#memory-layout:
467470
//

src/lib.rs

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ use core::{
381381
#[cfg(feature = "std")]
382382
use std::io;
383383

384-
use crate::pointer::invariant::{self, BecauseExclusive};
384+
use crate::pointer::{invariant, BecauseBidirectional};
385385

386386
#[cfg(any(feature = "alloc", test, kani))]
387387
extern crate alloc;
@@ -1840,7 +1840,7 @@ pub unsafe trait TryFromBytes {
18401840
Self: KnownLayout + IntoBytes,
18411841
{
18421842
static_assert_dst_is_not_zst!(Self);
1843-
match Ptr::from_mut(bytes).try_cast_into_no_leftover::<Self, BecauseExclusive>(None) {
1843+
match Ptr::from_mut(bytes).try_cast_into_no_leftover(None) {
18441844
Ok(source) => {
18451845
// This call may panic. If that happens, it doesn't cause any soundness
18461846
// issues, as we have not generated any invalid state which we need to
@@ -1852,9 +1852,7 @@ pub unsafe trait TryFromBytes {
18521852
// condition will not happen.
18531853
match source.try_into_valid() {
18541854
Ok(source) => Ok(source.as_mut()),
1855-
Err(e) => {
1856-
Err(e.map_src(|src| src.as_bytes::<BecauseExclusive>().as_mut()).into())
1857-
}
1855+
Err(e) => Err(e.map_src(|src| src.as_bytes().as_mut()).into()),
18581856
}
18591857
}
18601858
Err(e) => Err(e.map_src(Ptr::as_mut).into()),
@@ -2421,8 +2419,7 @@ pub unsafe trait TryFromBytes {
24212419
where
24222420
Self: KnownLayout<PointerMetadata = usize> + IntoBytes,
24232421
{
2424-
match Ptr::from_mut(source).try_cast_into_no_leftover::<Self, BecauseExclusive>(Some(count))
2425-
{
2422+
match Ptr::from_mut(source).try_cast_into_no_leftover(Some(count)) {
24262423
Ok(source) => {
24272424
// This call may panic. If that happens, it doesn't cause any soundness
24282425
// issues, as we have not generated any invalid state which we need to
@@ -2434,9 +2431,7 @@ pub unsafe trait TryFromBytes {
24342431
// condition will not happen.
24352432
match source.try_into_valid() {
24362433
Ok(source) => Ok(source.as_mut()),
2437-
Err(e) => {
2438-
Err(e.map_src(|src| src.as_bytes::<BecauseExclusive>().as_mut()).into())
2439-
}
2434+
Err(e) => Err(e.map_src(|src| src.as_bytes().as_mut()).into()),
24402435
}
24412436
}
24422437
Err(e) => Err(e.map_src(Ptr::as_mut).into()),
@@ -2844,7 +2839,7 @@ fn try_mut_from_prefix_suffix<T: IntoBytes + TryFromBytes + KnownLayout + ?Sized
28442839
cast_type: CastType,
28452840
meta: Option<T::PointerMetadata>,
28462841
) -> Result<(&mut T, &mut [u8]), TryCastError<&mut [u8], T>> {
2847-
match Ptr::from_mut(candidate).try_cast_into::<T, BecauseExclusive>(cast_type, meta) {
2842+
match Ptr::from_mut(candidate).try_cast_into(cast_type, meta) {
28482843
Ok((candidate, prefix_suffix)) => {
28492844
// This call may panic. If that happens, it doesn't cause any soundness
28502845
// issues, as we have not generated any invalid state which we need to
@@ -2856,7 +2851,7 @@ fn try_mut_from_prefix_suffix<T: IntoBytes + TryFromBytes + KnownLayout + ?Sized
28562851
// condition will not happen.
28572852
match candidate.try_into_valid() {
28582853
Ok(valid) => Ok((valid.as_mut(), prefix_suffix.as_mut())),
2859-
Err(e) => Err(e.map_src(|src| src.as_bytes::<BecauseExclusive>().as_mut()).into()),
2854+
Err(e) => Err(e.map_src(|src| src.as_bytes().as_mut()).into()),
28602855
}
28612856
}
28622857
Err(e) => Err(e.map_src(Ptr::as_mut).into()),
@@ -3835,8 +3830,8 @@ pub unsafe trait FromBytes: FromZeros {
38353830
Self: IntoBytes + KnownLayout,
38363831
{
38373832
static_assert_dst_is_not_zst!(Self);
3838-
match Ptr::from_mut(source).try_cast_into_no_leftover::<_, BecauseExclusive>(None) {
3839-
Ok(ptr) => Ok(ptr.recall_validity::<_, (_, (_, _))>().as_mut()),
3833+
match Ptr::from_mut(source).try_cast_into_no_leftover(None) {
3834+
Ok(ptr) => Ok(ptr.recall_validity::<_, BecauseBidirectional>().as_mut()),
38403835
Err(err) => Err(err.map_src(|src| src.as_mut())),
38413836
}
38423837
}
@@ -4304,11 +4299,9 @@ pub unsafe trait FromBytes: FromZeros {
43044299
Self: IntoBytes + KnownLayout<PointerMetadata = usize> + Immutable,
43054300
{
43064301
let source = Ptr::from_mut(source);
4307-
let maybe_slf = source.try_cast_into_no_leftover::<_, BecauseImmutable>(Some(count));
4302+
let maybe_slf = source.try_cast_into_no_leftover(Some(count));
43084303
match maybe_slf {
4309-
Ok(slf) => Ok(slf
4310-
.recall_validity::<_, (_, (_, (BecauseExclusive, BecauseExclusive)))>()
4311-
.as_mut()),
4304+
Ok(slf) => Ok(slf.recall_validity::<_, BecauseBidirectional>().as_mut()),
43124305
Err(err) => Err(err.map_src(|s| s.as_mut())),
43134306
}
43144307
}
@@ -4665,7 +4658,7 @@ pub unsafe trait FromBytes: FromZeros {
46654658
// cannot be violated even though `buf` may have more permissive bit
46664659
// validity than `ptr`.
46674660
let ptr = unsafe { ptr.assume_validity::<invariant::Initialized>() };
4668-
let ptr = ptr.as_bytes::<BecauseExclusive>();
4661+
let ptr = ptr.as_bytes();
46694662
src.read_exact(ptr.as_mut())?;
46704663
// SAFETY: `buf` entirely consists of initialized bytes, and `Self` is
46714664
// `FromBytes`.
@@ -4784,9 +4777,9 @@ fn mut_from_prefix_suffix<T: FromBytes + IntoBytes + KnownLayout + ?Sized>(
47844777
cast_type: CastType,
47854778
) -> Result<(&mut T, &mut [u8]), CastError<&mut [u8], T>> {
47864779
let (slf, prefix_suffix) = Ptr::from_mut(source)
4787-
.try_cast_into::<_, BecauseExclusive>(cast_type, meta)
4780+
.try_cast_into(cast_type, meta)
47884781
.map_err(|err| err.map_src(|s| s.as_mut()))?;
4789-
Ok((slf.recall_validity::<_, (_, (_, _))>().as_mut(), prefix_suffix.as_mut()))
4782+
Ok((slf.recall_validity::<_, BecauseBidirectional>().as_mut(), prefix_suffix.as_mut()))
47904783
}
47914784

47924785
/// Analyzes whether a type is [`IntoBytes`].

src/pointer/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ mod transmute;
1818
pub use {inner::PtrInner, transmute::*};
1919
#[doc(hidden)]
2020
pub use {
21-
invariant::{BecauseExclusive, BecauseImmutable, Read},
21+
invariant::{BecauseExclusive, Read},
2222
ptr::Ptr,
2323
};
2424

@@ -30,11 +30,11 @@ pub type Maybe<'a, T, Aliasing = invariant::Shared, Alignment = invariant::Unali
3030
Ptr<'a, T, (Aliasing, Alignment, invariant::Initialized)>;
3131

3232
/// Checks if the referent is zeroed.
33-
pub(crate) fn is_zeroed<T, I>(ptr: Ptr<'_, T, I>) -> bool
33+
pub(crate) fn is_zeroed<T, I>(mut ptr: Ptr<'_, T, I>) -> bool
3434
where
3535
T: crate::Immutable + crate::KnownLayout,
3636
I: invariant::Invariants<Validity = invariant::Initialized>,
3737
I::Aliasing: invariant::Reference,
3838
{
39-
ptr.as_bytes::<BecauseImmutable>().as_ref().iter().all(|&byte| byte == 0)
39+
ptr.reborrow().into_shared().as_bytes().as_ref().iter().all(|&byte| byte == 0)
4040
}

0 commit comments

Comments
 (0)