about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-07-27 18:29:13 +0000
committerbors <bors@rust-lang.org>2024-07-27 18:29:13 +0000
commitfbccf50533b1f287edccb1fc0dd847cd78a1a27e (patch)
treeb1a462aa09b0b4a5190ea4f6534d65958a532c2c /library
parentd9e1dea75e0f57d489068460ef32127e291a07c4 (diff)
parentf62ae7e120438a5802c50bab84bcf983a7014bb7 (diff)
downloadrust-fbccf50533b1f287edccb1fc0dd847cd78a1a27e.tar.gz
rust-fbccf50533b1f287edccb1fc0dd847cd78a1a27e.zip
Auto merge of #128278 - tgross35:rollup-zv7q0h5, r=tgross35
Rollup of 8 pull requests

Successful merges:

 - #125897 (from_ref, from_mut: clarify documentation)
 - #128207 (improve error message when `global_asm!` uses `asm!` options)
 - #128241 (Remove logic to suggest clone of function output)
 - #128259 ([illumos/solaris] set MSG_NOSIGNAL while writing to sockets)
 - #128262 (Delete `SimplifyArmIdentity` and `SimplifyBranchSame` tests)
 - #128266 (update `rust.channel` default value documentation)
 - #128267 (Add rustdoc GUI test to check title with and without search)
 - #128271 (Disable jump threading of float equality)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'library')
-rw-r--r--library/alloc/src/vec/mod.rs4
-rw-r--r--library/core/src/ptr/mod.rs88
-rw-r--r--library/core/src/slice/mod.rs4
-rw-r--r--library/std/src/os/unix/net/datagram.rs4
-rw-r--r--library/std/src/sys_common/net.rs1
5 files changed, 93 insertions, 8 deletions
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 729d5dd4fe4..f63a6dd6749 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1277,7 +1277,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// valid for zero sized reads if the vector didn't allocate.
     ///
     /// 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,
     /// which would also make any pointers to it invalid.
     ///
@@ -1337,7 +1337,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// raw pointer valid for zero sized reads if the vector didn't allocate.
     ///
     /// 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,
     /// which would also make any pointers to it invalid.
     ///
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index f2247e83ec5..9b0aa2e7bfe 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -777,8 +777,51 @@ where
 
 /// 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
-/// type or mutability, in particular if the code is refactored.
+/// For `r: &T`, `from_ref(r)` is equivalent to `r as *const T` (except for the caveat noted 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.
+///
+/// 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)]
 #[must_use]
 #[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.
 ///
-/// This is equivalent to `r as *mut T`, but is a bit safer since it will never silently change
-/// type or mutability, in particular if the code is refactored.
+/// For `r: &mut T`, `from_mut(r)` is equivalent to `r as *mut T` (except for the caveat noted
+/// 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)]
 #[must_use]
 #[stable(feature = "ptr_from_ref", since = "1.76.0")]
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 6d3e625bef4..e09e536722b 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -726,7 +726,7 @@ impl<T> [T] {
     /// Returns a raw pointer to the slice's buffer.
     ///
     /// 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
     /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
@@ -761,7 +761,7 @@ impl<T> [T] {
     /// Returns an unsafe mutable pointer to the slice's buffer.
     ///
     /// 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
     /// to be reallocated, which would also make any pointers to it invalid.
diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs
index b29f9099a11..f58f9b4d9ab 100644
--- a/library/std/src/os/unix/net/datagram.rs
+++ b/library/std/src/os/unix/net/datagram.rs
@@ -20,6 +20,8 @@ use crate::{fmt, io};
     target_os = "freebsd",
     target_os = "openbsd",
     target_os = "netbsd",
+    target_os = "solaris",
+    target_os = "illumos",
     target_os = "haiku",
     target_os = "nto",
 ))]
@@ -31,6 +33,8 @@ use libc::MSG_NOSIGNAL;
     target_os = "freebsd",
     target_os = "openbsd",
     target_os = "netbsd",
+    target_os = "solaris",
+    target_os = "illumos",
     target_os = "haiku",
     target_os = "nto",
 )))]
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 95ca67fc2e0..0a82b50ae1a 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -42,6 +42,7 @@ cfg_if::cfg_if! {
         target_os = "hurd",
         target_os = "dragonfly", target_os = "freebsd",
         target_os = "openbsd", target_os = "netbsd",
+        target_os = "solaris", target_os = "illumos",
         target_os = "haiku", target_os = "nto"))] {
         use libc::MSG_NOSIGNAL;
     } else {