Rollup merge of #125897 - RalfJung:from-ref, r=Amanieu
from_ref, from_mut: clarify documentation This was brought up [here](https://github.com/rust-lang/rust/issues/56604#issuecomment-2143193486). 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.
This commit is contained in:
commit
51734a8a6d
@ -1277,7 +1277,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
|
|||||||
/// valid for zero sized reads if the vector didn't allocate.
|
/// valid for zero sized reads if the vector didn't allocate.
|
||||||
///
|
///
|
||||||
/// The caller must ensure that the vector outlives the pointer this
|
/// The caller must ensure that the vector outlives the pointer this
|
||||||
/// function returns, or else it will end up pointing to garbage.
|
/// function returns, or else it will end up dangling.
|
||||||
/// Modifying the vector may cause its buffer to be reallocated,
|
/// Modifying the vector may cause its buffer to be reallocated,
|
||||||
/// which would also make any pointers to it invalid.
|
/// which would also make any pointers to it invalid.
|
||||||
///
|
///
|
||||||
@ -1337,7 +1337,7 @@ pub fn as_ptr(&self) -> *const T {
|
|||||||
/// raw pointer valid for zero sized reads if the vector didn't allocate.
|
/// raw pointer valid for zero sized reads if the vector didn't allocate.
|
||||||
///
|
///
|
||||||
/// The caller must ensure that the vector outlives the pointer this
|
/// The caller must ensure that the vector outlives the pointer this
|
||||||
/// function returns, or else it will end up pointing to garbage.
|
/// function returns, or else it will end up dangling.
|
||||||
/// Modifying the vector may cause its buffer to be reallocated,
|
/// Modifying the vector may cause its buffer to be reallocated,
|
||||||
/// which would also make any pointers to it invalid.
|
/// which would also make any pointers to it invalid.
|
||||||
///
|
///
|
||||||
|
@ -777,8 +777,51 @@ pub fn with_exposed_provenance_mut<T>(addr: usize) -> *mut T
|
|||||||
|
|
||||||
/// Convert a reference to a raw pointer.
|
/// Convert a reference to a raw pointer.
|
||||||
///
|
///
|
||||||
/// This is equivalent to `r as *const T`, but is a bit safer since it will never silently change
|
/// For `r: &T`, `from_ref(r)` is equivalent to `r as *const T` (except for the caveat noted below),
|
||||||
/// type or mutability, in particular if the code is refactored.
|
/// but is a bit safer since it will never silently change type or mutability, in particular if the
|
||||||
|
/// code is refactored.
|
||||||
|
///
|
||||||
|
/// The caller must ensure that the pointee outlives the pointer this function returns, or else it
|
||||||
|
/// will end up dangling.
|
||||||
|
///
|
||||||
|
/// The caller must also ensure that the memory the pointer (non-transitively) points to is never
|
||||||
|
/// written to (except inside an `UnsafeCell`) using this pointer or any pointer derived from it. If
|
||||||
|
/// you need to mutate the pointee, use [`from_mut`]`. Specifically, to turn a mutable reference `m:
|
||||||
|
/// &mut T` into `*const T`, prefer `from_mut(m).cast_const()` to obtain a pointer that can later be
|
||||||
|
/// used for mutation.
|
||||||
|
///
|
||||||
|
/// ## Interaction with lifetime extension
|
||||||
|
///
|
||||||
|
/// Note that this has subtle interactions with the rules for lifetime extension of temporaries in
|
||||||
|
/// tail expressions. This code is valid, albeit in a non-obvious way:
|
||||||
|
/// ```rust
|
||||||
|
/// # type T = i32;
|
||||||
|
/// # fn foo() -> T { 42 }
|
||||||
|
/// // The temporary holding the return value of `foo` has its lifetime extended,
|
||||||
|
/// // because the surrounding expression involves no function call.
|
||||||
|
/// let p = &foo() as *const T;
|
||||||
|
/// unsafe { p.read() };
|
||||||
|
/// ```
|
||||||
|
/// Naively replacing the cast with `from_ref` is not valid:
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// # use std::ptr;
|
||||||
|
/// # type T = i32;
|
||||||
|
/// # fn foo() -> T { 42 }
|
||||||
|
/// // The temporary holding the return value of `foo` does *not* have its lifetime extended,
|
||||||
|
/// // because the surrounding expression involves no function call.
|
||||||
|
/// let p = ptr::from_ref(&foo());
|
||||||
|
/// unsafe { p.read() }; // UB! Reading from a dangling pointer ⚠️
|
||||||
|
/// ```
|
||||||
|
/// The recommended way to write this code is to avoid relying on lifetime extension
|
||||||
|
/// when raw pointers are involved:
|
||||||
|
/// ```rust
|
||||||
|
/// # use std::ptr;
|
||||||
|
/// # type T = i32;
|
||||||
|
/// # fn foo() -> T { 42 }
|
||||||
|
/// let x = foo();
|
||||||
|
/// let p = ptr::from_ref(&x);
|
||||||
|
/// unsafe { p.read() };
|
||||||
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "ptr_from_ref", since = "1.76.0")]
|
#[stable(feature = "ptr_from_ref", since = "1.76.0")]
|
||||||
@ -791,8 +834,45 @@ pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
|
|||||||
|
|
||||||
/// Convert a mutable reference to a raw pointer.
|
/// Convert a mutable reference to a raw pointer.
|
||||||
///
|
///
|
||||||
/// This is equivalent to `r as *mut T`, but is a bit safer since it will never silently change
|
/// For `r: &mut T`, `from_mut(r)` is equivalent to `r as *mut T` (except for the caveat noted
|
||||||
/// type or mutability, in particular if the code is refactored.
|
/// below), but is a bit safer since it will never silently change type or mutability, in particular
|
||||||
|
/// if the code is refactored.
|
||||||
|
///
|
||||||
|
/// The caller must ensure that the pointee outlives the pointer this function returns, or else it
|
||||||
|
/// will end up dangling.
|
||||||
|
///
|
||||||
|
/// ## Interaction with lifetime extension
|
||||||
|
///
|
||||||
|
/// Note that this has subtle interactions with the rules for lifetime extension of temporaries in
|
||||||
|
/// tail expressions. This code is valid, albeit in a non-obvious way:
|
||||||
|
/// ```rust
|
||||||
|
/// # type T = i32;
|
||||||
|
/// # fn foo() -> T { 42 }
|
||||||
|
/// // The temporary holding the return value of `foo` has its lifetime extended,
|
||||||
|
/// // because the surrounding expression involves no function call.
|
||||||
|
/// let p = &mut foo() as *mut T;
|
||||||
|
/// unsafe { p.write(T::default()) };
|
||||||
|
/// ```
|
||||||
|
/// Naively replacing the cast with `from_mut` is not valid:
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// # use std::ptr;
|
||||||
|
/// # type T = i32;
|
||||||
|
/// # fn foo() -> T { 42 }
|
||||||
|
/// // The temporary holding the return value of `foo` does *not* have its lifetime extended,
|
||||||
|
/// // because the surrounding expression involves no function call.
|
||||||
|
/// let p = ptr::from_mut(&mut foo());
|
||||||
|
/// unsafe { p.write(T::default()) }; // UB! Writing to a dangling pointer ⚠️
|
||||||
|
/// ```
|
||||||
|
/// The recommended way to write this code is to avoid relying on lifetime extension
|
||||||
|
/// when raw pointers are involved:
|
||||||
|
/// ```rust
|
||||||
|
/// # use std::ptr;
|
||||||
|
/// # type T = i32;
|
||||||
|
/// # fn foo() -> T { 42 }
|
||||||
|
/// let mut x = foo();
|
||||||
|
/// let p = ptr::from_mut(&mut x);
|
||||||
|
/// unsafe { p.write(T::default()) };
|
||||||
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "ptr_from_ref", since = "1.76.0")]
|
#[stable(feature = "ptr_from_ref", since = "1.76.0")]
|
||||||
|
@ -726,7 +726,7 @@ pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
|
|||||||
/// Returns a raw pointer to the slice's buffer.
|
/// Returns a raw pointer to the slice's buffer.
|
||||||
///
|
///
|
||||||
/// The caller must ensure that the slice outlives the pointer this
|
/// The caller must ensure that the slice outlives the pointer this
|
||||||
/// function returns, or else it will end up pointing to garbage.
|
/// function returns, or else it will end up dangling.
|
||||||
///
|
///
|
||||||
/// The caller must also ensure that the memory the pointer (non-transitively) points to
|
/// The caller must also ensure that the memory the pointer (non-transitively) points to
|
||||||
/// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
|
/// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
|
||||||
@ -761,7 +761,7 @@ pub const fn as_ptr(&self) -> *const T {
|
|||||||
/// Returns an unsafe mutable pointer to the slice's buffer.
|
/// Returns an unsafe mutable pointer to the slice's buffer.
|
||||||
///
|
///
|
||||||
/// The caller must ensure that the slice outlives the pointer this
|
/// The caller must ensure that the slice outlives the pointer this
|
||||||
/// function returns, or else it will end up pointing to garbage.
|
/// function returns, or else it will end up dangling.
|
||||||
///
|
///
|
||||||
/// Modifying the container referenced by this slice may cause its buffer
|
/// Modifying the container referenced by this slice may cause its buffer
|
||||||
/// to be reallocated, which would also make any pointers to it invalid.
|
/// to be reallocated, which would also make any pointers to it invalid.
|
||||||
|
Loading…
Reference in New Issue
Block a user