diff --git a/Cargo.lock b/Cargo.lock
index 85f588f8e8ac5..2f5aec80cb199 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2082,6 +2082,13 @@ version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
 
+[[package]]
+name = "literal-escaper"
+version = "0.0.0"
+dependencies = [
+ "rustc-std-workspace-std 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "lld-wrapper"
 version = "0.1.0"
@@ -3134,6 +3141,12 @@ version = "1.0.1"
 name = "rustc-std-workspace-std"
 version = "1.0.1"
 
+[[package]]
+name = "rustc-std-workspace-std"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aba676a20abe46e5b0f1b0deae474aaaf31407e6c71147159890574599da04ef"
+
 [[package]]
 name = "rustc_abi"
 version = "0.0.0"
@@ -3172,6 +3185,7 @@ name = "rustc_ast"
 version = "0.0.0"
 dependencies = [
  "bitflags",
+ "literal-escaper",
  "memchr",
  "rustc_ast_ir",
  "rustc_data_structures",
@@ -3881,6 +3895,7 @@ name = "rustc_lexer"
 version = "0.0.0"
 dependencies = [
  "expect-test",
+ "literal-escaper",
  "memchr",
  "unicode-properties",
  "unicode-xid",
@@ -4143,6 +4158,7 @@ name = "rustc_parse"
 version = "0.0.0"
 dependencies = [
  "bitflags",
+ "literal-escaper",
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_data_structures",
@@ -4165,6 +4181,7 @@ dependencies = [
 name = "rustc_parse_format"
 version = "0.0.0"
 dependencies = [
+ "literal-escaper",
  "rustc_index",
  "rustc_lexer",
 ]
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml
index 902287d032802..7f0db1560c1ba 100644
--- a/compiler/rustc_ast/Cargo.toml
+++ b/compiler/rustc_ast/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2024"
 [dependencies]
 # tidy-alphabetical-start
 bitflags = "2.4.1"
+literal-escaper = { path = "../../library/literal-escaper" }
 memchr = "2.7.4"
 rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index 6896ac723fa58..121331ece6d64 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -2,7 +2,7 @@
 
 use std::{ascii, fmt, str};
 
-use rustc_lexer::unescape::{
+use literal_escaper::{
     MixedUnit, Mode, byte_from_char, unescape_byte, unescape_char, unescape_mixed, unescape_unicode,
 };
 use rustc_span::{Span, Symbol, kw, sym};
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index ed5662da16dc9..2d636da4a128b 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -649,10 +649,10 @@ fn print_crate_info(
             HostTuple => println_info!("{}", rustc_session::config::host_tuple()),
             Sysroot => println_info!("{}", sess.sysroot.display()),
             TargetLibdir => println_info!("{}", sess.target_tlib_path.dir.display()),
-            TargetSpec => {
+            TargetSpecJson => {
                 println_info!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
             }
-            AllTargetSpecs => {
+            AllTargetSpecsJson => {
                 let mut targets = BTreeMap::new();
                 for name in rustc_target::spec::TARGETS {
                     let triple = TargetTuple::from_tuple(name);
diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml
index 448a50faf458e..c72425fd92dba 100644
--- a/compiler/rustc_lexer/Cargo.toml
+++ b/compiler/rustc_lexer/Cargo.toml
@@ -16,6 +16,7 @@ Rust lexer used by rustc. No stability guarantees are provided.
 [dependencies]
 memchr = "2.7.4"
 unicode-xid = "0.2.0"
+literal-escaper = { path = "../../library/literal-escaper" }
 
 [dependencies.unicode-properties]
 version = "0.1.0"
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 61638e45253fd..c45dd33982b72 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -26,11 +26,13 @@
 // tidy-alphabetical-end
 
 mod cursor;
-pub mod unescape;
 
 #[cfg(test)]
 mod tests;
 
+// FIXME: This is needed for rust-analyzer. Remove this dependency once rust-analyzer uses
+// `literal-escaper`.
+pub use literal_escaper as unescape;
 use unicode_properties::UnicodeEmoji;
 pub use unicode_xid::UNICODE_VERSION as UNICODE_XID_VERSION;
 
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index c9dcab0c871dd..e83f2d5a56d60 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2024"
 [dependencies]
 # tidy-alphabetical-start
 bitflags = "2.4.1"
+literal-escaper = { path = "../../library/literal-escaper" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 1d17290e1c706..4a3fda86c86c0 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -1,12 +1,12 @@
 use std::ops::Range;
 
+use literal_escaper::{self, EscapeError, Mode};
 use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::util::unicode::contains_text_flow_control_chars;
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, Diag, DiagCtxtHandle, StashKey};
-use rustc_lexer::unescape::{self, EscapeError, Mode};
 use rustc_lexer::{Base, Cursor, DocStyle, LiteralKind, RawStrError};
 use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::{
@@ -970,7 +970,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
         postfix_len: u32,
     ) -> (token::LitKind, Symbol) {
         self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| {
-            unescape::unescape_unicode(src, mode, &mut |span, result| {
+            literal_escaper::unescape_unicode(src, mode, &mut |span, result| {
                 callback(span, result.map(drop))
             })
         })
@@ -986,7 +986,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
         postfix_len: u32,
     ) -> (token::LitKind, Symbol) {
         self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| {
-            unescape::unescape_mixed(src, mode, &mut |span, result| {
+            literal_escaper::unescape_mixed(src, mode, &mut |span, result| {
                 callback(span, result.map(drop))
             })
         })
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index 2e066f0179c3f..e8aa400e73d44 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -3,8 +3,8 @@
 use std::iter::once;
 use std::ops::Range;
 
+use literal_escaper::{EscapeError, Mode};
 use rustc_errors::{Applicability, DiagCtxtHandle, ErrorGuaranteed};
-use rustc_lexer::unescape::{EscapeError, Mode};
 use rustc_span::{BytePos, Span};
 use tracing::debug;
 
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 0774324eae742..85d94400b1c6f 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -6,6 +6,7 @@ use core::ops::{Bound, ControlFlow};
 use ast::mut_visit::{self, MutVisitor};
 use ast::token::{IdentIsRaw, MetaVarKind};
 use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered};
+use literal_escaper::unescape_char;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::TokenTree;
@@ -21,7 +22,6 @@ use rustc_ast::{
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic};
-use rustc_lexer::unescape::unescape_char;
 use rustc_macros::Subdiagnostic;
 use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error};
 use rustc_session::lint::BuiltinLintDiag;
diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml
index a39cca716d23e..e63ed9e16f2e8 100644
--- a/compiler/rustc_parse_format/Cargo.toml
+++ b/compiler/rustc_parse_format/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
+literal-escaper = { path = "../../library/literal-escaper" }
 rustc_index = { path = "../rustc_index", default-features = false }
 rustc_lexer = { path = "../rustc_lexer" }
 # tidy-alphabetical-end
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 5b8a2fe52d3f5..5780daf303437 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -18,7 +18,6 @@
 pub use Alignment::*;
 pub use Count::*;
 pub use Position::*;
-use rustc_lexer::unescape;
 
 // Note: copied from rustc_span
 /// Range inside of a `Span` used for diagnostics when we only have access to relative positions.
@@ -1094,12 +1093,14 @@ fn find_width_map_from_snippet(
 fn unescape_string(string: &str) -> Option<String> {
     let mut buf = String::new();
     let mut ok = true;
-    unescape::unescape_unicode(string, unescape::Mode::Str, &mut |_, unescaped_char| {
-        match unescaped_char {
+    literal_escaper::unescape_unicode(
+        string,
+        literal_escaper::Mode::Str,
+        &mut |_, unescaped_char| match unescaped_char {
             Ok(c) => buf.push(c),
             Err(_) => ok = false,
-        }
-    });
+        },
+    );
 
     ok.then_some(buf)
 }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 34755249b60b1..701d06e4fd403 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -44,7 +44,7 @@ pub mod sigpipe;
 
 pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
     // tidy-alphabetical-start
-    ("all-target-specs-json", PrintKind::AllTargetSpecs),
+    ("all-target-specs-json", PrintKind::AllTargetSpecsJson),
     ("calling-conventions", PrintKind::CallingConventions),
     ("cfg", PrintKind::Cfg),
     ("check-cfg", PrintKind::CheckCfg),
@@ -63,7 +63,7 @@ pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
     ("target-features", PrintKind::TargetFeatures),
     ("target-libdir", PrintKind::TargetLibdir),
     ("target-list", PrintKind::TargetList),
-    ("target-spec-json", PrintKind::TargetSpec),
+    ("target-spec-json", PrintKind::TargetSpecJson),
     ("tls-models", PrintKind::TlsModels),
     // tidy-alphabetical-end
 ];
@@ -873,27 +873,29 @@ pub struct PrintRequest {
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum PrintKind {
+    // tidy-alphabetical-start
+    AllTargetSpecsJson,
+    CallingConventions,
+    Cfg,
+    CheckCfg,
+    CodeModels,
+    CrateName,
+    DeploymentTarget,
     FileNames,
     HostTuple,
+    LinkArgs,
+    NativeStaticLibs,
+    RelocationModels,
+    SplitDebuginfo,
+    StackProtectorStrategies,
     Sysroot,
-    TargetLibdir,
-    CrateName,
-    Cfg,
-    CheckCfg,
-    CallingConventions,
-    TargetList,
     TargetCPUs,
     TargetFeatures,
-    RelocationModels,
-    CodeModels,
+    TargetLibdir,
+    TargetList,
+    TargetSpecJson,
     TlsModels,
-    TargetSpec,
-    AllTargetSpecs,
-    NativeStaticLibs,
-    StackProtectorStrategies,
-    LinkArgs,
-    SplitDebuginfo,
-    DeploymentTarget,
+    // tidy-alphabetical-end
 }
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)]
@@ -2030,49 +2032,13 @@ fn collect_print_requests(
     prints.extend(matches.opt_strs("print").into_iter().map(|req| {
         let (req, out) = split_out_file_name(&req);
 
-        let kind = match PRINT_KINDS.iter().find(|&&(name, _)| name == req) {
-            Some((_, PrintKind::TargetSpec)) => {
-                if unstable_opts.unstable_options {
-                    PrintKind::TargetSpec
-                } else {
-                    early_dcx.early_fatal(
-                        "the `-Z unstable-options` flag must also be passed to \
-                         enable the target-spec-json print option",
-                    );
-                }
-            }
-            Some((_, PrintKind::AllTargetSpecs)) => {
-                if unstable_opts.unstable_options {
-                    PrintKind::AllTargetSpecs
-                } else {
-                    early_dcx.early_fatal(
-                        "the `-Z unstable-options` flag must also be passed to \
-                         enable the all-target-specs-json print option",
-                    );
-                }
-            }
-            Some((_, PrintKind::CheckCfg)) => {
-                if unstable_opts.unstable_options {
-                    PrintKind::CheckCfg
-                } else {
-                    early_dcx.early_fatal(
-                        "the `-Z unstable-options` flag must also be passed to \
-                         enable the check-cfg print option",
-                    );
-                }
-            }
-            Some(&(_, print_kind)) => print_kind,
-            None => {
-                let prints =
-                    PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
-                let prints = prints.join(", ");
-
-                let mut diag =
-                    early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
-                #[allow(rustc::diagnostic_outside_of_impl)]
-                diag.help(format!("valid print requests are: {prints}"));
-                diag.emit()
-            }
+        let kind = if let Some((print_name, print_kind)) =
+            PRINT_KINDS.iter().find(|&&(name, _)| name == req)
+        {
+            check_print_request_stability(early_dcx, unstable_opts, (print_name, *print_kind));
+            *print_kind
+        } else {
+            emit_unknown_print_request_help(early_dcx, req)
         };
 
         let out = out.unwrap_or(OutFileName::Stdout);
@@ -2091,6 +2057,34 @@ fn collect_print_requests(
     prints
 }
 
+fn check_print_request_stability(
+    early_dcx: &EarlyDiagCtxt,
+    unstable_opts: &UnstableOptions,
+    (print_name, print_kind): (&str, PrintKind),
+) {
+    match print_kind {
+        PrintKind::AllTargetSpecsJson | PrintKind::CheckCfg | PrintKind::TargetSpecJson
+            if !unstable_opts.unstable_options =>
+        {
+            early_dcx.early_fatal(format!(
+                "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \
+                print option"
+            ));
+        }
+        _ => {}
+    }
+}
+
+fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str) -> ! {
+    let prints = PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
+    let prints = prints.join(", ");
+
+    let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
+    #[allow(rustc::diagnostic_outside_of_impl)]
+    diag.help(format!("valid print requests are: {prints}"));
+    diag.emit()
+}
+
 pub fn parse_target_triple(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> TargetTuple {
     match matches.opt_str("target") {
         Some(target) if target.ends_with(".json") => {
diff --git a/library/Cargo.lock b/library/Cargo.lock
index ac8740605144a..d9a24f7cd242b 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -165,6 +165,13 @@ dependencies = [
  "rustc-std-workspace-core",
 ]
 
+[[package]]
+name = "literal-escaper"
+version = "0.0.0"
+dependencies = [
+ "rustc-std-workspace-std",
+]
+
 [[package]]
 name = "memchr"
 version = "2.7.4"
@@ -236,6 +243,7 @@ name = "proc_macro"
 version = "0.0.0"
 dependencies = [
  "core",
+ "literal-escaper",
  "std",
 ]
 
diff --git a/library/Cargo.toml b/library/Cargo.toml
index 4d5955593ffcd..5445fd61afa0c 100644
--- a/library/Cargo.toml
+++ b/library/Cargo.toml
@@ -8,6 +8,7 @@ members = [
 ]
 
 exclude = [
+  "literal-escaper",
   # stdarch has its own Cargo workspace
   "stdarch",
   "windows_targets"
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index da9a77154f9b5..3782f9e95194c 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1252,6 +1252,19 @@ impl<T, A: Allocator> Vec<T, A> {
     /// vec.push(42);
     /// assert!(vec.capacity() >= 10);
     /// ```
+    ///
+    /// A vector with zero-sized elements will always have a capacity of usize::MAX:
+    ///
+    /// ```
+    /// #[derive(Clone)]
+    /// struct ZeroSized;
+    ///
+    /// fn main() {
+    ///     assert_eq!(std::mem::size_of::<ZeroSized>(), 0);
+    ///     let v = vec![ZeroSized; 0];
+    ///     assert_eq!(v.capacity(), usize::MAX);
+    /// }
+    /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")]
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 0246d0627cafe..d5cb10a5d1c8b 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -147,22 +147,42 @@ impl_from!(i16 => isize, #[stable(feature = "lossless_iusize_conv", since = "1.2
 // https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-951.pdf
 
 // Note: integers can only be represented with full precision in a float if
-// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
+// they fit in the significand, which is:
+// * 11 bits in f16
+// * 24 bits in f32
+// * 53 bits in f64
+// * 113 bits in f128
 // Lossy float conversions are not implemented at this time.
+// FIXME(f16_f128): The `f16`/`f128` impls `#[stable]` attributes should be changed to reference
+// `f16`/`f128` when they are stabilised (trait impls have to have a `#[stable]` attribute, but none
+// of the `f16`/`f128` impls can be used on stable as the `f16` and `f128` types are unstable).
 
 // signed integer -> float
+impl_from!(i8 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 impl_from!(i8 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 impl_from!(i8 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+impl_from!(i8 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 impl_from!(i16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 impl_from!(i16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+impl_from!(i16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 impl_from!(i32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+impl_from!(i32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+// FIXME(f16_f128): This impl would allow using `f128` on stable before it is stabilised.
+// impl_from!(i64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 
 // unsigned integer -> float
+impl_from!(u8 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 impl_from!(u8 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 impl_from!(u8 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+impl_from!(u8 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+impl_from!(u16 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 impl_from!(u16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+impl_from!(u16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+impl_from!(u32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+// FIXME(f16_f128): This impl would allow using `f128` on stable before it is stabilised.
+// impl_from!(u64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 
 // float -> float
 // FIXME(f16_f128): adding additional `From<{float}>` impls to `f32` breaks inference. See
@@ -174,7 +194,12 @@ impl_from!(f32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0
 impl_from!(f64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 
 macro_rules! impl_float_from_bool {
-    ($float:ty) => {
+    (
+        $float:ty $(;
+            doctest_prefix: $(#[doc = $doctest_prefix:literal])*
+            doctest_suffix: $(#[doc = $doctest_suffix:literal])*
+        )?
+    ) => {
         #[stable(feature = "float_from_bool", since = "1.68.0")]
         impl From<bool> for $float {
             #[doc = concat!("Converts a [`bool`] to [`", stringify!($float),"`] losslessly.")]
@@ -182,12 +207,14 @@ macro_rules! impl_float_from_bool {
             ///
             /// # Examples
             /// ```
+            $($(#[doc = $doctest_prefix])*)?
             #[doc = concat!("let x: ", stringify!($float)," = false.into();")]
             /// assert_eq!(x, 0.0);
             /// assert!(x.is_sign_positive());
             ///
             #[doc = concat!("let y: ", stringify!($float)," = true.into();")]
             /// assert_eq!(y, 1.0);
+            $($(#[doc = $doctest_suffix])*)?
             /// ```
             #[inline]
             fn from(small: bool) -> Self {
@@ -198,8 +225,27 @@ macro_rules! impl_float_from_bool {
 }
 
 // boolean -> float
+impl_float_from_bool!(
+    f16;
+    doctest_prefix:
+    // rustdoc doesn't remove the conventional space after the `///`
+    ///#![feature(f16)]
+    ///# #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
+    ///
+    doctest_suffix:
+    ///# }
+);
 impl_float_from_bool!(f32);
 impl_float_from_bool!(f64);
+impl_float_from_bool!(
+    f128;
+    doctest_prefix:
+    ///#![feature(f128)]
+    ///# #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
+    ///
+    doctest_suffix:
+    ///# }
+);
 
 // no possible bounds violation
 macro_rules! impl_try_from_unbounded {
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 078f7552c8744..cf03c07b6a564 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -3641,7 +3641,8 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(ptr: *const
 /// For regions of memory which might overlap, use [`copy`] instead.
 ///
 /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
-/// with the argument order swapped.
+/// with the source and destination arguments swapped,
+/// and `count` counting the number of `T`s instead of bytes.
 ///
 /// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the
 /// requirements of `T`. The initialization state is preserved exactly.
@@ -3761,8 +3762,10 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
 /// If the source and destination will *never* overlap,
 /// [`copy_nonoverlapping`] can be used instead.
 ///
-/// `copy` is semantically equivalent to C's [`memmove`], but with the argument
-/// order swapped. Copying takes place as if the bytes were copied from `src`
+/// `copy` is semantically equivalent to C's [`memmove`], but
+/// with the source and destination arguments swapped,
+/// and `count` counting the number of `T`s instead of bytes.
+/// Copying takes place as if the bytes were copied from `src`
 /// to a temporary array and then copied from the array to `dst`.
 ///
 /// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the
diff --git a/library/literal-escaper/Cargo.toml b/library/literal-escaper/Cargo.toml
new file mode 100644
index 0000000000000..708fcd3cacb69
--- /dev/null
+++ b/library/literal-escaper/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "literal-escaper"
+version = "0.0.0"
+edition = "2021"
+
+[dependencies]
+std = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-std' }
+
+[features]
+rustc-dep-of-std = ["dep:std"]
diff --git a/library/literal-escaper/README.md b/library/literal-escaper/README.md
new file mode 100644
index 0000000000000..9986d2451c759
--- /dev/null
+++ b/library/literal-escaper/README.md
@@ -0,0 +1,4 @@
+# literal-escaper
+
+This crate provides code to unescape string literals. It is used by `rustc_lexer`
+and `proc_macro`.
diff --git a/compiler/rustc_lexer/src/unescape.rs b/library/literal-escaper/src/lib.rs
similarity index 100%
rename from compiler/rustc_lexer/src/unescape.rs
rename to library/literal-escaper/src/lib.rs
diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/library/literal-escaper/src/tests.rs
similarity index 100%
rename from compiler/rustc_lexer/src/unescape/tests.rs
rename to library/literal-escaper/src/tests.rs
diff --git a/library/proc_macro/Cargo.toml b/library/proc_macro/Cargo.toml
index 72cb4e4166f8e..f2ac530dfd2b0 100644
--- a/library/proc_macro/Cargo.toml
+++ b/library/proc_macro/Cargo.toml
@@ -4,6 +4,7 @@ version = "0.0.0"
 edition = "2024"
 
 [dependencies]
+literal-escaper = { path = "../literal-escaper", features = ["rustc-dep-of-std"] }
 std = { path = "../std" }
 # Workaround: when documenting this crate rustdoc will try to load crate named
 # `core` when resolving doc links. Without this line a different `core` will be
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index d9141eab5919f..bd08d59daa866 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -28,6 +28,7 @@
 #![feature(restricted_std)]
 #![feature(rustc_attrs)]
 #![feature(extend_one)]
+#![feature(stmt_expr_attributes)]
 #![recursion_limit = "256"]
 #![allow(internal_features)]
 #![deny(ffi_unwind_calls)]
@@ -51,11 +52,24 @@ use std::{error, fmt};
 
 #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
 pub use diagnostic::{Diagnostic, Level, MultiSpan};
+#[unstable(feature = "proc_macro_value", issue = "136652")]
+pub use literal_escaper::EscapeError;
+use literal_escaper::{MixedUnit, Mode, byte_from_char, unescape_mixed, unescape_unicode};
 #[unstable(feature = "proc_macro_totokens", issue = "130977")]
 pub use to_tokens::ToTokens;
 
 use crate::escape::{EscapeOptions, escape_bytes};
 
+/// Errors returned when trying to retrieve a literal unescaped value.
+#[unstable(feature = "proc_macro_value", issue = "136652")]
+#[derive(Debug, PartialEq, Eq)]
+pub enum ConversionErrorKind {
+    /// The literal failed to be escaped, take a look at [`EscapeError`] for more information.
+    FailedToUnescape(EscapeError),
+    /// Trying to convert a literal with the wrong type.
+    InvalidLiteralKind,
+}
+
 /// Determines whether proc_macro has been made accessible to the currently
 /// running program.
 ///
@@ -1451,6 +1465,107 @@ impl Literal {
             }
         })
     }
+
+    /// Returns the unescaped string value if the current literal is a string or a string literal.
+    #[unstable(feature = "proc_macro_value", issue = "136652")]
+    pub fn str_value(&self) -> Result<String, ConversionErrorKind> {
+        self.0.symbol.with(|symbol| match self.0.kind {
+            bridge::LitKind::Str => {
+                if symbol.contains('\\') {
+                    let mut buf = String::with_capacity(symbol.len());
+                    let mut error = None;
+                    // Force-inlining here is aggressive but the closure is
+                    // called on every char in the string, so it can be hot in
+                    // programs with many long strings containing escapes.
+                    unescape_unicode(
+                        symbol,
+                        Mode::Str,
+                        &mut #[inline(always)]
+                        |_, c| match c {
+                            Ok(c) => buf.push(c),
+                            Err(err) => {
+                                if err.is_fatal() {
+                                    error = Some(ConversionErrorKind::FailedToUnescape(err));
+                                }
+                            }
+                        },
+                    );
+                    if let Some(error) = error { Err(error) } else { Ok(buf) }
+                } else {
+                    Ok(symbol.to_string())
+                }
+            }
+            bridge::LitKind::StrRaw(_) => Ok(symbol.to_string()),
+            _ => Err(ConversionErrorKind::InvalidLiteralKind),
+        })
+    }
+
+    /// Returns the unescaped string value if the current literal is a c-string or a c-string
+    /// literal.
+    #[unstable(feature = "proc_macro_value", issue = "136652")]
+    pub fn cstr_value(&self) -> Result<Vec<u8>, ConversionErrorKind> {
+        self.0.symbol.with(|symbol| match self.0.kind {
+            bridge::LitKind::CStr => {
+                let mut error = None;
+                let mut buf = Vec::with_capacity(symbol.len());
+
+                unescape_mixed(symbol, Mode::CStr, &mut |_span, c| match c {
+                    Ok(MixedUnit::Char(c)) => {
+                        buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
+                    }
+                    Ok(MixedUnit::HighByte(b)) => buf.push(b),
+                    Err(err) => {
+                        if err.is_fatal() {
+                            error = Some(ConversionErrorKind::FailedToUnescape(err));
+                        }
+                    }
+                });
+                if let Some(error) = error {
+                    Err(error)
+                } else {
+                    buf.push(0);
+                    Ok(buf)
+                }
+            }
+            bridge::LitKind::CStrRaw(_) => {
+                // Raw strings have no escapes so we can convert the symbol
+                // directly to a `Lrc<u8>` after appending the terminating NUL
+                // char.
+                let mut buf = symbol.to_owned().into_bytes();
+                buf.push(0);
+                Ok(buf)
+            }
+            _ => Err(ConversionErrorKind::InvalidLiteralKind),
+        })
+    }
+
+    /// Returns the unescaped string value if the current literal is a byte string or a byte string
+    /// literal.
+    #[unstable(feature = "proc_macro_value", issue = "136652")]
+    pub fn byte_str_value(&self) -> Result<Vec<u8>, ConversionErrorKind> {
+        self.0.symbol.with(|symbol| match self.0.kind {
+            bridge::LitKind::ByteStr => {
+                let mut buf = Vec::with_capacity(symbol.len());
+                let mut error = None;
+
+                unescape_unicode(symbol, Mode::ByteStr, &mut |_, c| match c {
+                    Ok(c) => buf.push(byte_from_char(c)),
+                    Err(err) => {
+                        if err.is_fatal() {
+                            error = Some(ConversionErrorKind::FailedToUnescape(err));
+                        }
+                    }
+                });
+                if let Some(error) = error { Err(error) } else { Ok(buf) }
+            }
+            bridge::LitKind::ByteStrRaw(_) => {
+                // Raw strings have no escapes so we can convert the symbol
+                // directly to a `Lrc<u8>`.
+                Ok(symbol.to_owned().into_bytes())
+            }
+            _ => Err(ConversionErrorKind::InvalidLiteralKind),
+        })
+    }
 }
 
 /// Parse a single literal from its stringified representation.
diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs
index cd2c7899f4bf1..9a5b3b2fd197a 100644
--- a/library/std/src/sys/personality/gcc.rs
+++ b/library/std/src/sys/personality/gcc.rs
@@ -220,7 +220,7 @@ cfg_if::cfg_if! {
                     Ok(action) => action,
                     Err(_) => return uw::_URC_FATAL_PHASE1_ERROR,
                 };
-                if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
+                if actions & uw::_UA_SEARCH_PHASE != 0 {
                     match eh_action {
                         EHAction::None | EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND,
                         EHAction::Catch(_) | EHAction::Filter(_) => uw::_URC_HANDLER_FOUND,
@@ -230,7 +230,7 @@ cfg_if::cfg_if! {
                     match eh_action {
                         EHAction::None => uw::_URC_CONTINUE_UNWIND,
                         // Forced unwinding hits a terminate action.
-                        EHAction::Filter(_) if actions as i32 & uw::_UA_FORCE_UNWIND as i32 != 0 => uw::_URC_CONTINUE_UNWIND,
+                        EHAction::Filter(_) if actions & uw::_UA_FORCE_UNWIND != 0 => uw::_URC_CONTINUE_UNWIND,
                         EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => {
                             uw::_Unwind_SetGR(
                                 context,
diff --git a/library/std/tests/floats/f128.rs b/library/std/tests/floats/f128.rs
index d0e8b157e6b6f..b4a6c672bf05f 100644
--- a/library/std/tests/floats/f128.rs
+++ b/library/std/tests/floats/f128.rs
@@ -983,3 +983,34 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::INFINITY));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
 }
+
+#[test]
+fn test_from() {
+    assert_eq!(f128::from(false), 0.0);
+    assert_eq!(f128::from(true), 1.0);
+    assert_eq!(f128::from(u8::MIN), 0.0);
+    assert_eq!(f128::from(42_u8), 42.0);
+    assert_eq!(f128::from(u8::MAX), 255.0);
+    assert_eq!(f128::from(i8::MIN), -128.0);
+    assert_eq!(f128::from(42_i8), 42.0);
+    assert_eq!(f128::from(i8::MAX), 127.0);
+    assert_eq!(f128::from(u16::MIN), 0.0);
+    assert_eq!(f128::from(42_u16), 42.0);
+    assert_eq!(f128::from(u16::MAX), 65535.0);
+    assert_eq!(f128::from(i16::MIN), -32768.0);
+    assert_eq!(f128::from(42_i16), 42.0);
+    assert_eq!(f128::from(i16::MAX), 32767.0);
+    assert_eq!(f128::from(u32::MIN), 0.0);
+    assert_eq!(f128::from(42_u32), 42.0);
+    assert_eq!(f128::from(u32::MAX), 4294967295.0);
+    assert_eq!(f128::from(i32::MIN), -2147483648.0);
+    assert_eq!(f128::from(42_i32), 42.0);
+    assert_eq!(f128::from(i32::MAX), 2147483647.0);
+    // FIXME(f16_f128): Uncomment these tests once the From<{u64,i64}> impls are added.
+    // assert_eq!(f128::from(u64::MIN), 0.0);
+    // assert_eq!(f128::from(42_u64), 42.0);
+    // assert_eq!(f128::from(u64::MAX), 18446744073709551615.0);
+    // assert_eq!(f128::from(i64::MIN), -9223372036854775808.0);
+    // assert_eq!(f128::from(42_i64), 42.0);
+    // assert_eq!(f128::from(i64::MAX), 9223372036854775807.0);
+}
diff --git a/library/std/tests/floats/f16.rs b/library/std/tests/floats/f16.rs
index 19389a9178e91..ca0b8efbe83ba 100644
--- a/library/std/tests/floats/f16.rs
+++ b/library/std/tests/floats/f16.rs
@@ -953,3 +953,15 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::INFINITY));
     assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
 }
+
+#[test]
+fn test_from() {
+    assert_eq!(f16::from(false), 0.0);
+    assert_eq!(f16::from(true), 1.0);
+    assert_eq!(f16::from(u8::MIN), 0.0);
+    assert_eq!(f16::from(42_u8), 42.0);
+    assert_eq!(f16::from(u8::MAX), 255.0);
+    assert_eq!(f16::from(i8::MIN), -128.0);
+    assert_eq!(f16::from(42_i8), 42.0);
+    assert_eq!(f16::from(i8::MAX), 127.0);
+}
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index ced8e82b8ebe8..fe33b3049162a 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -128,16 +128,13 @@ if #[cfg(any(target_vendor = "apple", target_os = "netbsd", not(target_arch = "a
     //
     // 32-bit ARM on iOS/tvOS/watchOS use either DWARF/Compact unwinding or
     // "setjmp-longjmp" / SjLj unwinding.
-    #[repr(C)]
-    #[derive(Copy, Clone, PartialEq)]
-    pub enum _Unwind_Action {
-        _UA_SEARCH_PHASE = 1,
-        _UA_CLEANUP_PHASE = 2,
-        _UA_HANDLER_FRAME = 4,
-        _UA_FORCE_UNWIND = 8,
-        _UA_END_OF_STACK = 16,
-    }
-    pub use _Unwind_Action::*;
+    pub type _Unwind_Action = c_int;
+
+    pub const _UA_SEARCH_PHASE: c_int = 1;
+    pub const _UA_CLEANUP_PHASE: c_int = 2;
+    pub const _UA_HANDLER_FRAME: c_int = 4;
+    pub const _UA_FORCE_UNWIND: c_int = 8;
+    pub const _UA_END_OF_STACK: c_int = 16;
 
     #[cfg_attr(
         all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
diff --git a/library/unwind/src/unwinding.rs b/library/unwind/src/unwinding.rs
index fa8a8c385839b..36120bc868ee9 100644
--- a/library/unwind/src/unwinding.rs
+++ b/library/unwind/src/unwinding.rs
@@ -2,16 +2,13 @@
 
 use core::ffi::{c_int, c_void};
 
-#[repr(C)]
-#[derive(Copy, Clone, PartialEq)]
-pub enum _Unwind_Action {
-    _UA_SEARCH_PHASE = 1,
-    _UA_CLEANUP_PHASE = 2,
-    _UA_HANDLER_FRAME = 4,
-    _UA_FORCE_UNWIND = 8,
-    _UA_END_OF_STACK = 16,
-}
-pub use _Unwind_Action::*;
+pub type _Unwind_Action = c_int;
+
+pub const _UA_SEARCH_PHASE: c_int = 1;
+pub const _UA_CLEANUP_PHASE: c_int = 2;
+pub const _UA_HANDLER_FRAME: c_int = 4;
+pub const _UA_FORCE_UNWIND: c_int = 8;
+pub const _UA_END_OF_STACK: c_int = 16;
 
 #[repr(C)]
 #[derive(Debug, Copy, Clone, PartialEq)]
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index b062781e68a71..343fbcc0286de 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -655,7 +655,7 @@ mod dist {
         let mut builder = Builder::new(&build);
         builder.run_step_descriptions(
             &Builder::get_step_descriptions(Kind::Build),
-            &["compiler/rustc".into(), "library".into()],
+            &["compiler/rustc".into(), "std".into()],
         );
 
         assert_eq!(builder.config.stage, 2);
diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs
index 2706aba5ffc8d..3720602dc7749 100644
--- a/src/bootstrap/src/core/metadata.rs
+++ b/src/bootstrap/src/core/metadata.rs
@@ -62,6 +62,11 @@ pub fn build(build: &mut Build) {
             let relative_path = krate.local_path(build);
             build.crates.insert(name.clone(), krate);
             let existing_path = build.crate_paths.insert(relative_path, name);
+            // `literal-escaper` is both a dependency of `compiler/rustc_lexer` and of
+            // `library/proc-macro`, making it appear multiple times in the workspace.
+            if existing_path.as_deref() == Some("literal-escaper") {
+                continue;
+            }
             assert!(
                 existing_path.is_none(),
                 "multiple crates with the same path: {}",
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index b2ad2fa773ae5..8dfde1679fe11 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1465,8 +1465,6 @@ pub(crate) fn notable_traits_button(
     ty: &clean::Type,
     cx: &Context<'_>,
 ) -> Option<impl fmt::Display> {
-    let mut has_notable_trait = false;
-
     if ty.is_unit() {
         // Very common fast path.
         return None;
@@ -1484,27 +1482,19 @@ pub(crate) fn notable_traits_button(
         return None;
     }
 
-    if let Some(impls) = cx.cache().impls.get(&did) {
-        for i in impls {
-            let impl_ = i.inner_impl();
-            if impl_.polarity != ty::ImplPolarity::Positive {
-                continue;
-            }
-
-            if !ty.is_doc_subtype_of(&impl_.for_, cx.cache()) {
+    let impls = cx.cache().impls.get(&did)?;
+    let has_notable_trait = impls
+        .iter()
+        .map(Impl::inner_impl)
+        .filter(|impl_| {
+            impl_.polarity == ty::ImplPolarity::Positive
                 // Two different types might have the same did,
                 // without actually being the same.
-                continue;
-            }
-            if let Some(trait_) = &impl_.trait_ {
-                let trait_did = trait_.def_id();
-
-                if cx.cache().traits.get(&trait_did).is_some_and(|t| t.is_notable_trait(cx.tcx())) {
-                    has_notable_trait = true;
-                }
-            }
-        }
-    }
+                && ty.is_doc_subtype_of(&impl_.for_, cx.cache())
+        })
+        .filter_map(|impl_| impl_.trait_.as_ref())
+        .filter_map(|trait_| cx.cache().traits.get(&trait_.def_id()))
+        .any(|t| t.is_notable_trait(cx.tcx()));
 
     has_notable_trait.then(|| {
         cx.types_with_notable_traits.borrow_mut().insert(ty.clone());
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 81c55ecaa7a29..8a95c6dd5e626 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -318,6 +318,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "libloading",
     "linux-raw-sys",
     "litemap",
+    "literal-escaper",
     "lock_api",
     "log",
     "matchers",
@@ -363,6 +364,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "rustc-rayon",
     "rustc-rayon-core",
     "rustc-stable-hash",
+    "rustc-std-workspace-std",
     "rustc_apfloat",
     "rustix",
     "ruzstd", // via object in thorin-dwp
diff --git a/tests/ui/feature-gates/feature-gate-print-check-cfg.rs b/tests/ui/feature-gates/feature-gate-print-check-cfg.rs
deleted file mode 100644
index 304e0c132e50a..0000000000000
--- a/tests/ui/feature-gates/feature-gate-print-check-cfg.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-//@ compile-flags: --print=check-cfg
-
-fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr b/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr
deleted file mode 100644
index 62ee44b94a489..0000000000000
--- a/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: the `-Z unstable-options` flag must also be passed to enable the check-cfg print option
-
diff --git a/tests/ui/feature-gates/literal-escaper.rs b/tests/ui/feature-gates/literal-escaper.rs
new file mode 100644
index 0000000000000..7c145fca7dec2
--- /dev/null
+++ b/tests/ui/feature-gates/literal-escaper.rs
@@ -0,0 +1,3 @@
+#![crate_type = "lib"]
+
+extern crate literal_escaper; //~ ERROR
diff --git a/tests/ui/feature-gates/literal-escaper.stderr b/tests/ui/feature-gates/literal-escaper.stderr
new file mode 100644
index 0000000000000..edddb6504f575
--- /dev/null
+++ b/tests/ui/feature-gates/literal-escaper.stderr
@@ -0,0 +1,13 @@
+error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
+  --> $DIR/literal-escaper.rs:3:1
+   |
+LL | extern crate literal_escaper;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information
+   = help: add `#![feature(rustc_private)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs
new file mode 100644
index 0000000000000..b205b05556912
--- /dev/null
+++ b/tests/ui/print-request/stability.rs
@@ -0,0 +1,103 @@
+//! Check that we properly gate unstable print requests (`--print=KIND`) and require the user to
+//! specify `-Z unstable-options` to use unstable print requests.
+
+// We don't care about the exact *stdout* output (i.e. what the print requests actually give back)
+// for the purposes of this test.
+//@ dont-check-compiler-stdout
+
+// We want to check for the core error message of the unstable print requests being `-Z
+// unstable-options`-gated and not the help because the help can change with addition of a new print
+// request, which is not important for the purposes of this test.
+//@ dont-check-compiler-stderr
+
+// =======================
+// Unstable print requests
+// =======================
+
+//@ revisions: all_target_specs_json
+//@[all_target_specs_json] compile-flags: --print=all-target-specs-json
+//@[all_target_specs_json] error-pattern: the `-Z unstable-options` flag must also be passed
+
+//@ revisions: check_cfg
+//@[check_cfg] compile-flags: --print=check-cfg
+//@[check_cfg] error-pattern: the `-Z unstable-options` flag must also be passed
+
+//@ revisions: target_spec_json
+//@[target_spec_json] compile-flags: --print=target-spec-json
+//@[target_spec_json] error-pattern: the `-Z unstable-options` flag must also be passed
+
+// =======================
+// Stable print requests
+// =======================
+
+//@ revisions: calling_conventions
+//@[calling_conventions] compile-flags: --print=calling-conventions
+//@[calling_conventions] check-pass
+
+//@ revisions: cfg
+//@[cfg] compile-flags: --print=cfg
+//@[cfg] check-pass
+
+//@ revisions: code_models
+//@[code_models] compile-flags: --print=code-models
+//@[code_models] check-pass
+
+//@ revisions: crate_name
+//@[crate_name] compile-flags: --print=crate-name
+//@[crate_name] check-pass
+
+// Note: `--print=deployment_target` is only accepted on Apple targets.
+//@ revisions: deployment_target
+//@[deployment_target] only-apple
+//@[deployment_target] compile-flags: --print=deployment-target
+//@[deployment_target] check-pass
+
+//@ revisions: file_names
+//@[file_names] compile-flags: --print=file-names
+//@[file_names] check-pass
+
+//@ revisions: host_tuple
+//@[host_tuple] compile-flags: --print=host-tuple
+//@[host_tuple] check-pass
+
+//@ revisions: link_args
+//@[link_args] compile-flags: --print=link-args
+//@[link_args] check-pass
+
+//@ revisions: native_static_libs
+//@[native_static_libs] compile-flags: --print=native-static-libs
+//@[native_static_libs] check-pass
+
+//@ revisions: relocation_models
+//@[relocation_models] compile-flags: --print=relocation-models
+//@[relocation_models] check-pass
+
+//@ revisions: split_debuginfo
+//@[split_debuginfo] compile-flags: --print=split-debuginfo
+//@[split_debuginfo] check-pass
+
+//@ revisions: stack_protector_strategies
+//@[stack_protector_strategies] compile-flags: --print=stack-protector-strategies
+//@[stack_protector_strategies] check-pass
+
+//@ revisions: target_cpus
+//@[target_cpus] compile-flags: --print=target-cpus
+//@[target_cpus] check-pass
+
+//@ revisions: target_features
+//@[target_features] compile-flags: --print=target-features
+//@[target_features] check-pass
+
+//@ revisions: target_libdir
+//@[target_libdir] compile-flags: --print=target-libdir
+//@[target_libdir] check-pass
+
+//@ revisions: target_list
+//@[target_list] compile-flags: --print=target-list
+//@[target_list] check-pass
+
+//@ revisions: tls_models
+//@[tls_models] compile-flags: --print=tls-models
+//@[tls_models] check-pass
+
+fn main() {}
diff --git a/tests/ui/proc-macro/auxiliary/api/literal.rs b/tests/ui/proc-macro/auxiliary/api/literal.rs
index 7109340bb645b..941de1521ade9 100644
--- a/tests/ui/proc-macro/auxiliary/api/literal.rs
+++ b/tests/ui/proc-macro/auxiliary/api/literal.rs
@@ -1,10 +1,11 @@
 // ignore-tidy-linelength
 
-use proc_macro::Literal;
+use proc_macro::{ConversionErrorKind, Literal};
 
 pub fn test() {
     test_display_literal();
     test_parse_literal();
+    test_str_value_methods();
 }
 
 fn test_display_literal() {
@@ -81,3 +82,53 @@ fn test_parse_literal() {
     assert!("- 10".parse::<Literal>().is_err());
     assert!("-'x'".parse::<Literal>().is_err());
 }
+
+fn test_str_value_methods() {
+    // Testing `str_value`
+    let lit = "\"\n\"".parse::<Literal>().unwrap();
+    assert_eq!(lit.str_value(), Ok("\n".to_string()));
+
+    let lit = "r#\"\n\"#".parse::<Literal>().unwrap();
+    assert_eq!(lit.str_value(), Ok("\n".to_string()));
+
+    let lit = "1".parse::<Literal>().unwrap();
+    assert_eq!(lit.str_value(), Err(ConversionErrorKind::InvalidLiteralKind));
+
+    let lit = "b\"\n\"".parse::<Literal>().unwrap();
+    assert_eq!(lit.str_value(), Err(ConversionErrorKind::InvalidLiteralKind));
+
+    let lit = "c\"\n\"".parse::<Literal>().unwrap();
+    assert_eq!(lit.str_value(), Err(ConversionErrorKind::InvalidLiteralKind));
+
+    // Testing `cstr_value`
+    let lit = "\"\n\"".parse::<Literal>().unwrap();
+    assert_eq!(lit.cstr_value(), Err(ConversionErrorKind::InvalidLiteralKind));
+
+    let lit = "r#\"\n\"#".parse::<Literal>().unwrap();
+    assert_eq!(lit.cstr_value(), Err(ConversionErrorKind::InvalidLiteralKind));
+
+    let lit = "1".parse::<Literal>().unwrap();
+    assert_eq!(lit.cstr_value(), Err(ConversionErrorKind::InvalidLiteralKind));
+
+    let lit = "b\"\n\"".parse::<Literal>().unwrap();
+    assert_eq!(lit.cstr_value(), Err(ConversionErrorKind::InvalidLiteralKind));
+
+    let lit = "c\"\n\"".parse::<Literal>().unwrap();
+    assert_eq!(lit.cstr_value(), Ok(vec![b'\n', 0]));
+
+    // Testing `byte_str_value`
+    let lit = "\"\n\"".parse::<Literal>().unwrap();
+    assert_eq!(lit.byte_str_value(), Err(ConversionErrorKind::InvalidLiteralKind));
+
+    let lit = "r#\"\n\"#".parse::<Literal>().unwrap();
+    assert_eq!(lit.byte_str_value(), Err(ConversionErrorKind::InvalidLiteralKind));
+
+    let lit = "1".parse::<Literal>().unwrap();
+    assert_eq!(lit.byte_str_value(), Err(ConversionErrorKind::InvalidLiteralKind));
+
+    let lit = "b\"\n\"".parse::<Literal>().unwrap();
+    assert_eq!(lit.byte_str_value(), Ok(vec![b'\n']));
+
+    let lit = "c\"\n\"".parse::<Literal>().unwrap();
+    assert_eq!(lit.byte_str_value(), Err(ConversionErrorKind::InvalidLiteralKind));
+}
diff --git a/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs b/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs
index abd667d8ce1d0..390d46852cd54 100644
--- a/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs
+++ b/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs
@@ -1,6 +1,7 @@
 //@ edition: 2021
 
 #![feature(proc_macro_span)]
+#![feature(proc_macro_value)]
 #![deny(dead_code)] // catch if a test function is never called
 
 extern crate proc_macro;