about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-03-07 10:40:12 +0000
committerbors <bors@rust-lang.org>2025-03-07 10:40:12 +0000
commit59a9b9e9d776cb5d6bc02e99c4dce4f94f622232 (patch)
tree214ffab869bda44aad4ffe17f5fa0d1965fc2109
parent91a0e1604f343730022bc903cbf201d8b0a86a71 (diff)
parentc33e9d6844aa4338e8906e240c2e994244f164b6 (diff)
downloadrust-59a9b9e9d776cb5d6bc02e99c4dce4f94f622232.tar.gz
rust-59a9b9e9d776cb5d6bc02e99c4dce4f94f622232.zip
Auto merge of #138151 - matthiaskrgr:rollup-j0p6ed1, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #136667 (Revert vita's c_char back to i8)
 - #137107 (Override default `Write` methods for cursor-like types)
 - #137777 (Specialize `OsString::push` and `OsString as From` for UTF-8)
 - #137832 (Fix crash in BufReader::peek())
 - #137904 (Improve the generic MIR in the default `PartialOrd::le` and friends)
 - #138115 (Suggest typo fix for static lifetime)
 - #138125 (Simplify `printf` and shell format suggestions)
 - #138129 (Stabilize const_char_classify, const_sockaddr_setters)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign.rs16
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs48
-rw-r--r--library/core/src/char/methods.rs4
-rw-r--r--library/core/src/cmp.rs22
-rw-r--r--library/core/src/ffi/primitives.rs8
-rw-r--r--library/core/src/net/socket_addr.rs16
-rw-r--r--library/std/src/ffi/os_str.rs50
-rw-r--r--library/std/src/io/buffered/bufreader.rs6
-rw-r--r--library/std/src/io/buffered/bufreader/buffer.rs4
-rw-r--r--library/std/src/io/cursor.rs100
-rw-r--r--library/std/src/io/impls.rs60
-rw-r--r--library/std/src/sys/os_str/bytes.rs5
-rw-r--r--library/std/src/sys/os_str/wtf8.rs5
-rw-r--r--tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir89
-rw-r--r--tests/mir-opt/pre-codegen/derived_ord.rs26
-rw-r--r--tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir4
-rw-r--r--tests/ui/lifetimes/static-typos.rs7
-rw-r--r--tests/ui/lifetimes/static-typos.stderr26
19 files changed, 431 insertions, 69 deletions
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 6dbd8a7ac01..12654001a1e 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -711,11 +711,9 @@ fn report_missing_placeholders(
                     };
 
                     let pos = sub.position();
-                    let sub = String::from(sub.as_str());
-                    if explained.contains(&sub) {
+                    if !explained.insert(sub.to_string()) {
                         continue;
                     }
-                    explained.insert(sub);
 
                     if !found_foreign {
                         found_foreign = true;
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index 866ec72f116..13d5b42942a 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -12,14 +12,16 @@ pub(crate) mod printf {
         Escape((usize, usize)),
     }
 
-    impl<'a> Substitution<'a> {
-        pub(crate) fn as_str(&self) -> &str {
+    impl ToString for Substitution<'_> {
+        fn to_string(&self) -> String {
             match self {
-                Substitution::Format(fmt) => fmt.span,
-                Substitution::Escape(_) => "%%",
+                Substitution::Format(fmt) => fmt.span.into(),
+                Substitution::Escape(_) => "%%".into(),
             }
         }
+    }
 
+    impl Substitution<'_> {
         pub(crate) fn position(&self) -> InnerSpan {
             match self {
                 Substitution::Format(fmt) => fmt.position,
@@ -627,15 +629,17 @@ pub(crate) mod shell {
         Escape((usize, usize)),
     }
 
-    impl Substitution<'_> {
-        pub(crate) fn as_str(&self) -> String {
+    impl ToString for Substitution<'_> {
+        fn to_string(&self) -> String {
             match self {
                 Substitution::Ordinal(n, _) => format!("${n}"),
                 Substitution::Name(n, _) => format!("${n}"),
                 Substitution::Escape(_) => "$$".into(),
             }
         }
+    }
 
+    impl Substitution<'_> {
         pub(crate) fn position(&self) -> InnerSpan {
             let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
             InnerSpan::new(pos.0, pos.1)
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 67024f988a4..84858cfc1b1 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -24,7 +24,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
 use rustc_hir::{MissingLifetimeKind, PrimTy};
 use rustc_middle::ty;
 use rustc_session::{Session, lint};
-use rustc_span::edit_distance::find_best_match_for_name;
+use rustc_span::edit_distance::{edit_distance, find_best_match_for_name};
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
@@ -2919,23 +2919,35 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             )
             .with_span_label(lifetime_ref.ident.span, "undeclared lifetime")
         };
-        self.suggest_introducing_lifetime(
-            &mut err,
-            Some(lifetime_ref.ident.name.as_str()),
-            |err, _, span, message, suggestion, span_suggs| {
-                err.multipart_suggestion_with_style(
-                    message,
-                    std::iter::once((span, suggestion)).chain(span_suggs.clone()).collect(),
-                    Applicability::MaybeIncorrect,
-                    if span_suggs.is_empty() {
-                        SuggestionStyle::ShowCode
-                    } else {
-                        SuggestionStyle::ShowAlways
-                    },
-                );
-                true
-            },
-        );
+
+        // Check if this is a typo of `'static`.
+        if edit_distance(lifetime_ref.ident.name.as_str(), "'static", 2).is_some() {
+            err.span_suggestion_verbose(
+                lifetime_ref.ident.span,
+                "you may have misspelled the `'static` lifetime",
+                "'static",
+                Applicability::MachineApplicable,
+            );
+        } else {
+            self.suggest_introducing_lifetime(
+                &mut err,
+                Some(lifetime_ref.ident.name.as_str()),
+                |err, _, span, message, suggestion, span_suggs| {
+                    err.multipart_suggestion_with_style(
+                        message,
+                        std::iter::once((span, suggestion)).chain(span_suggs.clone()).collect(),
+                        Applicability::MaybeIncorrect,
+                        if span_suggs.is_empty() {
+                            SuggestionStyle::ShowCode
+                        } else {
+                            SuggestionStyle::ShowAlways
+                        },
+                    );
+                    true
+                },
+            );
+        }
+
         err.emit();
     }
 
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 85cc315626d..bb71af339b8 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -337,7 +337,7 @@ impl char {
     /// '1'.is_digit(1);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_char_classify", issue = "132241")]
+    #[rustc_const_stable(feature = "const_char_classify", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn is_digit(self, radix: u32) -> bool {
         self.to_digit(radix).is_some()
@@ -886,7 +886,7 @@ impl char {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_char_classify", issue = "132241")]
+    #[rustc_const_stable(feature = "const_char_classify", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn is_whitespace(self) -> bool {
         match self {
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index c8ced78c4d7..b29251b4b43 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -397,6 +397,12 @@ pub enum Ordering {
 }
 
 impl Ordering {
+    #[inline]
+    const fn as_raw(self) -> i8 {
+        // FIXME(const-hack): just use `PartialOrd` against `Equal` once that's const
+        crate::intrinsics::discriminant_value(&self)
+    }
+
     /// Returns `true` if the ordering is the `Equal` variant.
     ///
     /// # Examples
@@ -413,7 +419,11 @@ impl Ordering {
     #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
     #[stable(feature = "ordering_helpers", since = "1.53.0")]
     pub const fn is_eq(self) -> bool {
-        matches!(self, Equal)
+        // All the `is_*` methods are implemented as comparisons against zero
+        // to follow how clang's libcxx implements their equivalents in
+        // <https://github.com/llvm/llvm-project/blob/60486292b79885b7800b082754153202bef5b1f0/libcxx/include/__compare/is_eq.h#L23-L28>
+
+        self.as_raw() == 0
     }
 
     /// Returns `true` if the ordering is not the `Equal` variant.
@@ -432,7 +442,7 @@ impl Ordering {
     #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
     #[stable(feature = "ordering_helpers", since = "1.53.0")]
     pub const fn is_ne(self) -> bool {
-        !matches!(self, Equal)
+        self.as_raw() != 0
     }
 
     /// Returns `true` if the ordering is the `Less` variant.
@@ -451,7 +461,7 @@ impl Ordering {
     #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
     #[stable(feature = "ordering_helpers", since = "1.53.0")]
     pub const fn is_lt(self) -> bool {
-        matches!(self, Less)
+        self.as_raw() < 0
     }
 
     /// Returns `true` if the ordering is the `Greater` variant.
@@ -470,7 +480,7 @@ impl Ordering {
     #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
     #[stable(feature = "ordering_helpers", since = "1.53.0")]
     pub const fn is_gt(self) -> bool {
-        matches!(self, Greater)
+        self.as_raw() > 0
     }
 
     /// Returns `true` if the ordering is either the `Less` or `Equal` variant.
@@ -489,7 +499,7 @@ impl Ordering {
     #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
     #[stable(feature = "ordering_helpers", since = "1.53.0")]
     pub const fn is_le(self) -> bool {
-        !matches!(self, Greater)
+        self.as_raw() <= 0
     }
 
     /// Returns `true` if the ordering is either the `Greater` or `Equal` variant.
@@ -508,7 +518,7 @@ impl Ordering {
     #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
     #[stable(feature = "ordering_helpers", since = "1.53.0")]
     pub const fn is_ge(self) -> bool {
-        !matches!(self, Less)
+        self.as_raw() >= 0
     }
 
     /// Reverses the `Ordering`.
diff --git a/library/core/src/ffi/primitives.rs b/library/core/src/ffi/primitives.rs
index ece3c7538da..6495e61b346 100644
--- a/library/core/src/ffi/primitives.rs
+++ b/library/core/src/ffi/primitives.rs
@@ -39,7 +39,6 @@ mod c_char_definition {
         // These are the targets on which c_char is unsigned. Usually the
         // signedness is the same for all target_os values on a given architecture
         // but there are some exceptions (see isSignedCharDefault() in clang).
-        //
         // aarch64:
         //   Section 10 "Arm C and C++ language mappings" in Procedure Call Standard for the ArmĀ®
         //   64-bit Architecture (AArch64) says C/C++ char is unsigned byte.
@@ -97,14 +96,19 @@ mod c_char_definition {
         //   are promoted to int as if from type signed char by default, unless the /J compilation
         //   option is used."
         //   https://learn.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp?view=msvc-170#character-types
+        // Vita:
+        //   Chars are signed by default on the Vita, and VITASDK follows that convention.
+        //   https://github.com/vitasdk/buildscripts/blob/09c533b771591ecde88864b6acad28ffb688dbd4/patches/gcc/0001-gcc-10.patch#L33-L34
+        //
         // L4Re:
-        //   The kernel builds with -funsigned-char on all targets (but useserspace follows the
+        //   The kernel builds with -funsigned-char on all targets (but userspace follows the
         //   architecture defaults). As we only have a target for userspace apps so there are no
         //   special cases for L4Re below.
         //   https://github.com/rust-lang/rust/pull/132975#issuecomment-2484645240
         if #[cfg(all(
             not(windows),
             not(target_vendor = "apple"),
+            not(target_os = "vita"),
             any(
                 target_arch = "aarch64",
                 target_arch = "arm",
diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs
index 9204797e6e1..57f47e66e81 100644
--- a/library/core/src/net/socket_addr.rs
+++ b/library/core/src/net/socket_addr.rs
@@ -200,7 +200,7 @@ impl SocketAddr {
     /// ```
     #[inline]
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")]
+    #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")]
     pub const fn set_ip(&mut self, new_ip: IpAddr) {
         // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away.
         match (self, new_ip) {
@@ -244,7 +244,7 @@ impl SocketAddr {
     /// ```
     #[inline]
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")]
+    #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")]
     pub const fn set_port(&mut self, new_port: u16) {
         match *self {
             SocketAddr::V4(ref mut a) => a.set_port(new_port),
@@ -350,7 +350,7 @@ impl SocketAddrV4 {
     /// ```
     #[inline]
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")]
+    #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")]
     pub const fn set_ip(&mut self, new_ip: Ipv4Addr) {
         self.ip = new_ip;
     }
@@ -386,7 +386,7 @@ impl SocketAddrV4 {
     /// ```
     #[inline]
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")]
+    #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")]
     pub const fn set_port(&mut self, new_port: u16) {
         self.port = new_port;
     }
@@ -448,7 +448,7 @@ impl SocketAddrV6 {
     /// ```
     #[inline]
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")]
+    #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")]
     pub const fn set_ip(&mut self, new_ip: Ipv6Addr) {
         self.ip = new_ip;
     }
@@ -484,7 +484,7 @@ impl SocketAddrV6 {
     /// ```
     #[inline]
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")]
+    #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")]
     pub const fn set_port(&mut self, new_port: u16) {
         self.port = new_port;
     }
@@ -532,7 +532,7 @@ impl SocketAddrV6 {
     /// ```
     #[inline]
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")]
+    #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")]
     pub const fn set_flowinfo(&mut self, new_flowinfo: u32) {
         self.flowinfo = new_flowinfo;
     }
@@ -575,7 +575,7 @@ impl SocketAddrV6 {
     /// ```
     #[inline]
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")]
+    #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")]
     pub const fn set_scope_id(&mut self, new_scope_id: u32) {
         self.scope_id = new_scope_id;
     }
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index f4a02802336..aa25ff5293c 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -257,7 +257,30 @@ impl OsString {
     #[inline]
     #[rustc_confusables("append", "put")]
     pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
-        self.inner.push_slice(&s.as_ref().inner)
+        trait SpecPushTo {
+            fn spec_push_to(&self, buf: &mut OsString);
+        }
+
+        impl<T: AsRef<OsStr>> SpecPushTo for T {
+            #[inline]
+            default fn spec_push_to(&self, buf: &mut OsString) {
+                buf.inner.push_slice(&self.as_ref().inner);
+            }
+        }
+
+        // Use a more efficient implementation when the string is UTF-8.
+        macro spec_str($T:ty) {
+            impl SpecPushTo for $T {
+                #[inline]
+                fn spec_push_to(&self, buf: &mut OsString) {
+                    buf.inner.push_str(self);
+                }
+            }
+        }
+        spec_str!(str);
+        spec_str!(String);
+
+        s.spec_push_to(self)
     }
 
     /// Creates a new `OsString` with at least the given capacity.
@@ -587,7 +610,30 @@ impl<T: ?Sized + AsRef<OsStr>> From<&T> for OsString {
     /// Copies any value implementing <code>[AsRef]&lt;[OsStr]&gt;</code>
     /// into a newly allocated [`OsString`].
     fn from(s: &T) -> OsString {
-        s.as_ref().to_os_string()
+        trait SpecToOsString {
+            fn spec_to_os_string(&self) -> OsString;
+        }
+
+        impl<T: AsRef<OsStr>> SpecToOsString for T {
+            #[inline]
+            default fn spec_to_os_string(&self) -> OsString {
+                self.as_ref().to_os_string()
+            }
+        }
+
+        // Preserve the known-UTF-8 property for strings.
+        macro spec_str($T:ty) {
+            impl SpecToOsString for $T {
+                #[inline]
+                fn spec_to_os_string(&self) -> OsString {
+                    OsString::from(String::from(self))
+                }
+            }
+        }
+        spec_str!(str);
+        spec_str!(String);
+
+        s.spec_to_os_string()
     }
 }
 
diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs
index 8b46738ab8a..697fb5974a3 100644
--- a/library/std/src/io/buffered/bufreader.rs
+++ b/library/std/src/io/buffered/bufreader.rs
@@ -118,16 +118,16 @@ impl<R: Read + ?Sized> BufReader<R> {
     /// #![feature(bufreader_peek)]
     /// use std::io::{Read, BufReader};
     ///
-    /// let mut bytes = &b"oh, hello"[..];
+    /// let mut bytes = &b"oh, hello there"[..];
     /// let mut rdr = BufReader::with_capacity(6, &mut bytes);
     /// assert_eq!(rdr.peek(2).unwrap(), b"oh");
     /// let mut buf = [0; 4];
     /// rdr.read(&mut buf[..]).unwrap();
     /// assert_eq!(&buf, b"oh, ");
-    /// assert_eq!(rdr.peek(2).unwrap(), b"he");
+    /// assert_eq!(rdr.peek(5).unwrap(), b"hello");
     /// let mut s = String::new();
     /// rdr.read_to_string(&mut s).unwrap();
-    /// assert_eq!(&s, "hello");
+    /// assert_eq!(&s, "hello there");
     /// assert_eq!(rdr.peek(1).unwrap().len(), 0);
     /// ```
     #[unstable(feature = "bufreader_peek", issue = "128405")]
diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs
index 5251cc302cb..9fd2472ebdf 100644
--- a/library/std/src/io/buffered/bufreader/buffer.rs
+++ b/library/std/src/io/buffered/bufreader/buffer.rs
@@ -109,8 +109,8 @@ impl Buffer {
 
     /// Read more bytes into the buffer without discarding any of its contents
     pub fn read_more(&mut self, mut reader: impl Read) -> io::Result<usize> {
-        let mut buf = BorrowedBuf::from(&mut self.buf[self.pos..]);
-        let old_init = self.initialized - self.pos;
+        let mut buf = BorrowedBuf::from(&mut self.buf[self.filled..]);
+        let old_init = self.initialized - self.filled;
         unsafe {
             buf.set_init(old_init);
         }
diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs
index 08832bbc1e3..d7131e2fe92 100644
--- a/library/std/src/io/cursor.rs
+++ b/library/std/src/io/cursor.rs
@@ -439,6 +439,27 @@ fn slice_write_vectored(
     Ok(nwritten)
 }
 
+#[inline]
+fn slice_write_all(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<()> {
+    let n = slice_write(pos_mut, slice, buf)?;
+    if n < buf.len() { Err(io::Error::WRITE_ALL_EOF) } else { Ok(()) }
+}
+
+#[inline]
+fn slice_write_all_vectored(
+    pos_mut: &mut u64,
+    slice: &mut [u8],
+    bufs: &[IoSlice<'_>],
+) -> io::Result<()> {
+    for buf in bufs {
+        let n = slice_write(pos_mut, slice, buf)?;
+        if n < buf.len() {
+            return Err(io::Error::WRITE_ALL_EOF);
+        }
+    }
+    Ok(())
+}
+
 /// Reserves the required space, and pads the vec with 0s if necessary.
 fn reserve_and_pad<A: Allocator>(
     pos_mut: &mut u64,
@@ -481,9 +502,12 @@ fn reserve_and_pad<A: Allocator>(
     Ok(pos)
 }
 
-/// Writes the slice to the vec without allocating
-/// # Safety: vec must have buf.len() spare capacity
-unsafe fn vec_write_unchecked<A>(pos: usize, vec: &mut Vec<u8, A>, buf: &[u8]) -> usize
+/// Writes the slice to the vec without allocating.
+///
+/// # Safety
+///
+/// `vec` must have `buf.len()` spare capacity.
+unsafe fn vec_write_all_unchecked<A>(pos: usize, vec: &mut Vec<u8, A>, buf: &[u8]) -> usize
 where
     A: Allocator,
 {
@@ -492,7 +516,7 @@ where
     pos + buf.len()
 }
 
-/// Resizing write implementation for [`Cursor`]
+/// Resizing `write_all` implementation for [`Cursor`].
 ///
 /// Cursor is allowed to have a pre-allocated and initialised
 /// vector body, but with a position of 0. This means the [`Write`]
@@ -501,7 +525,7 @@ where
 /// This also allows for the vec body to be empty, but with a position of N.
 /// This means that [`Write`] will pad the vec with 0 initially,
 /// before writing anything from that point
-fn vec_write<A>(pos_mut: &mut u64, vec: &mut Vec<u8, A>, buf: &[u8]) -> io::Result<usize>
+fn vec_write_all<A>(pos_mut: &mut u64, vec: &mut Vec<u8, A>, buf: &[u8]) -> io::Result<usize>
 where
     A: Allocator,
 {
@@ -512,7 +536,7 @@ where
     // Safety: we have ensured that the capacity is available
     // and that all bytes get written up to pos
     unsafe {
-        pos = vec_write_unchecked(pos, vec, buf);
+        pos = vec_write_all_unchecked(pos, vec, buf);
         if pos > vec.len() {
             vec.set_len(pos);
         }
@@ -523,7 +547,7 @@ where
     Ok(buf_len)
 }
 
-/// Resizing write_vectored implementation for [`Cursor`]
+/// Resizing `write_all_vectored` implementation for [`Cursor`].
 ///
 /// Cursor is allowed to have a pre-allocated and initialised
 /// vector body, but with a position of 0. This means the [`Write`]
@@ -532,7 +556,7 @@ where
 /// This also allows for the vec body to be empty, but with a position of N.
 /// This means that [`Write`] will pad the vec with 0 initially,
 /// before writing anything from that point
-fn vec_write_vectored<A>(
+fn vec_write_all_vectored<A>(
     pos_mut: &mut u64,
     vec: &mut Vec<u8, A>,
     bufs: &[IoSlice<'_>],
@@ -550,7 +574,7 @@ where
     // and that all bytes get written up to the last pos
     unsafe {
         for buf in bufs {
-            pos = vec_write_unchecked(pos, vec, buf);
+            pos = vec_write_all_unchecked(pos, vec, buf);
         }
         if pos > vec.len() {
             vec.set_len(pos);
@@ -580,6 +604,16 @@ impl Write for Cursor<&mut [u8]> {
     }
 
     #[inline]
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        slice_write_all(&mut self.pos, self.inner, buf)
+    }
+
+    #[inline]
+    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
+        slice_write_all_vectored(&mut self.pos, self.inner, bufs)
+    }
+
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
@@ -591,11 +625,11 @@ where
     A: Allocator,
 {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        vec_write(&mut self.pos, self.inner, buf)
+        vec_write_all(&mut self.pos, self.inner, buf)
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        vec_write_vectored(&mut self.pos, self.inner, bufs)
+        vec_write_all_vectored(&mut self.pos, self.inner, bufs)
     }
 
     #[inline]
@@ -603,6 +637,16 @@ where
         true
     }
 
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        vec_write_all(&mut self.pos, self.inner, buf)?;
+        Ok(())
+    }
+
+    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
+        vec_write_all_vectored(&mut self.pos, self.inner, bufs)?;
+        Ok(())
+    }
+
     #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
@@ -615,11 +659,11 @@ where
     A: Allocator,
 {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        vec_write(&mut self.pos, &mut self.inner, buf)
+        vec_write_all(&mut self.pos, &mut self.inner, buf)
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        vec_write_vectored(&mut self.pos, &mut self.inner, bufs)
+        vec_write_all_vectored(&mut self.pos, &mut self.inner, bufs)
     }
 
     #[inline]
@@ -627,6 +671,16 @@ where
         true
     }
 
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        vec_write_all(&mut self.pos, &mut self.inner, buf)?;
+        Ok(())
+    }
+
+    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
+        vec_write_all_vectored(&mut self.pos, &mut self.inner, bufs)?;
+        Ok(())
+    }
+
     #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
@@ -654,6 +708,16 @@ where
     }
 
     #[inline]
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        slice_write_all(&mut self.pos, &mut self.inner, buf)
+    }
+
+    #[inline]
+    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
+        slice_write_all_vectored(&mut self.pos, &mut self.inner, bufs)
+    }
+
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
@@ -677,6 +741,16 @@ impl<const N: usize> Write for Cursor<[u8; N]> {
     }
 
     #[inline]
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        slice_write_all(&mut self.pos, &mut self.inner, buf)
+    }
+
+    #[inline]
+    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
+        slice_write_all_vectored(&mut self.pos, &mut self.inner, bufs)
+    }
+
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index 8239b29884e..d0245f3d498 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -455,7 +455,17 @@ impl Write for &mut [u8] {
 
     #[inline]
     fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
-        if self.write(data)? == data.len() { Ok(()) } else { Err(io::Error::WRITE_ALL_EOF) }
+        if self.write(data)? < data.len() { Err(io::Error::WRITE_ALL_EOF) } else { Ok(()) }
+    }
+
+    #[inline]
+    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
+        for buf in bufs {
+            if self.write(buf)? < buf.len() {
+                return Err(io::Error::WRITE_ALL_EOF);
+            }
+        }
+        Ok(())
     }
 
     #[inline]
@@ -496,6 +506,12 @@ impl<A: Allocator> Write for Vec<u8, A> {
     }
 
     #[inline]
+    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
+        self.write_vectored(bufs)?;
+        Ok(())
+    }
+
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
@@ -515,6 +531,7 @@ impl<A: Allocator> Read for VecDeque<u8, A> {
         Ok(n)
     }
 
+    #[inline]
     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
         let (front, back) = self.as_slices();
 
@@ -547,6 +564,7 @@ impl<A: Allocator> Read for VecDeque<u8, A> {
         Ok(())
     }
 
+    #[inline]
     fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
         let len = cursor.capacity();
         let (front, back) = self.as_slices();
@@ -639,6 +657,12 @@ impl<A: Allocator> Write for VecDeque<u8, A> {
     }
 
     #[inline]
+    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
+        self.write_vectored(bufs)?;
+        Ok(())
+    }
+
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
@@ -646,6 +670,7 @@ impl<A: Allocator> Write for VecDeque<u8, A> {
 
 #[unstable(feature = "read_buf", issue = "78485")]
 impl<'a> io::Write for core::io::BorrowedCursor<'a> {
+    #[inline]
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         let amt = cmp::min(buf.len(), self.capacity());
         self.append(&buf[..amt]);
@@ -653,6 +678,39 @@ impl<'a> io::Write for core::io::BorrowedCursor<'a> {
     }
 
     #[inline]
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        let mut nwritten = 0;
+        for buf in bufs {
+            let n = self.write(buf)?;
+            nwritten += n;
+            if n < buf.len() {
+                break;
+            }
+        }
+        Ok(nwritten)
+    }
+
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        true
+    }
+
+    #[inline]
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        if self.write(buf)? < buf.len() { Err(io::Error::WRITE_ALL_EOF) } else { Ok(()) }
+    }
+
+    #[inline]
+    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
+        for buf in bufs {
+            if self.write(buf)? < buf.len() {
+                return Err(io::Error::WRITE_ALL_EOF);
+            }
+        }
+        Ok(())
+    }
+
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs
index 1d337694944..dfff2d3e5d3 100644
--- a/library/std/src/sys/os_str/bytes.rs
+++ b/library/std/src/sys/os_str/bytes.rs
@@ -140,6 +140,11 @@ impl Buf {
     }
 
     #[inline]
+    pub fn push_str(&mut self, s: &str) {
+        self.inner.extend_from_slice(s.as_bytes());
+    }
+
+    #[inline]
     pub fn reserve(&mut self, additional: usize) {
         self.inner.reserve(additional)
     }
diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs
index 8acec6f949f..a32f5d40f6a 100644
--- a/library/std/src/sys/os_str/wtf8.rs
+++ b/library/std/src/sys/os_str/wtf8.rs
@@ -117,6 +117,11 @@ impl Buf {
     }
 
     #[inline]
+    pub fn push_str(&mut self, s: &str) {
+        self.inner.push_str(s);
+    }
+
+    #[inline]
     pub fn reserve(&mut self, additional: usize) {
         self.inner.reserve(additional)
     }
diff --git a/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir
new file mode 100644
index 00000000000..49314a64c3f
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir
@@ -0,0 +1,89 @@
+// MIR for `demo_le` after PreCodegen
+
+fn demo_le(_1: &MultiField, _2: &MultiField) -> bool {
+    debug a => _1;
+    debug b => _2;
+    let mut _0: bool;
+    scope 1 (inlined <MultiField as PartialOrd>::le) {
+        let mut _11: std::option::Option<std::cmp::Ordering>;
+        scope 2 (inlined Option::<std::cmp::Ordering>::is_some_and::<fn(std::cmp::Ordering) -> bool {std::cmp::Ordering::is_le}>) {
+            let _12: std::cmp::Ordering;
+            scope 3 {
+                scope 4 (inlined <fn(std::cmp::Ordering) -> bool {std::cmp::Ordering::is_le} as FnOnce<(std::cmp::Ordering,)>>::call_once - shim(fn(std::cmp::Ordering) -> bool {std::cmp::Ordering::is_le})) {
+                    scope 5 (inlined std::cmp::Ordering::is_le) {
+                        let mut _13: i8;
+                        scope 6 (inlined std::cmp::Ordering::as_raw) {
+                        }
+                    }
+                }
+            }
+        }
+        scope 7 (inlined <MultiField as PartialOrd>::partial_cmp) {
+            let mut _6: std::option::Option<std::cmp::Ordering>;
+            let mut _7: i8;
+            scope 8 {
+            }
+            scope 9 (inlined std::cmp::impls::<impl PartialOrd for char>::partial_cmp) {
+                let mut _3: char;
+                let mut _4: char;
+                let mut _5: std::cmp::Ordering;
+            }
+            scope 10 (inlined std::cmp::impls::<impl PartialOrd for i16>::partial_cmp) {
+                let mut _8: i16;
+                let mut _9: i16;
+                let mut _10: std::cmp::Ordering;
+            }
+        }
+    }
+
+    bb0: {
+        StorageLive(_12);
+        StorageLive(_11);
+        StorageLive(_5);
+        StorageLive(_7);
+        StorageLive(_3);
+        _3 = copy ((*_1).0: char);
+        StorageLive(_4);
+        _4 = copy ((*_2).0: char);
+        _5 = Cmp(move _3, move _4);
+        StorageDead(_4);
+        StorageDead(_3);
+        _6 = Option::<std::cmp::Ordering>::Some(copy _5);
+        _7 = discriminant(_5);
+        switchInt(move _7) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        StorageLive(_10);
+        StorageLive(_8);
+        _8 = copy ((*_1).1: i16);
+        StorageLive(_9);
+        _9 = copy ((*_2).1: i16);
+        _10 = Cmp(move _8, move _9);
+        StorageDead(_9);
+        StorageDead(_8);
+        _11 = Option::<std::cmp::Ordering>::Some(move _10);
+        StorageDead(_10);
+        StorageDead(_7);
+        StorageDead(_5);
+        goto -> bb3;
+    }
+
+    bb2: {
+        _11 = copy _6;
+        StorageDead(_7);
+        StorageDead(_5);
+        goto -> bb3;
+    }
+
+    bb3: {
+        _12 = move ((_11 as Some).0: std::cmp::Ordering);
+        StorageLive(_13);
+        _13 = discriminant(_12);
+        _0 = Le(move _13, const 0_i8);
+        StorageDead(_13);
+        StorageDead(_11);
+        StorageDead(_12);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/derived_ord.rs b/tests/mir-opt/pre-codegen/derived_ord.rs
index bad751edf84..73ae923a6cb 100644
--- a/tests/mir-opt/pre-codegen/derived_ord.rs
+++ b/tests/mir-opt/pre-codegen/derived_ord.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 //@ compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=0
 
 #![crate_type = "lib"]
@@ -6,4 +5,29 @@
 #[derive(PartialOrd, PartialEq)]
 pub struct MultiField(char, i16);
 
+// Because this isn't derived by the impl, it's not on the `{impl#0}-partial_cmp`,
+// and thus we need to call it to see what the inlined generic one produces.
+pub fn demo_le(a: &MultiField, b: &MultiField) -> bool {
+    // CHECK-LABEL: fn demo_le
+    // CHECK: inlined <MultiField as PartialOrd>::le
+    // CHECK: inlined{{.+}}is_some_and
+    // CHECK: inlined <MultiField as PartialOrd>::partial_cmp
+
+    // CHECK: [[A0:_[0-9]+]] = copy ((*_1).0: char);
+    // CHECK: [[B0:_[0-9]+]] = copy ((*_2).0: char);
+    // CHECK: Cmp(move [[A0]], move [[B0]]);
+
+    // CHECK: [[D0:_[0-9]+]] = discriminant({{.+}});
+    // CHECK: switchInt(move [[D0]]) -> [0: bb{{[0-9]+}}, otherwise: bb{{[0-9]+}}];
+
+    // CHECK: [[A1:_[0-9]+]] = copy ((*_1).1: i16);
+    // CHECK: [[B1:_[0-9]+]] = copy ((*_2).1: i16);
+    // CHECK: Cmp(move [[A1]], move [[B1]]);
+
+    // CHECK: [[D1:_[0-9]+]] = discriminant({{.+}});
+    // CHECK: _0 = Le(move [[D1]], const 0_i8);
+    *a <= *b
+}
+
 // EMIT_MIR derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir
+// EMIT_MIR derived_ord.demo_le.PreCodegen.after.mir
diff --git a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir
index 5f4ec1de270..de25eebee77 100644
--- a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir
@@ -1,6 +1,6 @@
-// MIR for `<impl at $DIR/derived_ord.rs:6:10: 6:20>::partial_cmp` after PreCodegen
+// MIR for `<impl at $DIR/derived_ord.rs:5:10: 5:20>::partial_cmp` after PreCodegen
 
-fn <impl at $DIR/derived_ord.rs:6:10: 6:20>::partial_cmp(_1: &MultiField, _2: &MultiField) -> Option<std::cmp::Ordering> {
+fn <impl at $DIR/derived_ord.rs:5:10: 5:20>::partial_cmp(_1: &MultiField, _2: &MultiField) -> Option<std::cmp::Ordering> {
     debug self => _1;
     debug other => _2;
     let mut _0: std::option::Option<std::cmp::Ordering>;
diff --git a/tests/ui/lifetimes/static-typos.rs b/tests/ui/lifetimes/static-typos.rs
new file mode 100644
index 00000000000..941d1b376bc
--- /dev/null
+++ b/tests/ui/lifetimes/static-typos.rs
@@ -0,0 +1,7 @@
+fn stati<T: 'stati>() {}
+//~^ ERROR use of undeclared lifetime name `'stati`
+
+fn statoc<T: 'statoc>() {}
+//~^ ERROR use of undeclared lifetime name `'statoc`
+
+fn main() {}
diff --git a/tests/ui/lifetimes/static-typos.stderr b/tests/ui/lifetimes/static-typos.stderr
new file mode 100644
index 00000000000..a817fa89c7e
--- /dev/null
+++ b/tests/ui/lifetimes/static-typos.stderr
@@ -0,0 +1,26 @@
+error[E0261]: use of undeclared lifetime name `'stati`
+  --> $DIR/static-typos.rs:1:13
+   |
+LL | fn stati<T: 'stati>() {}
+   |             ^^^^^^ undeclared lifetime
+   |
+help: you may have misspelled the `'static` lifetime
+   |
+LL | fn stati<T: 'static>() {}
+   |                   +
+
+error[E0261]: use of undeclared lifetime name `'statoc`
+  --> $DIR/static-typos.rs:4:14
+   |
+LL | fn statoc<T: 'statoc>() {}
+   |              ^^^^^^^ undeclared lifetime
+   |
+help: you may have misspelled the `'static` lifetime
+   |
+LL - fn statoc<T: 'statoc>() {}
+LL + fn statoc<T: 'static>() {}
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.