Skip to content

Commit d6f970a

Browse files
authored
Rollup merge of rust-lang#125897 - RalfJung:from-ref, r=Amanieu
from_ref, from_mut: clarify documentation This was brought up [here](rust-lang#56604 (comment)). The domain of quantification is generally always constrained by the type in the type signature, and I am not sure it's always worth spelling that out explicitly as that makes things exceedingly verbose. But since this was explicitly brought up, let's clarify.
2 parents 339f756 + dbbb4ab commit d6f970a

File tree

3 files changed

+88
-8
lines changed

3 files changed

+88
-8
lines changed

alloc/src/vec/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1277,7 +1277,7 @@ impl<T, A: Allocator> Vec<T, A> {
12771277
/// valid for zero sized reads if the vector didn't allocate.
12781278
///
12791279
/// The caller must ensure that the vector outlives the pointer this
1280-
/// function returns, or else it will end up pointing to garbage.
1280+
/// function returns, or else it will end up dangling.
12811281
/// Modifying the vector may cause its buffer to be reallocated,
12821282
/// which would also make any pointers to it invalid.
12831283
///
@@ -1337,7 +1337,7 @@ impl<T, A: Allocator> Vec<T, A> {
13371337
/// raw pointer valid for zero sized reads if the vector didn't allocate.
13381338
///
13391339
/// The caller must ensure that the vector outlives the pointer this
1340-
/// function returns, or else it will end up pointing to garbage.
1340+
/// function returns, or else it will end up dangling.
13411341
/// Modifying the vector may cause its buffer to be reallocated,
13421342
/// which would also make any pointers to it invalid.
13431343
///

core/src/ptr/mod.rs

+84-4
Original file line numberDiff line numberDiff line change
@@ -777,8 +777,51 @@ where
777777

778778
/// Convert a reference to a raw pointer.
779779
///
780-
/// This is equivalent to `r as *const T`, but is a bit safer since it will never silently change
781-
/// type or mutability, in particular if the code is refactored.
780+
/// For `r: &T`, `from_ref(r)` is equivalent to `r as *const T` (except for the caveat noted below),
781+
/// but is a bit safer since it will never silently change type or mutability, in particular if the
782+
/// code is refactored.
783+
///
784+
/// The caller must ensure that the pointee outlives the pointer this function returns, or else it
785+
/// will end up dangling.
786+
///
787+
/// The caller must also ensure that the memory the pointer (non-transitively) points to is never
788+
/// written to (except inside an `UnsafeCell`) using this pointer or any pointer derived from it. If
789+
/// you need to mutate the pointee, use [`from_mut`]`. Specifically, to turn a mutable reference `m:
790+
/// &mut T` into `*const T`, prefer `from_mut(m).cast_const()` to obtain a pointer that can later be
791+
/// used for mutation.
792+
///
793+
/// ## Interaction with lifetime extension
794+
///
795+
/// Note that this has subtle interactions with the rules for lifetime extension of temporaries in
796+
/// tail expressions. This code is valid, albeit in a non-obvious way:
797+
/// ```rust
798+
/// # type T = i32;
799+
/// # fn foo() -> T { 42 }
800+
/// // The temporary holding the return value of `foo` has its lifetime extended,
801+
/// // because the surrounding expression involves no function call.
802+
/// let p = &foo() as *const T;
803+
/// unsafe { p.read() };
804+
/// ```
805+
/// Naively replacing the cast with `from_ref` is not valid:
806+
/// ```rust,no_run
807+
/// # use std::ptr;
808+
/// # type T = i32;
809+
/// # fn foo() -> T { 42 }
810+
/// // The temporary holding the return value of `foo` does *not* have its lifetime extended,
811+
/// // because the surrounding expression involves no function call.
812+
/// let p = ptr::from_ref(&foo());
813+
/// unsafe { p.read() }; // UB! Reading from a dangling pointer ⚠️
814+
/// ```
815+
/// The recommended way to write this code is to avoid relying on lifetime extension
816+
/// when raw pointers are involved:
817+
/// ```rust
818+
/// # use std::ptr;
819+
/// # type T = i32;
820+
/// # fn foo() -> T { 42 }
821+
/// let x = foo();
822+
/// let p = ptr::from_ref(&x);
823+
/// unsafe { p.read() };
824+
/// ```
782825
#[inline(always)]
783826
#[must_use]
784827
#[stable(feature = "ptr_from_ref", since = "1.76.0")]
@@ -791,8 +834,45 @@ pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
791834

792835
/// Convert a mutable reference to a raw pointer.
793836
///
794-
/// This is equivalent to `r as *mut T`, but is a bit safer since it will never silently change
795-
/// type or mutability, in particular if the code is refactored.
837+
/// For `r: &mut T`, `from_mut(r)` is equivalent to `r as *mut T` (except for the caveat noted
838+
/// below), but is a bit safer since it will never silently change type or mutability, in particular
839+
/// if the code is refactored.
840+
///
841+
/// The caller must ensure that the pointee outlives the pointer this function returns, or else it
842+
/// will end up dangling.
843+
///
844+
/// ## Interaction with lifetime extension
845+
///
846+
/// Note that this has subtle interactions with the rules for lifetime extension of temporaries in
847+
/// tail expressions. This code is valid, albeit in a non-obvious way:
848+
/// ```rust
849+
/// # type T = i32;
850+
/// # fn foo() -> T { 42 }
851+
/// // The temporary holding the return value of `foo` has its lifetime extended,
852+
/// // because the surrounding expression involves no function call.
853+
/// let p = &mut foo() as *mut T;
854+
/// unsafe { p.write(T::default()) };
855+
/// ```
856+
/// Naively replacing the cast with `from_mut` is not valid:
857+
/// ```rust,no_run
858+
/// # use std::ptr;
859+
/// # type T = i32;
860+
/// # fn foo() -> T { 42 }
861+
/// // The temporary holding the return value of `foo` does *not* have its lifetime extended,
862+
/// // because the surrounding expression involves no function call.
863+
/// let p = ptr::from_mut(&mut foo());
864+
/// unsafe { p.write(T::default()) }; // UB! Writing to a dangling pointer ⚠️
865+
/// ```
866+
/// The recommended way to write this code is to avoid relying on lifetime extension
867+
/// when raw pointers are involved:
868+
/// ```rust
869+
/// # use std::ptr;
870+
/// # type T = i32;
871+
/// # fn foo() -> T { 42 }
872+
/// let mut x = foo();
873+
/// let p = ptr::from_mut(&mut x);
874+
/// unsafe { p.write(T::default()) };
875+
/// ```
796876
#[inline(always)]
797877
#[must_use]
798878
#[stable(feature = "ptr_from_ref", since = "1.76.0")]

core/src/slice/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ impl<T> [T] {
726726
/// Returns a raw pointer to the slice's buffer.
727727
///
728728
/// The caller must ensure that the slice outlives the pointer this
729-
/// function returns, or else it will end up pointing to garbage.
729+
/// function returns, or else it will end up dangling.
730730
///
731731
/// The caller must also ensure that the memory the pointer (non-transitively) points to
732732
/// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
@@ -761,7 +761,7 @@ impl<T> [T] {
761761
/// Returns an unsafe mutable pointer to the slice's buffer.
762762
///
763763
/// The caller must ensure that the slice outlives the pointer this
764-
/// function returns, or else it will end up pointing to garbage.
764+
/// function returns, or else it will end up dangling.
765765
///
766766
/// Modifying the container referenced by this slice may cause its buffer
767767
/// to be reallocated, which would also make any pointers to it invalid.

0 commit comments

Comments
 (0)