@@ -419,6 +419,38 @@ mod _conversions {
419419 }
420420 }
421421
422+ /// `&'a mut T` → `Ptr<'a, T>`
423+ impl < ' a , T > Ptr < ' a , T , ( invariant:: Exclusive , invariant:: Aligned , invariant:: Valid ) >
424+ where
425+ T : ' a + ?Sized ,
426+ {
427+ /// Constructs a `Ptr` from an exclusive reference.
428+ #[ inline]
429+ pub ( crate ) fn from_mut ( ptr : & ' a mut T ) -> Self {
430+ let ptr = core:: ptr:: NonNull :: from ( ptr) ;
431+ // SAFETY:
432+ // 0. `ptr`, by invariant on `&'a mut T`, is derived from some valid
433+ // Rust allocation, `A`.
434+ // 1. `ptr`, by invariant on `&'a mut T`, has valid provenance for
435+ // `A`.
436+ // 2. `ptr`, by invariant on `&'a mut T`, addresses a byte range
437+ // which is entirely contained in `A`.
438+ // 3. `ptr`, by invariant on `&'a mut T`, addresses a byte range
439+ // whose length fits in an `isize`.
440+ // 4. `ptr`, by invariant on `&'a mut T`, addresses a byte range
441+ // which does not wrap around the address space.
442+ // 5. `A`, by invariant on `&'a mut T`, is guaranteed to live for at
443+ // least `'a`.
444+ // 6. `ptr`, by invariant on `&'a mut T`, conforms to the aliasing
445+ // invariant of `invariant::Exclusive`.
446+ // 7. `ptr`, by invariant on `&'a mut T`, conforms to the alignment
447+ // invariant of `invariant::Aligned`.
448+ // 8. `ptr`, by invariant on `&'a mut T`, conforms to the validity
449+ // invariant of `invariant::Valid`.
450+ unsafe { Self :: new ( ptr) }
451+ }
452+ }
453+
422454 /// `Ptr<'a, T>` → `&'a T`
423455 impl < ' a , T > Ptr < ' a , T , ( invariant:: Shared , invariant:: Aligned , invariant:: Valid ) >
424456 where
@@ -460,6 +492,104 @@ mod _conversions {
460492 }
461493 }
462494
495+ impl < ' a , T , I > Ptr < ' a , T , I >
496+ where
497+ T : ' a + ?Sized ,
498+ I : Invariants ,
499+ I :: Aliasing : invariant:: at_least:: Shared ,
500+ {
501+ /// Reborrows this `Ptr`, producing another `Ptr`.
502+ ///
503+ /// Since `self` is borrowed immutably, this prevents any mutable
504+ /// methods from being called on `self` as long as the returned `Ptr`
505+ /// exists.
506+ #[ allow( clippy:: needless_lifetimes) ] // Allows us to name the lifetime in the safety comment below.
507+ pub ( crate ) fn reborrow < ' b > ( & ' b mut self ) -> Ptr < ' b , T , I >
508+ where
509+ ' a : ' b ,
510+ {
511+ // SAFETY: The following all hold by invariant on `self`, and thus
512+ // hold of `ptr = self.as_non_null()`:
513+ // 0. `ptr` is derived from some valid Rust allocation, `A`.
514+ // 1. `ptr` has valid provenance for `A`.
515+ // 2. `ptr` addresses a byte range which is entirely contained in
516+ // `A`.
517+ // 3. `ptr` addresses a byte range whose length fits in an `isize`.
518+ // 4. `ptr` addresses a byte range which does not wrap around the
519+ // address space.
520+ // 5. `A` is guaranteed to live for at least `'a`.
521+ // 6. SEE BELOW.
522+ // 7. `ptr` conforms to the alignment invariant of
523+ // [`I::Alignment`](invariant::Alignment).
524+ // 8. `ptr` conforms to the validity invariant of
525+ // [`I::Validity`](invariant::Validity).
526+ // 9. During the lifetime 'a, no code will load or store this memory
527+ // region treating `UnsafeCell`s as existing at different ranges
528+ // than they exist in `T`.
529+ // 10. During the lifetime 'a, no reference will exist to this
530+ // memory which treats `UnsafeCell`s as existing at different
531+ // ranges than they exist in `T`.
532+ //
533+ // For aliasing (6 above), since `I::Aliasing:
534+ // invariant::at_least::Shared`, there are two cases for
535+ // `I::Aliasing`:
536+ // - For `invariant::Shared`: `'a` outlives `'b`, and so the
537+ // returned `Ptr` does not permit accessing the referent any
538+ // longer than is possible via `self`. For shared aliasing, it is
539+ // sound for multiple `Ptr`s to exist simultaneously which
540+ // reference the same memory, so creating a new one is not
541+ // problematic.
542+ // - For `invariant::Exclusive`: Since `self` is `&'b mut` and we
543+ // return a `Ptr` with lifetime `'b`, `self` is inaccessible to
544+ // the caller for the lifetime `'b` - in other words, `self` is
545+ // inaccessible to the caller as long as the returned `Ptr`
546+ // exists. Since `self` is an exclusive `Ptr`, no other live
547+ // references or `Ptr`s may exist which refer to the same memory
548+ // while `self` is live. Thus, as long as the returned `Ptr`
549+ // exists, no other references or `Ptr`s which refer to the same
550+ // memory may be live.
551+ unsafe { Ptr :: new ( self . as_non_null ( ) ) }
552+ }
553+ }
554+
555+ /// `Ptr<'a, T>` → `&'a mut T`
556+ impl < ' a , T > Ptr < ' a , T , ( invariant:: Exclusive , invariant:: Aligned , invariant:: Valid ) >
557+ where
558+ T : ' a + ?Sized ,
559+ {
560+ /// Converts the `Ptr` to a mutable reference.
561+ #[ allow( clippy:: wrong_self_convention) ]
562+ pub ( crate ) fn as_mut ( self ) -> & ' a mut T {
563+ let mut raw = self . as_non_null ( ) ;
564+ // SAFETY: This invocation of `NonNull::as_mut` satisfies its
565+ // documented safety preconditions:
566+ //
567+ // 1. The pointer is properly aligned. This is ensured by-contract
568+ // on `Ptr`, because the `ALIGNMENT_INVARIANT` is `Aligned`.
569+ //
570+ // 2. It must be “dereferenceable” in the sense defined in the
571+ // module documentation; i.e.:
572+ //
573+ // > The memory range of the given size starting at the pointer
574+ // > must all be within the bounds of a single allocated object.
575+ // > [2]
576+ //
577+ // This is ensured by contract on all `Ptr`s.
578+ //
579+ // 3. The pointer must point to an initialized instance of `T`. This
580+ // is ensured by-contract on `Ptr`, because the
581+ // `VALIDITY_INVARIANT` is `Valid`.
582+ //
583+ // 4. You must enforce Rust’s aliasing rules. This is ensured by
584+ // contract on `Ptr`, because the `ALIASING_INVARIANT` is
585+ // `Exclusive`.
586+ //
587+ // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_mut
588+ // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety
589+ unsafe { raw. as_mut ( ) }
590+ }
591+ }
592+
463593 /// `&'a MaybeUninit<T>` → `Ptr<'a, T>`
464594 impl < ' a , T > Ptr < ' a , T , ( invariant:: Shared , invariant:: Aligned , invariant:: AnyValidity ) >
465595 where
@@ -506,6 +636,7 @@ mod _conversions {
506636/// State transitions between invariants.
507637mod _transitions {
508638 use super :: * ;
639+ use crate :: TryFromBytes ;
509640
510641 impl < ' a , T , I > Ptr < ' a , T , I >
511642 where
@@ -592,6 +723,46 @@ mod _transitions {
592723 unsafe { self . assume_validity :: < invariant:: Valid > ( ) }
593724 }
594725
726+ /// Checks that `Ptr`'s referent is validly initialized for `T`,
727+ /// returning a `Ptr` with `invariant::Valid` on success.
728+ ///
729+ /// # Panics
730+ ///
731+ /// This method will panic if
732+ /// [`T::is_bit_valid`][TryFromBytes::is_bit_valid] panics.
733+ #[ inline]
734+ pub ( crate ) fn try_into_valid (
735+ mut self ,
736+ ) -> Option < Ptr < ' a , T , ( I :: Aliasing , I :: Alignment , invariant:: Valid ) > >
737+ where
738+ T : TryFromBytes ,
739+ I :: Aliasing : invariant:: at_least:: Shared ,
740+ I : Invariants < Validity = invariant:: Initialized > ,
741+ {
742+ // This call may panic. If that happens, it doesn't cause any soundness
743+ // issues, as we have not generated any invalid state which we need to
744+ // fix before returning.
745+ if T :: is_bit_valid ( self . reborrow ( ) . forget_exclusive ( ) . forget_aligned ( ) ) {
746+ // SAFETY: If `T::is_bit_valid`, code may assume that `self`
747+ // contains a bit-valid instance of `Self`.
748+ Some ( unsafe { self . assume_validity :: < invariant:: Valid > ( ) } )
749+ } else {
750+ None
751+ }
752+ }
753+
754+ /// Forgets that `Ptr`'s referent exclusively references `T`,
755+ /// downgrading to a shared reference.
756+ #[ doc( hidden) ]
757+ #[ inline]
758+ pub fn forget_exclusive ( self ) -> Ptr < ' a , T , ( invariant:: Shared , I :: Alignment , I :: Validity ) >
759+ where
760+ I :: Aliasing : invariant:: at_least:: Shared ,
761+ {
762+ // SAFETY: `I::Aliasing` is at least as restrictive as `Shared`.
763+ unsafe { Ptr :: from_ptr ( self ) }
764+ }
765+
595766 /// Forgets that `Ptr`'s referent is validly-aligned for `T`.
596767 #[ doc( hidden) ]
597768 #[ inline]
0 commit comments