@@ -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" ) ]
0 commit comments