@@ -419,6 +419,38 @@ mod _conversions {
419
419
}
420
420
}
421
421
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
+
422
454
/// `Ptr<'a, T>` → `&'a T`
423
455
impl < ' a , T > Ptr < ' a , T , ( invariant:: Shared , invariant:: Aligned , invariant:: Valid ) >
424
456
where
@@ -460,6 +492,104 @@ mod _conversions {
460
492
}
461
493
}
462
494
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
+
463
593
/// `&'a MaybeUninit<T>` → `Ptr<'a, T>`
464
594
impl < ' a , T > Ptr < ' a , T , ( invariant:: Shared , invariant:: Aligned , invariant:: AnyValidity ) >
465
595
where
@@ -506,6 +636,7 @@ mod _conversions {
506
636
/// State transitions between invariants.
507
637
mod _transitions {
508
638
use super :: * ;
639
+ use crate :: TryFromBytes ;
509
640
510
641
impl < ' a , T , I > Ptr < ' a , T , I >
511
642
where
@@ -592,6 +723,46 @@ mod _transitions {
592
723
unsafe { self . assume_validity :: < invariant:: Valid > ( ) }
593
724
}
594
725
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
+
595
766
/// Forgets that `Ptr`'s referent is validly-aligned for `T`.
596
767
#[ doc( hidden) ]
597
768
#[ inline]
0 commit comments