Repository: rust-lang/blog.rust-lang.org
Pull request #1604: 1.87.0 announcement
Author: login: Mark-Simulacrum
Created: 2025-05-04T18:16:34Z | Merged: 2025-05-15T17:29:38Z

[Rendered](https://github.com/rust-lang/blog.rust-lang.org/blob/master/content/Rust-1.87.0/index.md)


Diff:
diff --git a/content/Rust-1.87.0/index.md b/content/Rust-1.87.0/index.md
new file mode 100644
index 000000000..f8aee6878
--- /dev/null
+++ b/content/Rust-1.87.0/index.md
@@ -0,0 +1,265 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0 and ten years of Rust!"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+Live from the [10 Years of Rust celebration](https://2025.rustweek.org/celebration/) in Utrecht, Netherlands,
+the Rust team is happy to announce a new version of Rust, 1.87.0!
+
+![picture of Rustaceans at the release party](party.jpg)
+
+Today's release day happens to fall exactly on the 10 year anniversary of
+[Rust 1.0](https://blog.rust-lang.org/2015/05/15/Rust-1.0/)!
+
+Thank you to the myriad contributors who have worked on Rust, past and present.
+Here's to many more decades of Rust! 🎉
+
+---
+
+As usual, the new version includes all the changes that have been part of the beta version in the
+past six weeks, following the consistent regular release cycle that we have followed since Rust 1.0.
+
+If you have a previous version of Rust installed via `rustup`, you can get 1.87.0 with:
+
+```
+$ rustup update stable
+```
+
+If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.87.0](https://doc.rust-lang.org/stable/releases.html#version-1870-2025-04-03).
+
+If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
+
+## What's in 1.87.0 stable
+
+### Anonymous pipes
+
+1.87 adds access to anonymous pipes to the standard library. This includes
+integration with `std::process::Command`'s input/output methods. For example,
+joining the stdout and stderr streams into one is now relatively
+straightforward, as shown below, while it used to require either extra threads
+or platform-specific functions.
+
+```rust
+use std::process::Command;
+use std::io::Read;
+
+let (mut recv, send) = std::io::pipe()?;
+
+let mut command = Command::new("path/to/bin")
+    // Both stdout and stderr will write to the same pipe, combining the two.
+    .stdout(send.try_clone()?)
+    .stderr(send)
+    .spawn()?;
+
+let mut output = Vec::new();
+recv.read_to_end(&mut output)?;
+
+// It's important that we read from the pipe before the process exits, to avoid
+// filling the OS buffers if the program emits too much output.
+assert!(command.wait()?.success());
+```
+
+### Safe architecture intrinsics
+
+Most `std::arch` intrinsics that are unsafe only due to requiring target
+features to be enabled are now callable in safe code that has those features
+enabled. For example, the following toy program which implements summing an array using
+manual intrinsics can now use safe code for the core loop.
+
+```rust
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+use std::arch::x86_64::*;
+
+fn sum(slice: &[u32]) -> u32 {
+    #[cfg(target_arch = "x86_64")]
+    {
+        if is_x86_feature_detected!("avx2") {
+            // SAFETY: We have detected the feature is enabled at runtime,
+            // so it's safe to call this function.
+            return unsafe { sum_avx2(slice) };
+        }
+    }
+
+    slice.iter().sum()
+}
+
+#[target_feature(enable = "avx2")]
+#[cfg(target_arch = "x86_64")]
+fn sum_avx2(slice: &[u32]) -> u32 {
+    // SAFETY: __m256i and u32 have the same validity.
+    let (prefix, middle, tail) = unsafe { slice.align_to::<__m256i>() };
+    
+    let mut sum = prefix.iter().sum::<u32>();
+    sum += tail.iter().sum::<u32>();
+    
+    // Core loop is now fully safe code in 1.87, because the intrinsics require
+    // matching target features (avx2) to the function definition.
+    let mut base = _mm256_setzero_si256();
+    for e in middle.iter() {
+        base = _mm256_add_epi32(base, *e);
+    }
+    
+    // SAFETY: __m256i and u32 have the same validity.
+    let base: [u32; 8] = unsafe { std::mem::transmute(base) };
+    sum += base.iter().sum::<u32>();
+    
+    sum
+}
+```
+
+### `asm!` jumps to Rust code  
+
+Inline assembly (`asm!`) can now jump to labeled blocks within Rust code. This
+enables more flexible low-level programming, such as implementing optimized
+control flow in OS kernels or interacting with hardware more efficiently. 
+
+- The `asm!` macro now supports a label operand, which acts as a jump target.  
+- The label must be a block expression with a return type of `()` or `!`.  
+- The block executes when jumped to, and execution continues after the `asm!` block.  
+- Using output and label operands in the same `asm!` invocation remains [unstable](https://github.com/rust-lang/rust/issues/119364).  
+
+```rust
+unsafe {
+    asm!(
+        "jmp {}",
+        label {
+            println!("Jumped from asm!");
+        }
+    );
+}
+```
+
+For more details, please consult the [reference](https://doc.rust-lang.org/nightly/reference/inline-assembly.html#r-asm.operand-type.supported-operands.label).
+
+### Precise capturing (`+ use<...>`) in `impl Trait` in trait definitions
+
+This release stabilizes specifying the specific captured generic types and
+lifetimes in trait definitions using `impl Trait` return types. This allows
+using this feature in trait definitions, expanding on the stabilization for
+non-trait functions in
+[1.82](https://blog.rust-lang.org/2024/10/17/Rust-1.82.0/#precise-capturing-use-syntax).
+
+Some example desugarings:
+
+```rust
+trait Foo {
+    fn method<'a>(&'a self) -> impl Sized;
+    
+    // ... desugars to something like:
+    type Implicit1<'a>: Sized;
+    fn method_desugared<'a>(&'a self) -> Self::Implicit1<'a>;
+    
+    // ... whereas with precise capturing ...
+    fn precise<'a>(&'a self) -> impl Sized + use<Self>;
+    
+    // ... desugars to something like:
+    type Implicit2: Sized;
+    fn precise_desugared<'a>(&'a self) -> Self::Implicit2;
+}
+```
+
+### Stabilized APIs
+
+
+- [`Vec::extract_if`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.extract_if)
+- [`vec::ExtractIf`](https://doc.rust-lang.org/stable/std/vec/struct.ExtractIf.html)
+- [`LinkedList::extract_if`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.extract_if)
+- [`linked_list::ExtractIf`](https://doc.rust-lang.org/stable/std/collections/linked_list/struct.ExtractIf.html)
+- [`<[T]>::split_off`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off)
+- [`<[T]>::split_off_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_mut)
+- [`<[T]>::split_off_first`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_first)
+- [`<[T]>::split_off_first_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_first_mut)
+- [`<[T]>::split_off_last`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_last)
+- [`<[T]>::split_off_last_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_last_mut)
+- [`String::extend_from_within`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.extend_from_within)
+- [`os_str::Display`](https://doc.rust-lang.org/stable/std/ffi/os_str/struct.Display.html)
+- [`OsString::display`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.display)
+- [`OsStr::display`](https://doc.rust-lang.org/stable/std/ffi/struct.OsStr.html#method.display)
+- [`io::pipe`](https://doc.rust-lang.org/stable/std/io/fn.pipe.html)
+- [`io::PipeReader`](https://doc.rust-lang.org/stable/std/io/struct.PipeReader.html)
+- [`io::PipeWriter`](https://doc.rust-lang.org/stable/std/io/struct.PipeWriter.html)
+- [`impl From<PipeReader> for OwnedHandle`](https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeReader%3E-for-OwnedHandle)
+- [`impl From<PipeWriter> for OwnedHandle`](https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeWriter%3E-for-OwnedHandle)
+- [`impl From<PipeReader> for Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html)
+- [`impl From<PipeWriter> for Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CPipeWriter%3E-for-Stdio)
+- [`impl From<PipeReader> for OwnedFd`](https://doc.rust-lang.org/stable/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeReader%3E-for-OwnedFd)
+- [`impl From<PipeWriter> for OwnedFd`](https://doc.rust-lang.org/stable/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeWriter%3E-for-OwnedFd)
+- [`Box<MaybeUninit<T>>::write`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.write)
+- [`impl TryFrom<Vec<u8>> for String`](https://doc.rust-lang.org/stable/std/string/struct.String.html#impl-TryFrom%3CVec%3Cu8%3E%3E-for-String)
+- [`<*const T>::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from_unsigned)
+- [`<*const T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.byte_offset_from_unsigned)
+- [`<*mut T>::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from_unsigned-1)
+- [`<*mut T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.byte_offset_from_unsigned-1)
+- [`NonNull::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.offset_from_unsigned)
+- [`NonNull::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.byte_offset_from_unsigned)
+- [`<uN>::cast_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.cast_signed)
+- [`NonZero::<uN>::cast_signed`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.cast_signed-5).
+- [`<iN>::cast_unsigned`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.cast_unsigned).
+- [`NonZero::<iN>::cast_unsigned`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.cast_unsigned-5).
+- [`<uN>::is_multiple_of`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.is_multiple_of)
+- [`<uN>::unbounded_shl`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.unbounded_shl)
+- [`<uN>::unbounded_shr`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.unbounded_shr)
+- [`<iN>::unbounded_shl`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.unbounded_shl)
+- [`<iN>::unbounded_shr`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.unbounded_shr)
+- [`<iN>::midpoint`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.midpoint)
+- [`<str>::from_utf8`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8)
+- [`<str>::from_utf8_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8_mut)
+- [`<str>::from_utf8_unchecked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8_unchecked)
+- [`<str>::from_utf8_unchecked_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8_unchecked_mut)
+
+These previously stable APIs are now stable in const contexts:
+
+- [`core::str::from_utf8_mut`](https://doc.rust-lang.org/stable/std/str/fn.from_utf8_mut.html)
+- [`<[T]>::copy_from_slice`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.copy_from_slice)
+- [`SocketAddr::set_ip`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.set_ip)
+- [`SocketAddr::set_port`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.set_port),
+- [`SocketAddrV4::set_ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.set_ip)
+- [`SocketAddrV4::set_port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.set_port),
+- [`SocketAddrV6::set_ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_ip)
+- [`SocketAddrV6::set_port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_port)
+- [`SocketAddrV6::set_flowinfo`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_flowinfo)
+- [`SocketAddrV6::set_scope_id`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_scope_id)
+- [`char::is_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_digit)
+- [`char::is_whitespace`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_whitespace)
+- [`<[[T; N]]>::as_flattened`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_flattened)
+- [`<[[T; N]]>::as_flattened_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_flattened_mut) 
+- [`String::into_bytes`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.into_bytes)
+- [`String::as_str`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_str)
+- [`String::capacity`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.capacity)
+- [`String::as_bytes`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_bytes)
+- [`String::len`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.len)
+- [`String::is_empty`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.is_empty)
+- [`String::as_mut_str`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_mut_str)
+- [`String::as_mut_vec`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_mut_vec)
+- [`Vec::as_ptr`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_ptr)
+- [`Vec::as_slice`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_slice)
+- [`Vec::capacity`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.capacity)
+- [`Vec::len`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.len)
+- [`Vec::is_empty`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.is_empty)
+- [`Vec::as_mut_slice`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_mut_slice)
+- [`Vec::as_mut_ptr`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_mut_ptr)
+
+### `i586-pc-windows-msvc` target removal
+
+The Tier 2 target `i586-pc-windows-msvc` has been removed. `i586-pc-windows-msvc`'s difference to the much more popular Tier 1 target `i686-pc-windows-msvc` is that `i586-pc-windows-msvc` does not require SSE2 instruction support. But Windows 10, the minimum required OS version of all `windows` targets (except the `win7` targets), requires SSE2 instructions itself.
+
+All users currently targeting `i586-pc-windows-msvc` should migrate to `i686-pc-windows-msvc`.
+
+You can check the [Major Change Proposal](https://github.com/rust-lang/compiler-team/issues/840) for more information.
+
+### Other changes
+
+Check out everything that changed in [Rust](https://github.com/rust-lang/rust/releases/tag/1.87.0), [Cargo](https://doc.rust-lang.org/nightly/cargo/CHANGELOG.html#cargo-187-2025-05-15), and [Clippy](https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-187).
+
+## Contributors to 1.87.0
+
+Many people came together to create Rust 1.87.0. We couldn't have done it without all of you. [Thanks!](https://thanks.rust-lang.org/rust/1.87.0/)
diff --git a/content/Rust-1.87.0/party.jpg b/content/Rust-1.87.0/party.jpg
new file mode 100644
index 000000000..b4dfd2684
Binary files /dev/null and b/content/Rust-1.87.0/party.jpg differ


Reviews:
user: login: Mark-Simulacrum
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-04T18:17:58Z
user: login: emilyalbini
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-04T18:55:12Z
user: login: Mark-Simulacrum
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-04T19:02:37Z
user: login: alex-semenyuk
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-04T19:05:31Z
user: login: emilyalbini
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-04T19:09:18Z
user: login: Mark-Simulacrum
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-04T19:38:22Z
user: login: joshtriplett
body: Here's a first pass at text for the ten-year anniversary release.
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-04T22:20:30Z
user: login: jieyouxu
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-05T08:44:17Z
user: login: Kobzol
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-05T09:30:00Z
user: login: m-ou-se
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-05T10:08:31Z
user: login: m-ou-se
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-05T10:09:48Z
user: login: programmerjake
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-05T21:17:08Z
user: login: programmerjake
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-05T21:18:00Z
user: login: jieyouxu
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-08T13:52:47Z
user: login: traviscross
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T21:48:45Z
user: login: alex-semenyuk
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-09T02:44:27Z
user: login: emilyalbini
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-15T15:05:39Z

Review comments:
diff_hunk: @@ -0,0 +1,252 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
+
+If you have a previous version of Rust installed via `rustup`, you can get 1.87.0 with:
+
+```
+$ rustup update stable
+```
+
+If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.87.0](https://doc.rust-lang.org/stable/releases.html#version-1870-2025-04-03).
+
+If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
+
+## What's in 1.87.0 stable
+
+### Anonymous pipes
+
+1.87 adds access to anonymous pipes to the standard library. This includes
+integration with `std::process::Command`'s input/output methods.
+
+As a toy example, this program uses pipes to stream data into `cat` and read the output:
+
+```rust
+use std::process::Command;
+use std::io::{pipe, Read, Write};
+
+let (ping_rx, mut ping_tx) = pipe()?;
+let (mut pong_rx, pong_tx) = pipe()?;
+
+// Spawn a process that echoes its input.
+let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
+
+ping_tx.write_all(b"hello")?;
+// Close to unblock echo_server's reader.
+drop(ping_tx);
+
+let mut buf = String::new();
+// Block until echo_server's writer is closed.
+pong_rx.read_to_string(&mut buf)?;
+assert_eq!(&buf, "hello");
+
+echo_server.wait()?;
+```
+
+### Safe architecture intrinsics
+
+Most `std::arch` intrinsics that are unsafe only due to requiring target
+features to be enabled are now callable in safe code that has those features
+enabled. For example, the following toy program which implements summing an array using
+manual intrinsics can now use safe code for the core loop.
+
+```rust
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+use std::arch::x86_64::*;
+
+fn sum(slice: &[u32]) -> u32 {
+    #[cfg(target_arch = "x86_64")]
+    {
+        if is_x86_feature_detected!("avx2") {
+            // SAFETY: We have detected the feature is enabled at runtime,
+            // so it's safe to call this function.
+            return unsafe { sum_avx2(slice) };
+        }
+    }
+
+    slice.iter().sum()
+}
+
+#[target_feature(enable = "avx2")]
+#[cfg(target_arch = "x86_64")]
+fn sum_avx2(slice: &[u32]) -> u32 {
path: content/Rust-1.87.0.md
user: login: Mark-Simulacrum
body: Maybe there's a better (shorter?) example that can be fully safe code now except the function call? Something like crc32 perhaps that operates on just u64 values and so doesn't need the align/transmutes?
created_at: 2025-05-04T18:17:56Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,252 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
+
+If you have a previous version of Rust installed via `rustup`, you can get 1.87.0 with:
+
+```
+$ rustup update stable
+```
+
+If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.87.0](https://doc.rust-lang.org/stable/releases.html#version-1870-2025-04-03).
+
+If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
+
+## What's in 1.87.0 stable
+
+### Anonymous pipes
+
+1.87 adds access to anonymous pipes to the standard library. This includes
+integration with `std::process::Command`'s input/output methods.
+
+As a toy example, this program uses pipes to stream data into `cat` and read the output:
path: content/Rust-1.87.0.md
user: login: emilyalbini
body: Rather than a toy example, maybe it's worth putting a practical program people might actually use? I wanted the ability to combine captured stdout and stderr for so long, and I'm just excited it's now finally possible :D

```rust
use std::process::Command;
use std::io::Read;

let (mut recv, send) = std::io::pipe()?;

let mut command = Command::new("path/to/bin")
    // Both stdout and stderr will write to the same pipe, combining the two.
    .stdout(send.try_clone()?)
    .stderr(send)
    .spawn()?;

let mut output = Vec::new();
recv.read_to_end(&mut output)?;

// It's important that we read from the pipe before the process exits, to avoid
// filling the OS buffers if the program emits too much output.
assert!(command.wait()?.success());
```
created_at: 2025-05-04T18:53:23Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,252 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
+
+If you have a previous version of Rust installed via `rustup`, you can get 1.87.0 with:
+
+```
+$ rustup update stable
+```
+
+If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.87.0](https://doc.rust-lang.org/stable/releases.html#version-1870-2025-04-03).
+
+If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
+
+## What's in 1.87.0 stable
+
+### Anonymous pipes
+
+1.87 adds access to anonymous pipes to the standard library. This includes
+integration with `std::process::Command`'s input/output methods.
+
+As a toy example, this program uses pipes to stream data into `cat` and read the output:
path: content/Rust-1.87.0.md
user: login: Mark-Simulacrum
body: Yeah, that seems like a good idea. Not sure what a good candidate program is...
created_at: 2025-05-04T19:02:37Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,252 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
+
+If you have a previous version of Rust installed via `rustup`, you can get 1.87.0 with:
+
+```
+$ rustup update stable
+```
+
+If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.87.0](https://doc.rust-lang.org/stable/releases.html#version-1870-2025-04-03).
+
+If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
+
+## What's in 1.87.0 stable
+
+### Anonymous pipes
+
+1.87 adds access to anonymous pipes to the standard library. This includes
+integration with `std::process::Command`'s input/output methods.
+
+As a toy example, this program uses pipes to stream data into `cat` and read the output:
+
+```rust
+use std::process::Command;
+use std::io::{pipe, Read, Write};
+
+let (ping_rx, mut ping_tx) = pipe()?;
+let (mut pong_rx, pong_tx) = pipe()?;
+
+// Spawn a process that echoes its input.
+let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
+
+ping_tx.write_all(b"hello")?;
+// Close to unblock echo_server's reader.
+drop(ping_tx);
+
+let mut buf = String::new();
+// Block until echo_server's writer is closed.
+pong_rx.read_to_string(&mut buf)?;
+assert_eq!(&buf, "hello");
+
+echo_server.wait()?;
+```
+
+### Safe architecture intrinsics
+
+Most `std::arch` intrinsics that are unsafe only due to requiring target
+features to be enabled are now callable in safe code that has those features
+enabled. For example, the following toy program which implements summing an array using
+manual intrinsics can now use safe code for the core loop.
+
+```rust
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+use std::arch::x86_64::*;
+
+fn sum(slice: &[u32]) -> u32 {
+    #[cfg(target_arch = "x86_64")]
+    {
+        if is_x86_feature_detected!("avx2") {
+            // SAFETY: We have detected the feature is enabled at runtime,
+            // so it's safe to call this function.
+            return unsafe { sum_avx2(slice) };
+        }
+    }
+
+    slice.iter().sum()
+}
+
+#[target_feature(enable = "avx2")]
+#[cfg(target_arch = "x86_64")]
+fn sum_avx2(slice: &[u32]) -> u32 {
+    // SAFETY: __m256i and u32 have the same validity.
+    let (prefix, middle, tail) = unsafe { slice.align_to::<__m256i>() };
+    
+    let mut sum = prefix.iter().sum::<u32>();
+    sum += tail.iter().sum::<u32>();
+    
+    // Core loop is now fully safe code in 1.87, because the intrinsics require
+    // matching target features (avx2) to the function definition.
+    let mut base = _mm256_setzero_si256();
+    for e in middle.iter() {
+        base = _mm256_add_epi32(base, *e);
+    }
+    
+    // SAFETY: __m256i and u32 have the same validity.
+    let base: [u32; 8] = unsafe { std::mem::transmute(base) };
+    sum += base.iter().sum::<u32>();
+    
+    sum
+}
+```
+
+### `asm!` jumps to Rust code  
+
+Inline assembly (`asm!`) can now jump to labeled blocks within Rust code. This
+enables more flexible low-level programming, such as implementing optimized
+control flow in OS kernels or interacting with hardware more efficiently. 
+
+- The `asm!` macro now supports a label operand, which acts as a jump target.  
+- The label must be a block expression with a return type of `()` or `!`.  
+- The block executes when jumped to, and execution continues after the `asm!` block.  
+- Using output and label operands in the same `asm!` invocation remains [unstable](https://github.com/rust-lang/rust/issues/119364).  
+
+```rust
+unsafe {
+    asm!(
+        "jmp {}",
+        label {
+            println!("Jumped from asm!");
+        }
+    );
+}
+```
+
+For more details, please consult the [reference](https://doc.rust-lang.org/nightly/reference/inline-assembly.html#r-asm.operand-type.supported-operands.label).
+
+### Precise capturing (`+ use<...>`) in `impl Trait` in trait definitions
+
+This release stabilizes specifying the specific captured generic types and
+lifetimes in trait definitions using `impl Trait` return types. This allows
+using this feature in trait definitions, expanding on the stabilization for
+non-trait functions in
+[1.82](https://blog.rust-lang.org/2024/10/17/Rust-1.82.0/#precise-capturing-use-syntax).
+
+Some example desugarings:
+
+```rust
+trait Foo {
+    fn method<'a>(&'a self) -> impl Sized;
+    
+    // ... desugars to something like:
+    type Implicit1<'a>: Sized;
+    fn method_desugared<'a>(&'a self) -> Self::Implicit1<'a>;
+    
+    // ... whereas with precise capturing ...
+    fn precise<'a>(&'a self) -> impl Sized + use<Self>;
+    
+    // ... desugars to something like:
+    type Implicit2: Sized;
+    fn precise_desugared<'a>(&'a self) -> Self::Implicit2;
+}
+```
+
+### Stabilized APIs
+
+- [`Vec::extract_if`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.extract_if)
+- [`vec::ExtractIf`](https://doc.rust-lang.org/nightly/std/vec/struct.ExtractIf.html)
+- [`LinkedList::extract_if`](https://doc.rust-lang.org/nightly/std/collections/struct.LinkedList.html#method.extract_if)
+- [`linked_list::ExtractIf`](https://doc.rust-lang.org/nightly/std/collections/linked_list/struct.ExtractIf.html)
+- [`<[T]>::split_off`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off)
+- [`<[T]>::split_off_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_mut)
+- [`<[T]>::split_off_first`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first)
+- [`<[T]>::split_off_first_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first_mut)
+- [`<[T]>::split_off_last`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last)
+- [`<[T]>::split_off_last_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last_mut)
+- [`String::extend_from_within`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.extend_from_within)
+- [`os_str::Display`](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.Display.html)
+- [`OsString::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.display)
+- [`OsStr::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsStr.html#method.display)
+- [`io::pipe`](https://doc.rust-lang.org/nightly/std/io/fn.pipe.html)
+- [`io::PipeReader`](https://doc.rust-lang.org/nightly/std/io/struct.PipeReader.html)
+- [`io::PipeWriter`](https://doc.rust-lang.org/nightly/std/io/struct.PipeWriter.html)
+- [`impl From<PipeReader> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeReader%3E-for-OwnedHandle)
+- [`impl From<PipeWriter> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeWriter%3E-for-OwnedHandle)
+- [`impl From<PipeReader> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html)
+- [`impl From<PipeWriter> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html#impl-From%3CPipeWriter%3E-for-Stdio)
+- [`impl From<PipeReader> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeReader%3E-for-OwnedFd)
+- [`impl From<PipeWriter> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeWriter%3E-for-OwnedFd)
+- [`Box<MaybeUninit<T>>::write`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.write)
+- [`impl TryFrom<Vec<u8>> for String`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#impl-TryFrom%3CVec%3Cu8%3E%3E-for-String)
+
+These APIs are now stable in const contexts:
+
+- [`<*const T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned)
+- [`<*const T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned)
+- [`<*mut T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned-1)
+- [`<*mut T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned-1)
+- [`NonNull::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.offset_from_unsigned)
+- [`NonNull::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.byte_offset_from_unsigned)
+- [`<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.cast_signed)
+- [`NonZero::<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_signed-5).
+- [`<iN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.cast_signed).
+- [`NonZero::<iN>::cast_unsigned`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_unsigned-5).
+- [`<uN>::is_multiple_of`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.is_multiple_of)
+- [`<uN>::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shl)
+- [`<uN>::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shr)
+- [`<iN>::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shl)
+- [`<iN>::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shr)
+- [`<str>::from_utf8`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8)
+- [`<str>::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_mut)
+- [`<str>::from_utf8_unchecked`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked)
+- [`<str>::from_utf8_unchecked_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked_mut)
+- [`<[T]>::copy_from_slice`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.copy_from_slice)
+- [`SocketAddr::set_ip`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_ip)
+- [`SocketAddr::set_port`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_port),
+- [`SocketAddrV4::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_ip)
+- [`SocketAddrV4::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_port),
+- [`SocketAddrV6::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_ip)
+- [`SocketAddrV6::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_port)
+- [`SocketAddrV6::set_flowinfo`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_flowinfo)
+- [`SocketAddrV6::set_scope_id`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_scope_id)
+- [`char::is_digit`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_digit)
+- [`char::is_whitespace`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_whitespace)
+- [`<iN>:midpoint`](https://doc.rust-lang.org/std/primitive.isize.html#method.midpoint)
+- [`<[[T; N]]>::as_flattened`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_flattened)
+- [`<[[T; N]]>::as_flattened_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_flattened_mut) 
+- [`<str>::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_mut)
+- [`core::str::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/str/fn.from_utf8_mut.html)
+- [`String::into_bytes`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.into_bytes)
+- [`String::as_str`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_str)
+- [`String::capacity`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.capacity)
+- [`String::as_bytes`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_bytes)
+- [`String::len`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.len)
+- [`String::is_empty`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.is_empty)
+- [`String::as_mut_str`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_mut_str)
+- [`String::as_mut_vec`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_mut_vec)
+- [`Vec::as_ptr`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_ptr-1)
path: content/Rust-1.87.0.md
user: login: alex-semenyuk
body: ```suggestion
- [`Vec::as_ptr`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_ptr)
```
created_at: 2025-05-04T19:05:31Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,252 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
+
+If you have a previous version of Rust installed via `rustup`, you can get 1.87.0 with:
+
+```
+$ rustup update stable
+```
+
+If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.87.0](https://doc.rust-lang.org/stable/releases.html#version-1870-2025-04-03).
+
+If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
+
+## What's in 1.87.0 stable
+
+### Anonymous pipes
+
+1.87 adds access to anonymous pipes to the standard library. This includes
+integration with `std::process::Command`'s input/output methods.
+
+As a toy example, this program uses pipes to stream data into `cat` and read the output:
path: content/Rust-1.87.0.md
user: login: emilyalbini
body: You mean instead of `path/to/bin`? I think it'd be ok to leave the placeholder here, the goal I have here is not to have something people can copy/paste in the playground, but rather show that it's now possible to merge stdout and stderr, and show how people can do that in their projects.
created_at: 2025-05-04T19:09:18Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,252 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
+
+If you have a previous version of Rust installed via `rustup`, you can get 1.87.0 with:
+
+```
+$ rustup update stable
+```
+
+If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.87.0](https://doc.rust-lang.org/stable/releases.html#version-1870-2025-04-03).
+
+If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
+
+## What's in 1.87.0 stable
+
+### Anonymous pipes
+
+1.87 adds access to anonymous pipes to the standard library. This includes
+integration with `std::process::Command`'s input/output methods.
+
+As a toy example, this program uses pipes to stream data into `cat` and read the output:
path: content/Rust-1.87.0.md
user: login: Mark-Simulacrum
body: Ack, that makes sense. Pushed an update.
created_at: 2025-05-04T19:38:22Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,251 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
path: content/Rust-1.87.0.md
user: login: joshtriplett
body: ```suggestion
title = "Announcing Rust 1.87.0 and ten years of Rust!"
```
created_at: 2025-05-04T22:17:14Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,251 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
path: content/Rust-1.87.0.md
user: login: joshtriplett
body: ```suggestion
The Rust team is happy to announce a new version of Rust, 1.87.0. This release occurs on the ten-year anniversary of Rust 1.0, live from the stage at [RustWeek](https://rustweek.org/celebration/). Thank you to the myriad contributors who have worked on Rust, past and present. Here's to many more decades of Rust!

Rust is a programming language empowering everyone to build reliable and efficient software.
```
created_at: 2025-05-04T22:19:35Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,251 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
+
+If you have a previous version of Rust installed via `rustup`, you can get 1.87.0 with:
+
+```
+$ rustup update stable
+```
+
+If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.87.0](https://doc.rust-lang.org/stable/releases.html#version-1870-2025-04-03).
+
+If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
+
+## What's in 1.87.0 stable
+
+### Anonymous pipes
+
+1.87 adds access to anonymous pipes to the standard library. This includes
+integration with `std::process::Command`'s input/output methods. For example,
+joining the stdout and stderr streams into one is now relatively
+straightforward, as shown below, while it used to require either extra threads
+or platform-specific functions.
+
+```rust
+use std::process::Command;
+use std::io::Read;
+
+let (mut recv, send) = std::io::pipe()?;
+
+let mut command = Command::new("path/to/bin")
+    // Both stdout and stderr will write to the same pipe, combining the two.
+    .stdout(send.try_clone()?)
+    .stderr(send)
+    .spawn()?;
+
+let mut output = Vec::new();
+recv.read_to_end(&mut output)?;
+
+// It's important that we read from the pipe before the process exits, to avoid
+// filling the OS buffers if the program emits too much output.
+assert!(command.wait()?.success());
+```
+
+### Safe architecture intrinsics
+
+Most `std::arch` intrinsics that are unsafe only due to requiring target
+features to be enabled are now callable in safe code that has those features
+enabled. For example, the following toy program which implements summing an array using
+manual intrinsics can now use safe code for the core loop.
+
+```rust
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+use std::arch::x86_64::*;
+
+fn sum(slice: &[u32]) -> u32 {
+    #[cfg(target_arch = "x86_64")]
+    {
+        if is_x86_feature_detected!("avx2") {
+            // SAFETY: We have detected the feature is enabled at runtime,
+            // so it's safe to call this function.
+            return unsafe { sum_avx2(slice) };
+        }
+    }
+
+    slice.iter().sum()
+}
+
+#[target_feature(enable = "avx2")]
+#[cfg(target_arch = "x86_64")]
+fn sum_avx2(slice: &[u32]) -> u32 {
+    // SAFETY: __m256i and u32 have the same validity.
+    let (prefix, middle, tail) = unsafe { slice.align_to::<__m256i>() };
+    
+    let mut sum = prefix.iter().sum::<u32>();
+    sum += tail.iter().sum::<u32>();
+    
+    // Core loop is now fully safe code in 1.87, because the intrinsics require
+    // matching target features (avx2) to the function definition.
+    let mut base = _mm256_setzero_si256();
+    for e in middle.iter() {
+        base = _mm256_add_epi32(base, *e);
+    }
+    
+    // SAFETY: __m256i and u32 have the same validity.
+    let base: [u32; 8] = unsafe { std::mem::transmute(base) };
+    sum += base.iter().sum::<u32>();
+    
+    sum
+}
+```
+
+### `asm!` jumps to Rust code  
+
+Inline assembly (`asm!`) can now jump to labeled blocks within Rust code. This
+enables more flexible low-level programming, such as implementing optimized
+control flow in OS kernels or interacting with hardware more efficiently. 
+
+- The `asm!` macro now supports a label operand, which acts as a jump target.  
+- The label must be a block expression with a return type of `()` or `!`.  
+- The block executes when jumped to, and execution continues after the `asm!` block.  
+- Using output and label operands in the same `asm!` invocation remains [unstable](https://github.com/rust-lang/rust/issues/119364).  
+
+```rust
+unsafe {
+    asm!(
+        "jmp {}",
+        label {
+            println!("Jumped from asm!");
+        }
+    );
+}
+```
+
+For more details, please consult the [reference](https://doc.rust-lang.org/nightly/reference/inline-assembly.html#r-asm.operand-type.supported-operands.label).
+
+### Precise capturing (`+ use<...>`) in `impl Trait` in trait definitions
+
+This release stabilizes specifying the specific captured generic types and
+lifetimes in trait definitions using `impl Trait` return types. This allows
+using this feature in trait definitions, expanding on the stabilization for
+non-trait functions in
+[1.82](https://blog.rust-lang.org/2024/10/17/Rust-1.82.0/#precise-capturing-use-syntax).
+
+Some example desugarings:
+
+```rust
+trait Foo {
+    fn method<'a>(&'a self) -> impl Sized;
+    
+    // ... desugars to something like:
+    type Implicit1<'a>: Sized;
+    fn method_desugared<'a>(&'a self) -> Self::Implicit1<'a>;
+    
+    // ... whereas with precise capturing ...
+    fn precise<'a>(&'a self) -> impl Sized + use<Self>;
+    
+    // ... desugars to something like:
+    type Implicit2: Sized;
+    fn precise_desugared<'a>(&'a self) -> Self::Implicit2;
+}
+```
+
+### Stabilized APIs
+
+- [`Vec::extract_if`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.extract_if)
+- [`vec::ExtractIf`](https://doc.rust-lang.org/nightly/std/vec/struct.ExtractIf.html)
+- [`LinkedList::extract_if`](https://doc.rust-lang.org/nightly/std/collections/struct.LinkedList.html#method.extract_if)
+- [`linked_list::ExtractIf`](https://doc.rust-lang.org/nightly/std/collections/linked_list/struct.ExtractIf.html)
+- [`<[T]>::split_off`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off)
+- [`<[T]>::split_off_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_mut)
+- [`<[T]>::split_off_first`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first)
+- [`<[T]>::split_off_first_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first_mut)
+- [`<[T]>::split_off_last`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last)
+- [`<[T]>::split_off_last_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last_mut)
+- [`String::extend_from_within`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.extend_from_within)
+- [`os_str::Display`](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.Display.html)
+- [`OsString::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.display)
+- [`OsStr::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsStr.html#method.display)
+- [`io::pipe`](https://doc.rust-lang.org/nightly/std/io/fn.pipe.html)
+- [`io::PipeReader`](https://doc.rust-lang.org/nightly/std/io/struct.PipeReader.html)
+- [`io::PipeWriter`](https://doc.rust-lang.org/nightly/std/io/struct.PipeWriter.html)
+- [`impl From<PipeReader> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeReader%3E-for-OwnedHandle)
+- [`impl From<PipeWriter> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeWriter%3E-for-OwnedHandle)
+- [`impl From<PipeReader> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html)
+- [`impl From<PipeWriter> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html#impl-From%3CPipeWriter%3E-for-Stdio)
+- [`impl From<PipeReader> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeReader%3E-for-OwnedFd)
+- [`impl From<PipeWriter> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeWriter%3E-for-OwnedFd)
+- [`Box<MaybeUninit<T>>::write`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.write)
+- [`impl TryFrom<Vec<u8>> for String`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#impl-TryFrom%3CVec%3Cu8%3E%3E-for-String)
+
+These APIs are now stable in const contexts:
+
+- [`<*const T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned)
+- [`<*const T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned)
+- [`<*mut T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned-1)
+- [`<*mut T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned-1)
+- [`NonNull::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.offset_from_unsigned)
+- [`NonNull::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.byte_offset_from_unsigned)
+- [`<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.cast_signed)
+- [`NonZero::<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_signed-5).
+- [`<iN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.cast_signed).
+- [`NonZero::<iN>::cast_unsigned`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_unsigned-5).
+- [`<uN>::is_multiple_of`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.is_multiple_of)
+- [`<uN>::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shl)
+- [`<uN>::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shr)
+- [`<iN>::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shl)
+- [`<iN>::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shr)
+- [`<str>::from_utf8`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8)
+- [`<str>::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_mut)
+- [`<str>::from_utf8_unchecked`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked)
+- [`<str>::from_utf8_unchecked_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked_mut)
+- [`<[T]>::copy_from_slice`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.copy_from_slice)
+- [`SocketAddr::set_ip`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_ip)
+- [`SocketAddr::set_port`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_port),
+- [`SocketAddrV4::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_ip)
+- [`SocketAddrV4::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_port),
+- [`SocketAddrV6::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_ip)
+- [`SocketAddrV6::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_port)
+- [`SocketAddrV6::set_flowinfo`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_flowinfo)
+- [`SocketAddrV6::set_scope_id`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_scope_id)
+- [`char::is_digit`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_digit)
+- [`char::is_whitespace`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_whitespace)
+- [`<iN>:midpoint`](https://doc.rust-lang.org/std/primitive.isize.html#method.midpoint)
+- [`<[[T; N]]>::as_flattened`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_flattened)
+- [`<[[T; N]]>::as_flattened_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_flattened_mut) 
+- [`<str>::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_mut)
+- [`core::str::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/str/fn.from_utf8_mut.html)
+- [`String::into_bytes`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.into_bytes)
+- [`String::as_str`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_str)
+- [`String::capacity`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.capacity)
+- [`String::as_bytes`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_bytes)
+- [`String::len`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.len)
+- [`String::is_empty`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.is_empty)
+- [`String::as_mut_str`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_mut_str)
+- [`String::as_mut_vec`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_mut_vec)
+- [`Vec::as_ptr`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_ptr)
+- [`Vec::as_slice`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_slice)
+- [`Vec::capacity`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.capacity)
+- [`Vec::len`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.len)
+- [`Vec::is_empty`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.is_empty)
+- [`Vec::as_mut_slice`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_mut_slice)
+- [`Vec::as_mut_ptr`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_mut_ptr)
+
+### `i586-pc-windows-msvc` target removal
+
+The tier-2 target `i586-pc-windows-msvc` has been removed. Its difference to the much more popular `i686-pc-windows-msvc` is that it does not require SSE2 instruction support, but Windows 10, the minimum required OS version of all `windows` targets (except the `win7` targets), requires SSE2 instructions itself.
path: content/Rust-1.87.0.md
user: login: jieyouxu
body: Nit:

```suggestion
The Tier 2 target `i586-pc-windows-msvc` has been removed. `i586-pc-windows-msvc`'s difference to the much more popular Tier 1 target `i686-pc-windows-msvc` is that `i586-pc-windows-msvc` does not require SSE2 instruction support. But Windows 10, the minimum required OS version of all `windows` targets (except the `win7` targets), requires SSE2 instructions itself.
```
created_at: 2025-05-05T08:43:49Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,251 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
path: content/Rust-1.87.0.md
user: login: Kobzol
body: Would be awesome to embed a photo of the celebration room filled with people directly into the blog post :)
created_at: 2025-05-05T09:27:39Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,251 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
path: content/Rust-1.87.0.md
user: login: m-ou-se
body: I think it'd also be good to make clear that the 1.87.0 release itself isn't a special release; just that the day is. There will probably be some press coverage, and I don't think they should report the specific features of 1.87.0 itself as the big 10 year milestone.

Happy to think of some text for this. Probably a separate paragraph at the top or something.
created_at: 2025-05-05T10:08:31Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,251 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
path: content/Rust-1.87.0.md
user: login: m-ou-se
body: > Would be awesome to embed a photo of the celebration room filled with people directly into the blog post :)

I was planning on doing that for the posts on social media. (Which I can just do from my phone.) Might be tricky to do that in the blog post, though, to do that quickly on stage.
created_at: 2025-05-05T10:09:48Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,251 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
+
+If you have a previous version of Rust installed via `rustup`, you can get 1.87.0 with:
+
+```
+$ rustup update stable
+```
+
+If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.87.0](https://doc.rust-lang.org/stable/releases.html#version-1870-2025-04-03).
+
+If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
+
+## What's in 1.87.0 stable
+
+### Anonymous pipes
+
+1.87 adds access to anonymous pipes to the standard library. This includes
+integration with `std::process::Command`'s input/output methods. For example,
+joining the stdout and stderr streams into one is now relatively
+straightforward, as shown below, while it used to require either extra threads
+or platform-specific functions.
+
+```rust
+use std::process::Command;
+use std::io::Read;
+
+let (mut recv, send) = std::io::pipe()?;
+
+let mut command = Command::new("path/to/bin")
+    // Both stdout and stderr will write to the same pipe, combining the two.
+    .stdout(send.try_clone()?)
+    .stderr(send)
+    .spawn()?;
+
+let mut output = Vec::new();
+recv.read_to_end(&mut output)?;
+
+// It's important that we read from the pipe before the process exits, to avoid
+// filling the OS buffers if the program emits too much output.
+assert!(command.wait()?.success());
+```
+
+### Safe architecture intrinsics
+
+Most `std::arch` intrinsics that are unsafe only due to requiring target
+features to be enabled are now callable in safe code that has those features
+enabled. For example, the following toy program which implements summing an array using
+manual intrinsics can now use safe code for the core loop.
+
+```rust
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+use std::arch::x86_64::*;
+
+fn sum(slice: &[u32]) -> u32 {
+    #[cfg(target_arch = "x86_64")]
+    {
+        if is_x86_feature_detected!("avx2") {
+            // SAFETY: We have detected the feature is enabled at runtime,
+            // so it's safe to call this function.
+            return unsafe { sum_avx2(slice) };
+        }
+    }
+
+    slice.iter().sum()
+}
+
+#[target_feature(enable = "avx2")]
+#[cfg(target_arch = "x86_64")]
+fn sum_avx2(slice: &[u32]) -> u32 {
+    // SAFETY: __m256i and u32 have the same validity.
+    let (prefix, middle, tail) = unsafe { slice.align_to::<__m256i>() };
+    
+    let mut sum = prefix.iter().sum::<u32>();
+    sum += tail.iter().sum::<u32>();
+    
+    // Core loop is now fully safe code in 1.87, because the intrinsics require
+    // matching target features (avx2) to the function definition.
+    let mut base = _mm256_setzero_si256();
+    for e in middle.iter() {
+        base = _mm256_add_epi32(base, *e);
+    }
+    
+    // SAFETY: __m256i and u32 have the same validity.
+    let base: [u32; 8] = unsafe { std::mem::transmute(base) };
+    sum += base.iter().sum::<u32>();
+    
+    sum
+}
+```
+
+### `asm!` jumps to Rust code  
+
+Inline assembly (`asm!`) can now jump to labeled blocks within Rust code. This
+enables more flexible low-level programming, such as implementing optimized
+control flow in OS kernels or interacting with hardware more efficiently. 
+
+- The `asm!` macro now supports a label operand, which acts as a jump target.  
+- The label must be a block expression with a return type of `()` or `!`.  
+- The block executes when jumped to, and execution continues after the `asm!` block.  
+- Using output and label operands in the same `asm!` invocation remains [unstable](https://github.com/rust-lang/rust/issues/119364).  
+
+```rust
+unsafe {
+    asm!(
+        "jmp {}",
+        label {
+            println!("Jumped from asm!");
+        }
+    );
+}
+```
+
+For more details, please consult the [reference](https://doc.rust-lang.org/nightly/reference/inline-assembly.html#r-asm.operand-type.supported-operands.label).
+
+### Precise capturing (`+ use<...>`) in `impl Trait` in trait definitions
+
+This release stabilizes specifying the specific captured generic types and
+lifetimes in trait definitions using `impl Trait` return types. This allows
+using this feature in trait definitions, expanding on the stabilization for
+non-trait functions in
+[1.82](https://blog.rust-lang.org/2024/10/17/Rust-1.82.0/#precise-capturing-use-syntax).
+
+Some example desugarings:
+
+```rust
+trait Foo {
+    fn method<'a>(&'a self) -> impl Sized;
+    
+    // ... desugars to something like:
+    type Implicit1<'a>: Sized;
+    fn method_desugared<'a>(&'a self) -> Self::Implicit1<'a>;
+    
+    // ... whereas with precise capturing ...
+    fn precise<'a>(&'a self) -> impl Sized + use<Self>;
+    
+    // ... desugars to something like:
+    type Implicit2: Sized;
+    fn precise_desugared<'a>(&'a self) -> Self::Implicit2;
+}
+```
+
+### Stabilized APIs
+
+- [`Vec::extract_if`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.extract_if)
+- [`vec::ExtractIf`](https://doc.rust-lang.org/nightly/std/vec/struct.ExtractIf.html)
+- [`LinkedList::extract_if`](https://doc.rust-lang.org/nightly/std/collections/struct.LinkedList.html#method.extract_if)
+- [`linked_list::ExtractIf`](https://doc.rust-lang.org/nightly/std/collections/linked_list/struct.ExtractIf.html)
+- [`<[T]>::split_off`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off)
+- [`<[T]>::split_off_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_mut)
+- [`<[T]>::split_off_first`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first)
+- [`<[T]>::split_off_first_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first_mut)
+- [`<[T]>::split_off_last`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last)
+- [`<[T]>::split_off_last_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last_mut)
+- [`String::extend_from_within`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.extend_from_within)
+- [`os_str::Display`](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.Display.html)
+- [`OsString::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.display)
+- [`OsStr::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsStr.html#method.display)
+- [`io::pipe`](https://doc.rust-lang.org/nightly/std/io/fn.pipe.html)
+- [`io::PipeReader`](https://doc.rust-lang.org/nightly/std/io/struct.PipeReader.html)
+- [`io::PipeWriter`](https://doc.rust-lang.org/nightly/std/io/struct.PipeWriter.html)
+- [`impl From<PipeReader> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeReader%3E-for-OwnedHandle)
+- [`impl From<PipeWriter> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeWriter%3E-for-OwnedHandle)
+- [`impl From<PipeReader> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html)
+- [`impl From<PipeWriter> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html#impl-From%3CPipeWriter%3E-for-Stdio)
+- [`impl From<PipeReader> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeReader%3E-for-OwnedFd)
+- [`impl From<PipeWriter> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeWriter%3E-for-OwnedFd)
+- [`Box<MaybeUninit<T>>::write`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.write)
+- [`impl TryFrom<Vec<u8>> for String`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#impl-TryFrom%3CVec%3Cu8%3E%3E-for-String)
+
+These APIs are now stable in const contexts:
+
+- [`<*const T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned)
+- [`<*const T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned)
+- [`<*mut T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned-1)
+- [`<*mut T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned-1)
+- [`NonNull::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.offset_from_unsigned)
+- [`NonNull::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.byte_offset_from_unsigned)
+- [`<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.cast_signed)
+- [`NonZero::<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_signed-5).
+- [`<iN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.cast_signed).
path: content/Rust-1.87.0.md
user: login: programmerjake
body: ```suggestion
- [`<iN>::cast_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.cast_unsigned).
```
created_at: 2025-05-05T21:17:08Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,251 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
+
+If you have a previous version of Rust installed via `rustup`, you can get 1.87.0 with:
+
+```
+$ rustup update stable
+```
+
+If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.87.0](https://doc.rust-lang.org/stable/releases.html#version-1870-2025-04-03).
+
+If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
+
+## What's in 1.87.0 stable
+
+### Anonymous pipes
+
+1.87 adds access to anonymous pipes to the standard library. This includes
+integration with `std::process::Command`'s input/output methods. For example,
+joining the stdout and stderr streams into one is now relatively
+straightforward, as shown below, while it used to require either extra threads
+or platform-specific functions.
+
+```rust
+use std::process::Command;
+use std::io::Read;
+
+let (mut recv, send) = std::io::pipe()?;
+
+let mut command = Command::new("path/to/bin")
+    // Both stdout and stderr will write to the same pipe, combining the two.
+    .stdout(send.try_clone()?)
+    .stderr(send)
+    .spawn()?;
+
+let mut output = Vec::new();
+recv.read_to_end(&mut output)?;
+
+// It's important that we read from the pipe before the process exits, to avoid
+// filling the OS buffers if the program emits too much output.
+assert!(command.wait()?.success());
+```
+
+### Safe architecture intrinsics
+
+Most `std::arch` intrinsics that are unsafe only due to requiring target
+features to be enabled are now callable in safe code that has those features
+enabled. For example, the following toy program which implements summing an array using
+manual intrinsics can now use safe code for the core loop.
+
+```rust
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+use std::arch::x86_64::*;
+
+fn sum(slice: &[u32]) -> u32 {
+    #[cfg(target_arch = "x86_64")]
+    {
+        if is_x86_feature_detected!("avx2") {
+            // SAFETY: We have detected the feature is enabled at runtime,
+            // so it's safe to call this function.
+            return unsafe { sum_avx2(slice) };
+        }
+    }
+
+    slice.iter().sum()
+}
+
+#[target_feature(enable = "avx2")]
+#[cfg(target_arch = "x86_64")]
+fn sum_avx2(slice: &[u32]) -> u32 {
+    // SAFETY: __m256i and u32 have the same validity.
+    let (prefix, middle, tail) = unsafe { slice.align_to::<__m256i>() };
+    
+    let mut sum = prefix.iter().sum::<u32>();
+    sum += tail.iter().sum::<u32>();
+    
+    // Core loop is now fully safe code in 1.87, because the intrinsics require
+    // matching target features (avx2) to the function definition.
+    let mut base = _mm256_setzero_si256();
+    for e in middle.iter() {
+        base = _mm256_add_epi32(base, *e);
+    }
+    
+    // SAFETY: __m256i and u32 have the same validity.
+    let base: [u32; 8] = unsafe { std::mem::transmute(base) };
+    sum += base.iter().sum::<u32>();
+    
+    sum
+}
+```
+
+### `asm!` jumps to Rust code  
+
+Inline assembly (`asm!`) can now jump to labeled blocks within Rust code. This
+enables more flexible low-level programming, such as implementing optimized
+control flow in OS kernels or interacting with hardware more efficiently. 
+
+- The `asm!` macro now supports a label operand, which acts as a jump target.  
+- The label must be a block expression with a return type of `()` or `!`.  
+- The block executes when jumped to, and execution continues after the `asm!` block.  
+- Using output and label operands in the same `asm!` invocation remains [unstable](https://github.com/rust-lang/rust/issues/119364).  
+
+```rust
+unsafe {
+    asm!(
+        "jmp {}",
+        label {
+            println!("Jumped from asm!");
+        }
+    );
+}
+```
+
+For more details, please consult the [reference](https://doc.rust-lang.org/nightly/reference/inline-assembly.html#r-asm.operand-type.supported-operands.label).
+
+### Precise capturing (`+ use<...>`) in `impl Trait` in trait definitions
+
+This release stabilizes specifying the specific captured generic types and
+lifetimes in trait definitions using `impl Trait` return types. This allows
+using this feature in trait definitions, expanding on the stabilization for
+non-trait functions in
+[1.82](https://blog.rust-lang.org/2024/10/17/Rust-1.82.0/#precise-capturing-use-syntax).
+
+Some example desugarings:
+
+```rust
+trait Foo {
+    fn method<'a>(&'a self) -> impl Sized;
+    
+    // ... desugars to something like:
+    type Implicit1<'a>: Sized;
+    fn method_desugared<'a>(&'a self) -> Self::Implicit1<'a>;
+    
+    // ... whereas with precise capturing ...
+    fn precise<'a>(&'a self) -> impl Sized + use<Self>;
+    
+    // ... desugars to something like:
+    type Implicit2: Sized;
+    fn precise_desugared<'a>(&'a self) -> Self::Implicit2;
+}
+```
+
+### Stabilized APIs
+
+- [`Vec::extract_if`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.extract_if)
+- [`vec::ExtractIf`](https://doc.rust-lang.org/nightly/std/vec/struct.ExtractIf.html)
+- [`LinkedList::extract_if`](https://doc.rust-lang.org/nightly/std/collections/struct.LinkedList.html#method.extract_if)
+- [`linked_list::ExtractIf`](https://doc.rust-lang.org/nightly/std/collections/linked_list/struct.ExtractIf.html)
+- [`<[T]>::split_off`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off)
+- [`<[T]>::split_off_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_mut)
+- [`<[T]>::split_off_first`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first)
+- [`<[T]>::split_off_first_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first_mut)
+- [`<[T]>::split_off_last`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last)
+- [`<[T]>::split_off_last_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last_mut)
+- [`String::extend_from_within`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.extend_from_within)
+- [`os_str::Display`](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.Display.html)
+- [`OsString::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.display)
+- [`OsStr::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsStr.html#method.display)
+- [`io::pipe`](https://doc.rust-lang.org/nightly/std/io/fn.pipe.html)
+- [`io::PipeReader`](https://doc.rust-lang.org/nightly/std/io/struct.PipeReader.html)
+- [`io::PipeWriter`](https://doc.rust-lang.org/nightly/std/io/struct.PipeWriter.html)
+- [`impl From<PipeReader> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeReader%3E-for-OwnedHandle)
+- [`impl From<PipeWriter> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeWriter%3E-for-OwnedHandle)
+- [`impl From<PipeReader> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html)
+- [`impl From<PipeWriter> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html#impl-From%3CPipeWriter%3E-for-Stdio)
+- [`impl From<PipeReader> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeReader%3E-for-OwnedFd)
+- [`impl From<PipeWriter> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeWriter%3E-for-OwnedFd)
+- [`Box<MaybeUninit<T>>::write`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.write)
+- [`impl TryFrom<Vec<u8>> for String`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#impl-TryFrom%3CVec%3Cu8%3E%3E-for-String)
+
+These APIs are now stable in const contexts:
+
+- [`<*const T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned)
+- [`<*const T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned)
+- [`<*mut T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned-1)
+- [`<*mut T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned-1)
+- [`NonNull::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.offset_from_unsigned)
+- [`NonNull::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.byte_offset_from_unsigned)
+- [`<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.cast_signed)
+- [`NonZero::<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_signed-5).
+- [`<iN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.cast_signed).
+- [`NonZero::<iN>::cast_unsigned`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_unsigned-5).
+- [`<uN>::is_multiple_of`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.is_multiple_of)
+- [`<uN>::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shl)
+- [`<uN>::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shr)
+- [`<iN>::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shl)
+- [`<iN>::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shr)
+- [`<str>::from_utf8`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8)
+- [`<str>::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_mut)
+- [`<str>::from_utf8_unchecked`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked)
+- [`<str>::from_utf8_unchecked_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked_mut)
+- [`<[T]>::copy_from_slice`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.copy_from_slice)
+- [`SocketAddr::set_ip`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_ip)
+- [`SocketAddr::set_port`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_port),
+- [`SocketAddrV4::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_ip)
+- [`SocketAddrV4::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_port),
+- [`SocketAddrV6::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_ip)
+- [`SocketAddrV6::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_port)
+- [`SocketAddrV6::set_flowinfo`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_flowinfo)
+- [`SocketAddrV6::set_scope_id`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_scope_id)
+- [`char::is_digit`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_digit)
+- [`char::is_whitespace`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_whitespace)
+- [`<iN>:midpoint`](https://doc.rust-lang.org/std/primitive.isize.html#method.midpoint)
path: content/Rust-1.87.0.md
user: login: programmerjake
body: ```suggestion
- [`<iN>::midpoint`](https://doc.rust-lang.org/std/primitive.isize.html#method.midpoint)
```
created_at: 2025-05-05T21:18:00Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,251 @@
++++
+path = "2025/05/15/Rust-1.87.0"
+title = "Announcing Rust 1.87.0"
+authors = ["The Rust Release Team"]
+aliases = [
+    "2025/05/15/Rust-1.87.0.html",
+    "releases/1.87.0",
+]
+
+[extra]
+release = true
++++
+
+The Rust team is happy to announce a new version of Rust, 1.87.0. Rust is a programming language empowering everyone to build reliable and efficient software.
+
+If you have a previous version of Rust installed via `rustup`, you can get 1.87.0 with:
+
+```
+$ rustup update stable
+```
+
+If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.87.0](https://doc.rust-lang.org/stable/releases.html#version-1870-2025-04-03).
+
+If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
+
+## What's in 1.87.0 stable
+
+### Anonymous pipes
+
+1.87 adds access to anonymous pipes to the standard library. This includes
+integration with `std::process::Command`'s input/output methods. For example,
+joining the stdout and stderr streams into one is now relatively
+straightforward, as shown below, while it used to require either extra threads
+or platform-specific functions.
+
+```rust
+use std::process::Command;
+use std::io::Read;
+
+let (mut recv, send) = std::io::pipe()?;
+
+let mut command = Command::new("path/to/bin")
+    // Both stdout and stderr will write to the same pipe, combining the two.
+    .stdout(send.try_clone()?)
+    .stderr(send)
+    .spawn()?;
+
+let mut output = Vec::new();
+recv.read_to_end(&mut output)?;
+
+// It's important that we read from the pipe before the process exits, to avoid
+// filling the OS buffers if the program emits too much output.
+assert!(command.wait()?.success());
+```
+
+### Safe architecture intrinsics
+
+Most `std::arch` intrinsics that are unsafe only due to requiring target
+features to be enabled are now callable in safe code that has those features
+enabled. For example, the following toy program which implements summing an array using
+manual intrinsics can now use safe code for the core loop.
+
+```rust
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+use std::arch::x86_64::*;
+
+fn sum(slice: &[u32]) -> u32 {
+    #[cfg(target_arch = "x86_64")]
+    {
+        if is_x86_feature_detected!("avx2") {
+            // SAFETY: We have detected the feature is enabled at runtime,
+            // so it's safe to call this function.
+            return unsafe { sum_avx2(slice) };
+        }
+    }
+
+    slice.iter().sum()
+}
+
+#[target_feature(enable = "avx2")]
+#[cfg(target_arch = "x86_64")]
+fn sum_avx2(slice: &[u32]) -> u32 {
+    // SAFETY: __m256i and u32 have the same validity.
+    let (prefix, middle, tail) = unsafe { slice.align_to::<__m256i>() };
+    
+    let mut sum = prefix.iter().sum::<u32>();
+    sum += tail.iter().sum::<u32>();
+    
+    // Core loop is now fully safe code in 1.87, because the intrinsics require
+    // matching target features (avx2) to the function definition.
+    let mut base = _mm256_setzero_si256();
+    for e in middle.iter() {
+        base = _mm256_add_epi32(base, *e);
+    }
+    
+    // SAFETY: __m256i and u32 have the same validity.
+    let base: [u32; 8] = unsafe { std::mem::transmute(base) };
+    sum += base.iter().sum::<u32>();
+    
+    sum
+}
+```
+
+### `asm!` jumps to Rust code  
+
+Inline assembly (`asm!`) can now jump to labeled blocks within Rust code. This
+enables more flexible low-level programming, such as implementing optimized
+control flow in OS kernels or interacting with hardware more efficiently. 
+
+- The `asm!` macro now supports a label operand, which acts as a jump target.  
+- The label must be a block expression with a return type of `()` or `!`.  
+- The block executes when jumped to, and execution continues after the `asm!` block.  
+- Using output and label operands in the same `asm!` invocation remains [unstable](https://github.com/rust-lang/rust/issues/119364).  
+
+```rust
+unsafe {
+    asm!(
+        "jmp {}",
+        label {
+            println!("Jumped from asm!");
+        }
+    );
+}
+```
+
+For more details, please consult the [reference](https://doc.rust-lang.org/nightly/reference/inline-assembly.html#r-asm.operand-type.supported-operands.label).
+
+### Precise capturing (`+ use<...>`) in `impl Trait` in trait definitions
+
+This release stabilizes specifying the specific captured generic types and
+lifetimes in trait definitions using `impl Trait` return types. This allows
+using this feature in trait definitions, expanding on the stabilization for
+non-trait functions in
+[1.82](https://blog.rust-lang.org/2024/10/17/Rust-1.82.0/#precise-capturing-use-syntax).
+
+Some example desugarings:
+
+```rust
+trait Foo {
+    fn method<'a>(&'a self) -> impl Sized;
+    
+    // ... desugars to something like:
+    type Implicit1<'a>: Sized;
+    fn method_desugared<'a>(&'a self) -> Self::Implicit1<'a>;
+    
+    // ... whereas with precise capturing ...
+    fn precise<'a>(&'a self) -> impl Sized + use<Self>;
+    
+    // ... desugars to something like:
+    type Implicit2: Sized;
+    fn precise_desugared<'a>(&'a self) -> Self::Implicit2;
+}
+```
+
+### Stabilized APIs
+
+- [`Vec::extract_if`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.extract_if)
+- [`vec::ExtractIf`](https://doc.rust-lang.org/nightly/std/vec/struct.ExtractIf.html)
+- [`LinkedList::extract_if`](https://doc.rust-lang.org/nightly/std/collections/struct.LinkedList.html#method.extract_if)
+- [`linked_list::ExtractIf`](https://doc.rust-lang.org/nightly/std/collections/linked_list/struct.ExtractIf.html)
+- [`<[T]>::split_off`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off)
+- [`<[T]>::split_off_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_mut)
+- [`<[T]>::split_off_first`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first)
+- [`<[T]>::split_off_first_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first_mut)
+- [`<[T]>::split_off_last`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last)
+- [`<[T]>::split_off_last_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last_mut)
+- [`String::extend_from_within`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.extend_from_within)
+- [`os_str::Display`](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.Display.html)
+- [`OsString::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.display)
+- [`OsStr::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsStr.html#method.display)
+- [`io::pipe`](https://doc.rust-lang.org/nightly/std/io/fn.pipe.html)
+- [`io::PipeReader`](https://doc.rust-lang.org/nightly/std/io/struct.PipeReader.html)
+- [`io::PipeWriter`](https://doc.rust-lang.org/nightly/std/io/struct.PipeWriter.html)
+- [`impl From<PipeReader> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeReader%3E-for-OwnedHandle)
+- [`impl From<PipeWriter> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeWriter%3E-for-OwnedHandle)
+- [`impl From<PipeReader> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html)
+- [`impl From<PipeWriter> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html#impl-From%3CPipeWriter%3E-for-Stdio)
+- [`impl From<PipeReader> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeReader%3E-for-OwnedFd)
+- [`impl From<PipeWriter> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeWriter%3E-for-OwnedFd)
+- [`Box<MaybeUninit<T>>::write`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.write)
+- [`impl TryFrom<Vec<u8>> for String`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#impl-TryFrom%3CVec%3Cu8%3E%3E-for-String)
+
+These APIs are now stable in const contexts:
+
+- [`<*const T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned)
+- [`<*const T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned)
+- [`<*mut T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned-1)
+- [`<*mut T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned-1)
+- [`NonNull::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.offset_from_unsigned)
+- [`NonNull::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.byte_offset_from_unsigned)
+- [`<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.cast_signed)
+- [`NonZero::<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_signed-5).
+- [`<iN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.cast_signed).
+- [`NonZero::<iN>::cast_unsigned`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_unsigned-5).
+- [`<uN>::is_multiple_of`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.is_multiple_of)
+- [`<uN>::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shl)
+- [`<uN>::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shr)
+- [`<iN>::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shl)
+- [`<iN>::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shr)
+- [`<str>::from_utf8`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8)
+- [`<str>::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_mut)
+- [`<str>::from_utf8_unchecked`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked)
+- [`<str>::from_utf8_unchecked_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked_mut)
+- [`<[T]>::copy_from_slice`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.copy_from_slice)
+- [`SocketAddr::set_ip`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_ip)
+- [`SocketAddr::set_port`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_port),
+- [`SocketAddrV4::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_ip)
+- [`SocketAddrV4::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_port),
+- [`SocketAddrV6::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_ip)
+- [`SocketAddrV6::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_port)
+- [`SocketAddrV6::set_flowinfo`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_flowinfo)
+- [`SocketAddrV6::set_scope_id`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_scope_id)
+- [`char::is_digit`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_digit)
+- [`char::is_whitespace`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_whitespace)
+- [`<iN>:midpoint`](https://doc.rust-lang.org/std/primitive.isize.html#method.midpoint)
path: content/Rust-1.87.0.md
user: login: jieyouxu
body: Note: I already fixed this in the actual tracking issue I think, but it needs resync'd
created_at: 2025-05-08T13:52:46Z
author_association: MEMBER

PR comments:
user: login: Mark-Simulacrum
created_at: 2025-05-04T18:16:42Z
body: @rustbot ping relnotes-interest-group
author_association: MEMBER
user: login: rustbot
created_at: 2025-05-04T18:16:44Z
body: Hi relnotes-interest-group, this PR adds a release blog post. Could you review
the blog post if you have time? Thanks <3


cc @alex-semenyuk @jieyouxu @joshtriplett @Kobzol @lcnr @traviscross
author_association: COLLABORATOR
user: login: m-ou-se
created_at: 2025-05-04T18:32:03Z
body: > I didn't mention anything about 10 years since 1.0 here -- maybe a separate post is best?

This release blog post will be published live from the stage at the celebration at RustWeek (by @pietroalbini), so I think it'd be good if we put some mention of the 10 year anniversary in this blog post.

I'll put it on my to do list for this week to come up with some short text for that.
author_association: MEMBER
user: login: BoxyUwU
created_at: 2025-05-08T13:39:48Z
body: There have been some changes to the stabilized APIs since when this PR was authored. They should be re-copied from #140802 before merging
author_association: MEMBER
user: login: emilyalbini
created_at: 2025-05-09T17:04:13Z
body: The list of stabilized APIs changed again in https://github.com/rust-lang/rust/pull/140864
author_association: MEMBER
user: login: m-ou-se
created_at: 2025-05-15T13:05:52Z
body: Added text for the 10 year anniversary, and a placeholder for the photo.
author_association: MEMBER