Skip to content

Commit ce0bb45

Browse files
committed
[WIP][pointer] Support generic TransmuteFrom
Makes progress on #1122
1 parent 0cfcccb commit ce0bb45

File tree

7 files changed

+410
-550
lines changed

7 files changed

+410
-550
lines changed

src/impls.rs

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -443,13 +443,13 @@ mod atomics {
443443
use super::*;
444444

445445
macro_rules! impl_traits_for_atomics {
446-
($($atomics:ident),* $(,)?) => {
446+
($($atomics:ident[$repr:ty]),* $(,)?) => {
447447
$(
448448
impl_known_layout!($atomics);
449-
impl_for_transparent_wrapper!(=> TryFromBytes for $atomics);
450-
impl_for_transparent_wrapper!(=> FromZeros for $atomics);
451-
impl_for_transparent_wrapper!(=> FromBytes for $atomics);
452-
impl_for_transparent_wrapper!(=> IntoBytes for $atomics);
449+
impl_for_transmute_from!(=> TryFromBytes for $atomics[$repr]);
450+
impl_for_transmute_from!(=> FromZeros for $atomics[$repr]);
451+
impl_for_transmute_from!(=> FromBytes for $atomics[$repr]);
452+
impl_for_transmute_from!(=> IntoBytes for $atomics[$repr]);
453453
)*
454454
};
455455
}
@@ -461,13 +461,13 @@ mod atomics {
461461

462462
use super::*;
463463

464-
impl_traits_for_atomics!(AtomicU8, AtomicI8);
464+
impl_traits_for_atomics!(AtomicU8[u8], AtomicI8[i8]);
465465

466466
impl_known_layout!(AtomicBool);
467467

468-
impl_for_transparent_wrapper!(=> TryFromBytes for AtomicBool);
469-
impl_for_transparent_wrapper!(=> FromZeros for AtomicBool);
470-
impl_for_transparent_wrapper!(=> IntoBytes for AtomicBool);
468+
impl_for_transmute_from!(=> TryFromBytes for AtomicBool[bool]);
469+
impl_for_transmute_from!(=> FromZeros for AtomicBool[bool]);
470+
impl_for_transmute_from!(=> IntoBytes for AtomicBool[bool]);
471471

472472
safety_comment! {
473473
/// SAFETY:
@@ -497,7 +497,7 @@ mod atomics {
497497
/// SAFETY:
498498
/// All of these pass an atomic type and that type's native equivalent, as
499499
/// required by the macro safety preconditions.
500-
unsafe_impl_transparent_wrapper_for_atomic!(AtomicU8 [u8], AtomicI8 [i8], AtomicBool [bool]);
500+
unsafe_impl_transmute_from_for_atomic!(AtomicU8 [u8], AtomicI8 [i8], AtomicBool [bool]);
501501
}
502502
}
503503

@@ -508,13 +508,13 @@ mod atomics {
508508

509509
use super::*;
510510

511-
impl_traits_for_atomics!(AtomicU16, AtomicI16);
511+
impl_traits_for_atomics!(AtomicU16[u16], AtomicI16[i16]);
512512

513513
safety_comment! {
514514
/// SAFETY:
515515
/// All of these pass an atomic type and that type's native equivalent, as
516516
/// required by the macro safety preconditions.
517-
unsafe_impl_transparent_wrapper_for_atomic!(AtomicU16 [u16], AtomicI16 [i16]);
517+
unsafe_impl_transmute_from_for_atomic!(AtomicU16 [u16], AtomicI16 [i16]);
518518
}
519519
}
520520

@@ -525,13 +525,13 @@ mod atomics {
525525

526526
use super::*;
527527

528-
impl_traits_for_atomics!(AtomicU32, AtomicI32);
528+
impl_traits_for_atomics!(AtomicU32[u32], AtomicI32[i32]);
529529

530530
safety_comment! {
531531
/// SAFETY:
532532
/// All of these pass an atomic type and that type's native equivalent, as
533533
/// required by the macro safety preconditions.
534-
unsafe_impl_transparent_wrapper_for_atomic!(AtomicU32 [u32], AtomicI32 [i32]);
534+
unsafe_impl_transmute_from_for_atomic!(AtomicU32 [u32], AtomicI32 [i32]);
535535
}
536536
}
537537

@@ -542,13 +542,13 @@ mod atomics {
542542

543543
use super::*;
544544

545-
impl_traits_for_atomics!(AtomicU64, AtomicI64);
545+
impl_traits_for_atomics!(AtomicU64[u64], AtomicI64[i64]);
546546

547547
safety_comment! {
548548
/// SAFETY:
549549
/// All of these pass an atomic type and that type's native equivalent, as
550550
/// required by the macro safety preconditions.
551-
unsafe_impl_transparent_wrapper_for_atomic!(AtomicU64 [u64], AtomicI64 [i64]);
551+
unsafe_impl_transmute_from_for_atomic!(AtomicU64 [u64], AtomicI64 [i64]);
552552
}
553553
}
554554

@@ -559,21 +559,21 @@ mod atomics {
559559

560560
use super::*;
561561

562-
impl_traits_for_atomics!(AtomicUsize, AtomicIsize);
562+
impl_traits_for_atomics!(AtomicUsize[usize], AtomicIsize[isize]);
563563

564564
impl_known_layout!(T => AtomicPtr<T>);
565565

566566
// TODO(#170): Implement `FromBytes` and `IntoBytes` once we implement
567567
// those traits for `*mut T`.
568-
impl_for_transparent_wrapper!(T => TryFromBytes for AtomicPtr<T>);
569-
impl_for_transparent_wrapper!(T => FromZeros for AtomicPtr<T>);
568+
impl_for_transmute_from!(T => TryFromBytes for AtomicPtr<T>[*mut T]);
569+
impl_for_transmute_from!(T => FromZeros for AtomicPtr<T>[*mut T]);
570570

571571
safety_comment! {
572572
/// SAFETY:
573573
/// This passes an atomic type and that type's native equivalent, as
574574
/// required by the macro safety preconditions.
575-
unsafe_impl_transparent_wrapper_for_atomic!(AtomicUsize [usize], AtomicIsize [isize]);
576-
unsafe_impl_transparent_wrapper_for_atomic!(T => AtomicPtr<T> [*mut T]);
575+
unsafe_impl_transmute_from_for_atomic!(AtomicUsize [usize], AtomicIsize [isize]);
576+
unsafe_impl_transmute_from_for_atomic!(T => AtomicPtr<T> [*mut T]);
577577
}
578578
}
579579
}
@@ -603,12 +603,12 @@ safety_comment! {
603603
assert_unaligned!(PhantomData<()>, PhantomData<u8>, PhantomData<u64>);
604604
}
605605

606-
impl_for_transparent_wrapper!(T: Immutable => Immutable for Wrapping<T>);
607-
impl_for_transparent_wrapper!(T: TryFromBytes => TryFromBytes for Wrapping<T>);
608-
impl_for_transparent_wrapper!(T: FromZeros => FromZeros for Wrapping<T>);
609-
impl_for_transparent_wrapper!(T: FromBytes => FromBytes for Wrapping<T>);
610-
impl_for_transparent_wrapper!(T: IntoBytes => IntoBytes for Wrapping<T>);
611-
impl_for_transparent_wrapper!(T: Unaligned => Unaligned for Wrapping<T>);
606+
impl_for_transmute_from!(T: Immutable => Immutable for Wrapping<T>[T]);
607+
impl_for_transmute_from!(T: TryFromBytes => TryFromBytes for Wrapping<T>[T]);
608+
impl_for_transmute_from!(T: FromZeros => FromZeros for Wrapping<T>[T]);
609+
impl_for_transmute_from!(T: FromBytes => FromBytes for Wrapping<T>[T]);
610+
impl_for_transmute_from!(T: IntoBytes => IntoBytes for Wrapping<T>[T]);
611+
impl_for_transmute_from!(T: Unaligned => Unaligned for Wrapping<T>[T]);
612612
assert_unaligned!(Wrapping<()>, Wrapping<u8>);
613613

614614
safety_comment! {
@@ -620,22 +620,22 @@ safety_comment! {
620620
unsafe_impl!(T => FromBytes for MaybeUninit<T>);
621621
}
622622

623-
impl_for_transparent_wrapper!(T: Immutable => Immutable for MaybeUninit<T>);
624-
impl_for_transparent_wrapper!(T: Unaligned => Unaligned for MaybeUninit<T>);
623+
impl_for_transmute_from!(T: Immutable => Immutable for MaybeUninit<T>[T]);
624+
impl_for_transmute_from!(T: Unaligned => Unaligned for MaybeUninit<T>[T]);
625625
assert_unaligned!(MaybeUninit<()>, MaybeUninit<u8>);
626626

627-
impl_for_transparent_wrapper!(T: ?Sized + Immutable => Immutable for ManuallyDrop<T>);
628-
impl_for_transparent_wrapper!(T: ?Sized + TryFromBytes => TryFromBytes for ManuallyDrop<T>);
629-
impl_for_transparent_wrapper!(T: ?Sized + FromZeros => FromZeros for ManuallyDrop<T>);
630-
impl_for_transparent_wrapper!(T: ?Sized + FromBytes => FromBytes for ManuallyDrop<T>);
631-
impl_for_transparent_wrapper!(T: ?Sized + IntoBytes => IntoBytes for ManuallyDrop<T>);
632-
impl_for_transparent_wrapper!(T: ?Sized + Unaligned => Unaligned for ManuallyDrop<T>);
627+
impl_for_transmute_from!(T: ?Sized + Immutable => Immutable for ManuallyDrop<T>[T]);
628+
impl_for_transmute_from!(T: ?Sized + TryFromBytes => TryFromBytes for ManuallyDrop<T>[T]);
629+
impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for ManuallyDrop<T>[T]);
630+
impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for ManuallyDrop<T>[T]);
631+
impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for ManuallyDrop<T>[T]);
632+
impl_for_transmute_from!(T: ?Sized + Unaligned => Unaligned for ManuallyDrop<T>[T]);
633633
assert_unaligned!(ManuallyDrop<()>, ManuallyDrop<u8>);
634634

635-
impl_for_transparent_wrapper!(T: ?Sized + FromZeros => FromZeros for UnsafeCell<T>);
636-
impl_for_transparent_wrapper!(T: ?Sized + FromBytes => FromBytes for UnsafeCell<T>);
637-
impl_for_transparent_wrapper!(T: ?Sized + IntoBytes => IntoBytes for UnsafeCell<T>);
638-
impl_for_transparent_wrapper!(T: ?Sized + Unaligned => Unaligned for UnsafeCell<T>);
635+
impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for UnsafeCell<T>[T]);
636+
impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for UnsafeCell<T>[T]);
637+
impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for UnsafeCell<T>[T]);
638+
impl_for_transmute_from!(T: ?Sized + Unaligned => Unaligned for UnsafeCell<T>[T]);
639639
assert_unaligned!(UnsafeCell<()>, UnsafeCell<u8>);
640640

641641
// SAFETY: See safety comment in `is_bit_valid` impl.

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2718,7 +2718,7 @@ unsafe fn try_read_from<S, T: TryFromBytes>(
27182718
// We use `from_mut` despite not mutating via `c_ptr` so that we don't need
27192719
// to add a `T: Immutable` bound.
27202720
let c_ptr = Ptr::from_mut(&mut candidate);
2721-
let c_ptr = c_ptr.transparent_wrapper_into_inner();
2721+
let c_ptr = c_ptr.transmute();
27222722
// SAFETY: `c_ptr` has no uninitialized sub-ranges because it derived from
27232723
// `candidate`, which the caller promises is entirely initialized.
27242724
let c_ptr = unsafe { c_ptr.assume_validity::<invariant::Initialized>() };

src/pointer/invariant.rs

Lines changed: 139 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
//! Invariants are encoded as ([`Aliasing`], [`Alignment`], [`Validity`])
1414
//! triples implementing the [`Invariants`] trait.
1515
16+
use super::*;
17+
1618
/// The invariants of a [`Ptr`][super::Ptr].
1719
pub trait Invariants: Sealed {
1820
type Aliasing: Aliasing;
@@ -88,7 +90,14 @@ pub trait Validity: Sealed {
8890
///
8991
/// Given `A: Reference`, callers may assume that either `A = Shared` or `A =
9092
/// Exclusive`.
91-
pub trait Reference: Aliasing + Sealed {}
93+
pub trait Reference: Aliasing + Sealed {
94+
fn with<'a, T, I, S, E, O>(ptr: Ptr<'a, T, I>, shared: S, exclusive: E) -> O
95+
where
96+
T: 'a + ?Sized,
97+
I: Invariants<Aliasing = Self>,
98+
S: FnOnce(Ptr<'a, T, I::WithAliasing<Shared>>) -> O,
99+
E: FnOnce(Ptr<'a, T, I::WithAliasing<Exclusive>>) -> O;
100+
}
92101

93102
/// No requirement - any invariant is allowed.
94103
pub enum Any {}
@@ -129,7 +138,18 @@ impl Aliasing for Shared {
129138
type Variance<'a, T: 'a + ?Sized> = &'a T;
130139
type MappedTo<M: AliasingMapping> = M::FromShared;
131140
}
132-
impl Reference for Shared {}
141+
impl Reference for Shared {
142+
#[inline(always)]
143+
fn with<'a, T, I, S, E, O>(ptr: Ptr<'a, T, I>, shared: S, _exclusive: E) -> O
144+
where
145+
T: 'a + ?Sized,
146+
I: Invariants<Aliasing = Shared>,
147+
S: FnOnce(Ptr<'a, T, I::WithAliasing<Shared>>) -> O,
148+
E: FnOnce(Ptr<'a, T, I::WithAliasing<Exclusive>>) -> O,
149+
{
150+
shared(ptr.unify_invariants())
151+
}
152+
}
133153

134154
/// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a mut T`.
135155
///
@@ -142,10 +162,21 @@ impl Aliasing for Exclusive {
142162
type Variance<'a, T: 'a + ?Sized> = &'a mut T;
143163
type MappedTo<M: AliasingMapping> = M::FromExclusive;
144164
}
145-
impl Reference for Exclusive {}
165+
impl Reference for Exclusive {
166+
#[inline(always)]
167+
fn with<'a, T, I, S, E, O>(ptr: Ptr<'a, T, I>, _shared: S, exclusive: E) -> O
168+
where
169+
T: 'a + ?Sized,
170+
I: Invariants<Aliasing = Exclusive>,
171+
S: FnOnce(Ptr<'a, T, I::WithAliasing<Shared>>) -> O,
172+
E: FnOnce(Ptr<'a, T, I::WithAliasing<Exclusive>>) -> O,
173+
{
174+
exclusive(ptr.unify_invariants())
175+
}
176+
}
146177

147-
/// The referent is aligned: for `Ptr<T>`, the referent's address is a
148-
/// multiple of the `T`'s alignment.
178+
/// The referent is aligned: for `Ptr<T>`, the referent's address is a multiple
179+
/// of the `T`'s alignment.
149180
pub enum Aligned {}
150181
impl Alignment for Aligned {
151182
type MappedTo<M: AlignmentMapping> = M::FromAligned;
@@ -182,8 +213,8 @@ impl Validity for AsInitialized {
182213
type MappedTo<M: ValidityMapping> = M::FromAsInitialized;
183214
}
184215

185-
/// The byte ranges in the referent are fully initialized. In other words, if
186-
/// the referent is `N` bytes long, then it contains a bit-valid `[u8; N]`.
216+
/// The byte ranges in the referent are fully initialized. In other words,
217+
/// if the referent is `N` bytes long, then it contains a bit-valid `[u8; N]`.
187218
pub enum Initialized {}
188219
impl Validity for Initialized {
189220
type MappedTo<M: ValidityMapping> = M::FromInitialized;
@@ -296,6 +327,32 @@ pub use mapping::*;
296327
mod mapping {
297328
use super::*;
298329

330+
pub trait Mapping {
331+
type Aliasing: AliasingMapping;
332+
type Alignment: AlignmentMapping;
333+
type Validity: ValidityMapping;
334+
}
335+
336+
// TODO: How to make this less error prone? Right now, e.g.,
337+
// `(Preserved, Any, Preserved)` and `(Any, Preserved, Preserved)` both
338+
// implement `Mapping`, and it's not clear from the definition which
339+
// order the invariants come in.
340+
//
341+
// First attempt was to do `Mapping for ((Aliasing, A), (Alignment, AA),
342+
// (Validity, V))`, but not all of `Aliasing`, `Alignment`, and
343+
// `Validity` are object safe.
344+
impl<A: AliasingMapping, AA: AlignmentMapping, V: ValidityMapping> Mapping for (A, AA, V) {
345+
type Aliasing = A;
346+
type Alignment = AA;
347+
type Validity = V;
348+
}
349+
350+
impl Mapping for Preserved {
351+
type Aliasing = Preserved;
352+
type Alignment = Preserved;
353+
type Validity = Preserved;
354+
}
355+
299356
pub trait AliasingMapping {
300357
type FromAny: Aliasing;
301358
type FromShared: Aliasing;
@@ -314,6 +371,16 @@ mod mapping {
314371
type FromValid: Validity;
315372
}
316373

374+
// TODO: Better name?
375+
pub enum Preserved {}
376+
377+
#[allow(type_alias_bounds)]
378+
pub type Mapped<I: Invariants, M: Mapping> = (
379+
MappedAliasing<I::Aliasing, M::Aliasing>,
380+
MappedAlignment<I::Alignment, M::Alignment>,
381+
MappedValidity<I::Validity, M::Validity>,
382+
);
383+
317384
#[allow(type_alias_bounds)]
318385
pub type MappedAliasing<I: Aliasing, M: AliasingMapping> = I::MappedTo<M>;
319386

@@ -331,13 +398,42 @@ mod mapping {
331398
type FromExclusive = FromExclusive;
332399
}
333400

401+
pub enum UnsafeCellMismatch {}
402+
403+
impl AliasingMapping for UnsafeCellMismatch {
404+
type FromAny = Any;
405+
type FromShared = Any;
406+
type FromExclusive = Exclusive;
407+
}
408+
409+
impl AliasingMapping for Preserved {
410+
type FromAny = Any;
411+
type FromShared = Shared;
412+
type FromExclusive = Exclusive;
413+
}
414+
334415
impl<FromAny: Alignment, FromAligned: Alignment> AlignmentMapping
335-
for ((Any, FromAny), (Shared, FromAligned))
416+
for ((Any, FromAny), (Aligned, FromAligned))
336417
{
337418
type FromAny = FromAny;
338419
type FromAligned = FromAligned;
339420
}
340421

422+
impl AlignmentMapping for Any {
423+
type FromAny = Any;
424+
type FromAligned = Any;
425+
}
426+
427+
impl AlignmentMapping for Preserved {
428+
type FromAny = Any;
429+
type FromAligned = Aligned;
430+
}
431+
432+
impl AlignmentMapping for Aligned {
433+
type FromAny = Aligned;
434+
type FromAligned = Aligned;
435+
}
436+
341437
impl<
342438
FromAny: Validity,
343439
FromAsInitialized: Validity,
@@ -363,4 +459,39 @@ mod mapping {
363459
type FromInitialized = FromInitialized;
364460
type FromValid = Any;
365461
}
462+
463+
impl ValidityMapping for Any {
464+
type FromAny = Any;
465+
type FromAsInitialized = Any;
466+
type FromInitialized = Any;
467+
type FromValid = Any;
468+
}
469+
470+
impl ValidityMapping for Preserved {
471+
type FromAny = Any;
472+
type FromAsInitialized = AsInitialized;
473+
type FromInitialized = Initialized;
474+
type FromValid = Valid;
475+
}
476+
477+
impl ValidityMapping for AsInitialized {
478+
type FromAny = AsInitialized;
479+
type FromAsInitialized = AsInitialized;
480+
type FromInitialized = AsInitialized;
481+
type FromValid = AsInitialized;
482+
}
483+
484+
impl ValidityMapping for Initialized {
485+
type FromAny = Initialized;
486+
type FromAsInitialized = Initialized;
487+
type FromInitialized = Initialized;
488+
type FromValid = Initialized;
489+
}
490+
491+
impl ValidityMapping for Valid {
492+
type FromAny = Valid;
493+
type FromAsInitialized = Valid;
494+
type FromInitialized = Valid;
495+
type FromValid = Valid;
496+
}
366497
}

0 commit comments

Comments
 (0)