@@ -777,17 +777,51 @@ where
777777
778778/// Convert a reference to a raw pointer.
779779///
780- /// For `r: &T`, `from_ref(r)` is equivalent to `r as *const T`, but is a bit safer since it will
781- /// never silently change 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.
782783///
783784/// The caller must ensure that the pointee outlives the pointer this function returns, or else it
784- /// will end up pointing to garbage .
785+ /// will end up dangling .
785786///
786787/// The caller must also ensure that the memory the pointer (non-transitively) points to is never
787788/// written to (except inside an `UnsafeCell`) using this pointer or any pointer derived from it. If
788789/// you need to mutate the pointee, use [`from_mut`]`. Specifically, to turn a mutable reference `m:
789790/// &mut T` into `*const T`, prefer `from_mut(m).cast_const()` to obtain a pointer that can later be
790791/// 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+ /// ```
791825#[ inline( always) ]
792826#[ must_use]
793827#[ stable( feature = "ptr_from_ref" , since = "1.76.0" ) ]
@@ -800,11 +834,45 @@ pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
800834
801835/// Convert a mutable reference to a raw pointer.
802836///
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+ ///
803841/// The caller must ensure that the pointee outlives the pointer this function returns, or else it
804- /// will end up pointing to garbage.
842+ /// will end up dangling.
843+ ///
844+ /// ## Interaction with lifetime extension
805845///
806- /// For `r: &mut T`, `from_mut(r)` is equivalent to `r as *mut T`, but is a bit safer since it will
807- /// never silently change type or mutability, in particular if the code is refactored.
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+ /// ```
808876#[ inline( always) ]
809877#[ must_use]
810878#[ stable( feature = "ptr_from_ref" , since = "1.76.0" ) ]
0 commit comments