diff --git a/Cargo.lock b/Cargo.lock
index 633eeb3d3bd8e..7afb6d5f361a7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4294,6 +4294,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_hir",
+ "rustc_macros",
  "rustc_middle",
  "rustc_session",
  "rustc_span",
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index a1233d62cb02e..708fe8719a1eb 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -1,4 +1,6 @@
-use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{
+    struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
+};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
 
@@ -476,10 +478,11 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     fn struct_span_err_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
         code: DiagnosticId,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code)
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 8ef2974c37232..a2df072aa3119 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(let_else)]
 #![feature(min_specialization)]
 #![feature(never_type)]
+#![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![feature(trusted_step)]
 #![feature(try_blocks)]
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index c75d83bd0a0e3..aa355150b4f81 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -36,7 +36,7 @@ pub fn expand_cfg(
 }
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "builtin-macros-requires-cfg-pattern")]
+#[error(builtin_macros::requires_cfg_pattern)]
 struct RequiresCfgPattern {
     #[primary_span]
     #[label]
@@ -44,7 +44,7 @@ struct RequiresCfgPattern {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "builtin-macros-expected-one-cfg-pattern")]
+#[error(builtin_macros::expected_one_cfg_pattern)]
 struct OneCfgPattern {
     #[primary_span]
     span: Span,
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 6c30923bc3d73..4be3ae11e4e5b 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(associated_type_bounds)]
 #![feature(strict_provenance)]
 #![feature(int_roundings)]
+#![feature(if_let_guard)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 0ed4c3f1d9430..7f14b95317b46 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -376,32 +376,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
 
             // This requires that atomic intrinsics follow a specific naming pattern:
-            // "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
-            name if name_str.starts_with("atomic_") => {
+            // "atomic_<operation>[_<ordering>]"
+            name if let Some(atomic) = name_str.strip_prefix("atomic_") => {
                 use crate::common::AtomicOrdering::*;
                 use crate::common::{AtomicRmwBinOp, SynchronizationScope};
 
-                let split: Vec<_> = name_str.split('_').collect();
-
-                let is_cxchg = split[1] == "cxchg" || split[1] == "cxchgweak";
-                let (order, failorder) = match split.len() {
-                    2 => (SequentiallyConsistent, SequentiallyConsistent),
-                    3 => match split[2] {
-                        "unordered" => (Unordered, Unordered),
-                        "relaxed" => (Relaxed, Relaxed),
-                        "acq" => (Acquire, Acquire),
-                        "rel" => (Release, Relaxed),
-                        "acqrel" => (AcquireRelease, Acquire),
-                        "failrelaxed" if is_cxchg => (SequentiallyConsistent, Relaxed),
-                        "failacq" if is_cxchg => (SequentiallyConsistent, Acquire),
-                        _ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
-                    },
-                    4 => match (split[2], split[3]) {
-                        ("acq", "failrelaxed") if is_cxchg => (Acquire, Relaxed),
-                        ("acqrel", "failrelaxed") if is_cxchg => (AcquireRelease, Relaxed),
-                        _ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
-                    },
-                    _ => bx.sess().fatal("Atomic intrinsic not in correct format"),
+                let Some((instruction, ordering)) = atomic.split_once('_') else {
+                    bx.sess().fatal("Atomic intrinsic missing memory ordering");
+                };
+
+                let parse_ordering = |bx: &Bx, s| match s {
+                    "unordered" => Unordered,
+                    "relaxed" => Relaxed,
+                    "acquire" => Acquire,
+                    "release" => Release,
+                    "acqrel" => AcquireRelease,
+                    "seqcst" => SequentiallyConsistent,
+                    _ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
                 };
 
                 let invalid_monomorphization = |ty| {
@@ -416,11 +407,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     );
                 };
 
-                match split[1] {
+                match instruction {
                     "cxchg" | "cxchgweak" => {
+                        let Some((success, failure)) = ordering.split_once('_') else {
+                            bx.sess().fatal("Atomic compare-exchange intrinsic missing failure memory ordering");
+                        };
                         let ty = substs.type_at(0);
                         if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
-                            let weak = split[1] == "cxchgweak";
+                            let weak = instruction == "cxchgweak";
                             let mut dst = args[0].immediate();
                             let mut cmp = args[1].immediate();
                             let mut src = args[2].immediate();
@@ -432,7 +426,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 cmp = bx.ptrtoint(cmp, bx.type_isize());
                                 src = bx.ptrtoint(src, bx.type_isize());
                             }
-                            let pair = bx.atomic_cmpxchg(dst, cmp, src, order, failorder, weak);
+                            let pair = bx.atomic_cmpxchg(dst, cmp, src, parse_ordering(bx, success), parse_ordering(bx, failure), weak);
                             let val = bx.extract_value(pair, 0);
                             let success = bx.extract_value(pair, 1);
                             let val = bx.from_immediate(val);
@@ -460,11 +454,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 let llty = bx.type_isize();
                                 let ptr_llty = bx.type_ptr_to(llty);
                                 source = bx.pointercast(source, ptr_llty);
-                                let result = bx.atomic_load(llty, source, order, size);
+                                let result = bx.atomic_load(llty, source, parse_ordering(bx, ordering), size);
                                 // ... and then cast the result back to a pointer
                                 bx.inttoptr(result, bx.backend_type(layout))
                             } else {
-                                bx.atomic_load(bx.backend_type(layout), source, order, size)
+                                bx.atomic_load(bx.backend_type(layout), source, parse_ordering(bx, ordering), size)
                             }
                         } else {
                             return invalid_monomorphization(ty);
@@ -484,7 +478,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 ptr = bx.pointercast(ptr, ptr_llty);
                                 val = bx.ptrtoint(val, bx.type_isize());
                             }
-                            bx.atomic_store(val, ptr, order, size);
+                            bx.atomic_store(val, ptr, parse_ordering(bx, ordering), size);
                             return;
                         } else {
                             return invalid_monomorphization(ty);
@@ -492,12 +486,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
 
                     "fence" => {
-                        bx.atomic_fence(order, SynchronizationScope::CrossThread);
+                        bx.atomic_fence(parse_ordering(bx, ordering), SynchronizationScope::CrossThread);
                         return;
                     }
 
                     "singlethreadfence" => {
-                        bx.atomic_fence(order, SynchronizationScope::SingleThread);
+                        bx.atomic_fence(parse_ordering(bx, ordering), SynchronizationScope::SingleThread);
                         return;
                     }
 
@@ -531,7 +525,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 ptr = bx.pointercast(ptr, ptr_llty);
                                 val = bx.ptrtoint(val, bx.type_isize());
                             }
-                            bx.atomic_rmw(atom_op, ptr, val, order)
+                            bx.atomic_rmw(atom_op, ptr, val, parse_ordering(bx, ordering))
                         } else {
                             return invalid_monomorphization(ty);
                         }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0093.md b/compiler/rustc_error_codes/src/error_codes/E0093.md
index 6d58e50ec8813..b1683cf4fc4ae 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0093.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0093.md
@@ -24,12 +24,12 @@ functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in
 #![feature(intrinsics)]
 
 extern "rust-intrinsic" {
-    fn atomic_fence(); // ok!
+    fn atomic_fence_seqcst(); // ok!
 }
 
 fn main() {
     unsafe {
-        atomic_fence();
+        atomic_fence_seqcst();
     }
 }
 ```
diff --git a/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl b/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl
index 1d3e33c81851f..4a42d52f71004 100644
--- a/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl
@@ -1,5 +1,5 @@
-builtin-macros-requires-cfg-pattern =
+builtin_macros-requires-cfg-pattern =
     macro requires a cfg-pattern as an argument
     .label = cfg-pattern required
 
-builtin-macros-expected-one-cfg-pattern = expected 1 cfg-pattern
+builtin_macros-expected-one-cfg-pattern = expected 1 cfg-pattern
diff --git a/compiler/rustc_error_messages/locales/en-US/privacy.ftl b/compiler/rustc_error_messages/locales/en-US/privacy.ftl
new file mode 100644
index 0000000000000..2b0778f48caee
--- /dev/null
+++ b/compiler/rustc_error_messages/locales/en-US/privacy.ftl
@@ -0,0 +1,12 @@
+privacy-field-is-private = field `{$field_name}` of {$variant_descr} `{$def_path_str}` is private
+privacy-field-is-private-is-update-syntax-label = field `{$field_name}` is private
+privacy-field-is-private-label = private field
+
+privacy-item-is-private = {$kind} `{$descr}` is private
+    .label = private {$kind}
+privacy-unnamed-item-is-private = {$kind} is private
+    .label = private {$kind}
+
+privacy-in-public-interface = {$vis_descr} {$kind} `{$descr}` in public interface
+    .label = can't leak {$vis_descr} {$kind}
+    .visibility-label = `{$descr}` declared as {$vis_descr}
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 7211c05432698..90eb5ef54462d 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -32,6 +32,7 @@ pub use unic_langid::{langid, LanguageIdentifier};
 // Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
 fluent_messages! {
     parser => "../locales/en-US/parser.ftl",
+    privacy => "../locales/en-US/privacy.ftl",
     typeck => "../locales/en-US/typeck.ftl",
     builtin_macros => "../locales/en-US/builtin_macros.ftl",
 }
@@ -258,18 +259,6 @@ pub enum SubdiagnosticMessage {
     FluentAttr(FluentId),
 }
 
-impl SubdiagnosticMessage {
-    /// Create a `SubdiagnosticMessage` for the provided Fluent attribute.
-    pub fn attr(id: impl Into<FluentId>) -> Self {
-        SubdiagnosticMessage::FluentAttr(id.into())
-    }
-
-    /// Create a `SubdiagnosticMessage` for the provided Fluent identifier.
-    pub fn message(id: impl Into<FluentId>) -> Self {
-        SubdiagnosticMessage::FluentIdentifier(id.into())
-    }
-}
-
 /// `From` impl that enables existing diagnostic calls to functions which now take
 /// `impl Into<SubdiagnosticMessage>` to continue to work as before.
 impl<S: Into<String>> From<S> for SubdiagnosticMessage {
@@ -332,11 +321,6 @@ impl DiagnosticMessage {
             _ => panic!("expected non-translatable diagnostic message"),
         }
     }
-
-    /// Create a `DiagnosticMessage` for the provided Fluent identifier.
-    pub fn new(id: impl Into<FluentId>) -> Self {
-        DiagnosticMessage::FluentIdentifier(id.into(), None)
-    }
 }
 
 /// `From` impl that enables existing diagnostic calls to functions which now take
@@ -347,6 +331,27 @@ impl<S: Into<String>> From<S> for DiagnosticMessage {
     }
 }
 
+/// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but
+/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagnosticMessage` and the
+/// subdiagnostic derive refers to typed identifiers that are `DiagnosticMessage`s, so need to be
+/// able to convert between these, as much as they'll be converted back into `DiagnosticMessage`
+/// using `with_subdiagnostic_message` eventually. Don't use this other than for the derive.
+impl Into<SubdiagnosticMessage> for DiagnosticMessage {
+    fn into(self) -> SubdiagnosticMessage {
+        match self {
+            DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s),
+            DiagnosticMessage::FluentIdentifier(id, None) => {
+                SubdiagnosticMessage::FluentIdentifier(id)
+            }
+            // There isn't really a sensible behaviour for this because it loses information but
+            // this is the most sensible of the behaviours.
+            DiagnosticMessage::FluentIdentifier(_, Some(attr)) => {
+                SubdiagnosticMessage::FluentAttr(attr)
+            }
+        }
+    }
+}
+
 /// A span together with some additional data.
 #[derive(Clone, Debug)]
 pub struct SpanLabel {
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 245719bff1202..1e57d66dd9f56 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1077,6 +1077,7 @@ impl<'a> ExtCtxt<'a> {
         self.current_expansion.id.expansion_cause()
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -1101,9 +1102,11 @@ impl<'a> ExtCtxt<'a> {
     ///
     /// Compilation will be stopped in the near future (at the end of
     /// the macro expansion phase).
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.sess.parse_sess.span_diagnostic.span_err(sp, msg);
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
     }
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 86ff110eec183..c18147592dc70 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -9,6 +9,7 @@
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_span)]
+#![feature(rustc_attrs)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
 
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index fadb1c8793398..56c8635a189e1 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -406,9 +406,12 @@ impl LateLintPass<'_> for Diagnostics {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         let Some((span, def_id, substs)) = typeck_results_of_method_fn(cx, expr) else { return };
         debug!(?span, ?def_id, ?substs);
-        if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) &&
-            !cx.tcx.has_attr(instance.def_id(), sym::rustc_lint_diagnostics)
-        {
+        let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs)
+            .ok()
+            .and_then(|inst| inst)
+            .map(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics))
+            .unwrap_or(false);
+        if !has_attr {
             return;
         }
 
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index b1bfd612b90e5..d52455e2576c9 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -289,6 +289,7 @@ declare_lint! {
     "constant evaluation encountered erroneous expression",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #71800 <https://github.com/rust-lang/rust/issues/71800>",
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
     };
     report_in_external_macro
 }
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index 95ee0d4a060d2..d0c8652718969 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -12,7 +12,9 @@ use proc_macro2::{Ident, TokenStream};
 use quote::{format_ident, quote};
 use std::collections::HashMap;
 use std::str::FromStr;
-use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, Type};
+use syn::{
+    parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type,
+};
 use synstructure::{BindingInfo, Structure};
 
 /// The central struct for constructing the `into_diagnostic` method from an annotated struct.
@@ -118,23 +120,23 @@ impl<'a> SessionDiagnosticDerive<'a> {
                         return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error();
                     }
                     (Some((kind, _)), None) => {
-                        span_err(span, "`slug` not specified")
-                            .help(&format!("use the `#[{}(slug = \"...\")]` attribute to set this diagnostic's slug", kind.descr()))
+                        span_err(span, "diagnostic slug not specified")
+                            .help(&format!(
+                                "specify the slug as the first argument to the attribute, such as \
+                                 `#[{}(typeck::example_error)]`",
+                                kind.descr()
+                            ))
                             .emit();
                         return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error();
                     }
                     (Some((SessionDiagnosticKind::Error, _)), Some((slug, _))) => {
                         quote! {
-                            let mut #diag = #sess.struct_err(
-                                rustc_errors::DiagnosticMessage::new(#slug),
-                            );
+                            let mut #diag = #sess.struct_err(rustc_errors::fluent::#slug);
                         }
                     }
                     (Some((SessionDiagnosticKind::Warn, _)), Some((slug, _))) => {
                         quote! {
-                            let mut #diag = #sess.struct_warn(
-                                rustc_errors::DiagnosticMessage::new(#slug),
-                            );
+                            let mut #diag = #sess.struct_warn(rustc_errors::fluent::#slug);
                         }
                     }
                 };
@@ -226,7 +228,7 @@ struct SessionDiagnosticDeriveBuilder {
     kind: Option<(SessionDiagnosticKind, proc_macro::Span)>,
     /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that
     /// has the actual diagnostic message.
-    slug: Option<(String, proc_macro::Span)>,
+    slug: Option<(Path, proc_macro::Span)>,
     /// Error codes are a optional part of the struct attribute - this is only set to detect
     /// multiple specifications.
     code: Option<(String, proc_macro::Span)>,
@@ -240,50 +242,79 @@ impl HasFieldMap for SessionDiagnosticDeriveBuilder {
 
 impl SessionDiagnosticDeriveBuilder {
     /// Establishes state in the `SessionDiagnosticDeriveBuilder` resulting from the struct
-    /// attributes like `#[error(..)#`, such as the diagnostic kind and slug. Generates
+    /// attributes like `#[error(..)`, such as the diagnostic kind and slug. Generates
     /// diagnostic builder calls for setting error code and creating note/help messages.
     fn generate_structure_code(
         &mut self,
         attr: &Attribute,
     ) -> Result<TokenStream, SessionDiagnosticDeriveError> {
+        let diag = &self.diag;
         let span = attr.span().unwrap();
 
         let name = attr.path.segments.last().unwrap().ident.to_string();
         let name = name.as_str();
         let meta = attr.parse_meta()?;
 
-        if matches!(name, "help" | "note") && matches!(meta, Meta::Path(_) | Meta::NameValue(_)) {
-            let diag = &self.diag;
-            let id = match meta {
-                Meta::Path(..) => quote! { #name },
-                Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
-                    quote! { #s }
-                }
-                _ => unreachable!(),
-            };
-            let fn_name = proc_macro2::Ident::new(name, attr.span());
-
-            return Ok(quote! {
-                #diag.#fn_name(rustc_errors::SubdiagnosticMessage::attr(#id));
-            });
-        }
+        let is_help_or_note = matches!(name, "help" | "note");
 
         let nested = match meta {
+            // Most attributes are lists, like `#[error(..)]`/`#[warning(..)]` for most cases or
+            // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug.
             Meta::List(MetaList { ref nested, .. }) => nested,
+            // Subdiagnostics without spans can be applied to the type too, and these are just
+            // paths: `#[help]` and `#[note]`
+            Meta::Path(_) if is_help_or_note => {
+                let fn_name = proc_macro2::Ident::new(name, attr.span());
+                return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::_subdiag::#fn_name); });
+            }
             _ => throw_invalid_attr!(attr, &meta),
         };
 
-        let kind = match name {
-            "error" => SessionDiagnosticKind::Error,
-            "warning" => SessionDiagnosticKind::Warn,
+        // Check the kind before doing any further processing so that there aren't misleading
+        // "no kind specified" errors if there are failures later.
+        match name {
+            "error" => self.kind.set_once((SessionDiagnosticKind::Error, span)),
+            "warning" => self.kind.set_once((SessionDiagnosticKind::Warn, span)),
+            "help" | "note" => (),
             _ => throw_invalid_attr!(attr, &meta, |diag| {
-                diag.help("only `error` and `warning` are valid attributes")
+                diag.help("only `error`, `warning`, `help` and `note` are valid attributes")
             }),
-        };
-        self.kind.set_once((kind, span));
+        }
+
+        // First nested element should always be the path, e.g. `#[error(typeck::invalid)]` or
+        // `#[help(typeck::another_help)]`.
+        let mut nested_iter = nested.into_iter();
+        if let Some(nested_attr) = nested_iter.next() {
+            // Report an error if there are any other list items after the path.
+            if is_help_or_note && nested_iter.next().is_some() {
+                throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+                    diag.help("`help` and `note` struct attributes can only have one argument")
+                });
+            }
 
+            match nested_attr {
+                NestedMeta::Meta(Meta::Path(path)) if is_help_or_note => {
+                    let fn_name = proc_macro2::Ident::new(name, attr.span());
+                    return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); });
+                }
+                NestedMeta::Meta(Meta::Path(path)) => {
+                    self.slug.set_once((path.clone(), span));
+                }
+                NestedMeta::Meta(meta @ Meta::NameValue(_))
+                    if !is_help_or_note
+                        && meta.path().segments.last().unwrap().ident.to_string() == "code" =>
+                {
+                    // don't error for valid follow-up attributes
+                }
+                nested_attr => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+                    diag.help("first argument of the attribute should be the diagnostic slug")
+                }),
+            };
+        }
+
+        // Remaining attributes are optional, only `code = ".."` at the moment.
         let mut tokens = Vec::new();
-        for nested_attr in nested {
+        for nested_attr in nested_iter {
             let meta = match nested_attr {
                 syn::NestedMeta::Meta(meta) => meta,
                 _ => throw_invalid_nested_attr!(attr, &nested_attr),
@@ -291,28 +322,24 @@ impl SessionDiagnosticDeriveBuilder {
 
             let path = meta.path();
             let nested_name = path.segments.last().unwrap().ident.to_string();
-            match &meta {
-                // Struct attributes are only allowed to be applied once, and the diagnostic
-                // changes will be set in the initialisation code.
-                Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
-                    let span = s.span().unwrap();
-                    match nested_name.as_str() {
-                        "slug" => {
-                            self.slug.set_once((s.value(), span));
-                        }
-                        "code" => {
-                            self.code.set_once((s.value(), span));
-                            let (diag, code) = (&self.diag, &self.code.as_ref().map(|(v, _)| v));
-                            tokens.push(quote! {
-                                #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
-                            });
-                        }
-                        _ => invalid_nested_attr(attr, &nested_attr)
-                            .help("only `slug` and `code` are valid nested attributes")
-                            .emit(),
+            // Struct attributes are only allowed to be applied once, and the diagnostic
+            // changes will be set in the initialisation code.
+            if let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) = &meta {
+                let span = s.span().unwrap();
+                match nested_name.as_str() {
+                    "code" => {
+                        self.code.set_once((s.value(), span));
+                        let code = &self.code.as_ref().map(|(v, _)| v);
+                        tokens.push(quote! {
+                            #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
+                        });
                     }
+                    _ => invalid_nested_attr(attr, &nested_attr)
+                        .help("only `code` is a valid nested attributes following the slug")
+                        .emit(),
                 }
-                _ => invalid_nested_attr(attr, &nested_attr).emit(),
+            } else {
+                invalid_nested_attr(attr, &nested_attr).emit()
             }
         }
 
@@ -382,142 +409,215 @@ impl SessionDiagnosticDeriveBuilder {
         info: FieldInfo<'_>,
         binding: TokenStream,
     ) -> Result<TokenStream, SessionDiagnosticDeriveError> {
+        let meta = attr.parse_meta()?;
+        match meta {
+            Meta::Path(_) => self.generate_inner_field_code_path(attr, info, binding),
+            Meta::List(MetaList { .. }) => self.generate_inner_field_code_list(attr, info, binding),
+            _ => throw_invalid_attr!(attr, &meta),
+        }
+    }
+
+    fn generate_inner_field_code_path(
+        &mut self,
+        attr: &Attribute,
+        info: FieldInfo<'_>,
+        binding: TokenStream,
+    ) -> Result<TokenStream, SessionDiagnosticDeriveError> {
+        assert!(matches!(attr.parse_meta()?, Meta::Path(_)));
         let diag = &self.diag;
 
+        let meta = attr.parse_meta()?;
+
         let ident = &attr.path.segments.last().unwrap().ident;
         let name = ident.to_string();
         let name = name.as_str();
+        match name {
+            "skip_arg" => {
+                // Don't need to do anything - by virtue of the attribute existing, the
+                // `set_arg` call will not be generated.
+                Ok(quote! {})
+            }
+            "primary_span" => {
+                report_error_if_not_applied_to_span(attr, &info)?;
+                Ok(quote! {
+                    #diag.set_span(#binding);
+                })
+            }
+            "label" => {
+                report_error_if_not_applied_to_span(attr, &info)?;
+                Ok(self.add_spanned_subdiagnostic(binding, ident, parse_quote! { _subdiag::label }))
+            }
+            "note" | "help" => {
+                let path = match name {
+                    "note" => parse_quote! { _subdiag::note },
+                    "help" => parse_quote! { _subdiag::help },
+                    _ => unreachable!(),
+                };
+                if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
+                    Ok(self.add_spanned_subdiagnostic(binding, ident, path))
+                } else if type_is_unit(&info.ty) {
+                    Ok(self.add_subdiagnostic(ident, path))
+                } else {
+                    report_type_error(attr, "`Span` or `()`")?;
+                }
+            }
+            "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }),
+            _ => throw_invalid_attr!(attr, &meta, |diag| {
+                diag.help(
+                    "only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` \
+                     are valid field attributes",
+                )
+            }),
+        }
+    }
 
+    fn generate_inner_field_code_list(
+        &mut self,
+        attr: &Attribute,
+        info: FieldInfo<'_>,
+        binding: TokenStream,
+    ) -> Result<TokenStream, SessionDiagnosticDeriveError> {
         let meta = attr.parse_meta()?;
-        match meta {
-            Meta::Path(_) => match name {
-                "skip_arg" => {
-                    // Don't need to do anything - by virtue of the attribute existing, the
-                    // `set_arg` call will not be generated.
-                    Ok(quote! {})
-                }
-                "primary_span" => {
-                    report_error_if_not_applied_to_span(attr, &info)?;
-                    Ok(quote! {
-                        #diag.set_span(#binding);
-                    })
-                }
-                "label" => {
-                    report_error_if_not_applied_to_span(attr, &info)?;
-                    Ok(self.add_spanned_subdiagnostic(binding, ident, name))
-                }
-                "note" | "help" => {
-                    if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
-                        Ok(self.add_spanned_subdiagnostic(binding, ident, name))
-                    } else if type_is_unit(&info.ty) {
-                        Ok(self.add_subdiagnostic(ident, name))
-                    } else {
-                        report_type_error(attr, "`Span` or `()`")?;
-                    }
-                }
-                "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }),
-                _ => throw_invalid_attr!(attr, &meta, |diag| {
-                    diag
-                        .help("only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes")
-                }),
-            },
-            Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(ref s), .. }) => match name {
-                "label" => {
-                    report_error_if_not_applied_to_span(attr, &info)?;
-                    Ok(self.add_spanned_subdiagnostic(binding, ident, &s.value()))
-                }
-                "note" | "help" => {
-                    if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
-                        Ok(self.add_spanned_subdiagnostic(binding, ident, &s.value()))
-                    } else if type_is_unit(&info.ty) {
-                        Ok(self.add_subdiagnostic(ident, &s.value()))
-                    } else {
-                        report_type_error(attr, "`Span` or `()`")?;
-                    }
-                }
-                _ => throw_invalid_attr!(attr, &meta, |diag| {
-                    diag.help("only `label`, `note` and `help` are valid field attributes")
-                }),
-            },
-            Meta::List(MetaList { ref path, ref nested, .. }) => {
-                let name = path.segments.last().unwrap().ident.to_string();
-                let name = name.as_ref();
-
-                match name {
-                    "suggestion" | "suggestion_short" | "suggestion_hidden"
-                    | "suggestion_verbose" => (),
-                    _ => throw_invalid_attr!(attr, &meta, |diag| {
-                        diag
-                            .help("only `suggestion{,_short,_hidden,_verbose}` are valid field attributes")
-                    }),
-                };
+        let Meta::List(MetaList { ref path, ref nested, .. }) = meta  else { unreachable!() };
 
-                let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?;
+        let ident = &attr.path.segments.last().unwrap().ident;
+        let name = path.segments.last().unwrap().ident.to_string();
+        let name = name.as_ref();
+        match name {
+            "suggestion" | "suggestion_short" | "suggestion_hidden" | "suggestion_verbose" => {
+                return self.generate_inner_field_code_suggestion(attr, info);
+            }
+            "label" | "help" | "note" => (),
+            _ => throw_invalid_attr!(attr, &meta, |diag| {
+                diag.help(
+                    "only `label`, `note`, `help` or `suggestion{,_short,_hidden,_verbose}` are \
+                     valid field attributes",
+                )
+            }),
+        }
 
-                let mut msg = None;
-                let mut code = None;
+        // For `#[label(..)]`, `#[note(..)]` and `#[help(..)]`, the first nested element must be a
+        // path, e.g. `#[label(typeck::label)]`.
+        let mut nested_iter = nested.into_iter();
+        let msg = match nested_iter.next() {
+            Some(NestedMeta::Meta(Meta::Path(path))) => path.clone(),
+            Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr),
+            None => throw_invalid_attr!(attr, &meta),
+        };
 
-                for nested_attr in nested {
-                    let meta = match nested_attr {
-                        syn::NestedMeta::Meta(ref meta) => meta,
-                        syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr),
-                    };
+        // None of these attributes should have anything following the slug.
+        if nested_iter.next().is_some() {
+            throw_invalid_attr!(attr, &meta);
+        }
 
-                    let nested_name = meta.path().segments.last().unwrap().ident.to_string();
-                    let nested_name = nested_name.as_str();
-                    match meta {
-                        Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
-                            let span = meta.span().unwrap();
-                            match nested_name {
-                                "message" => {
-                                    msg = Some(s.value());
-                                }
-                                "code" => {
-                                    let formatted_str = self.build_format(&s.value(), s.span());
-                                    code = Some(formatted_str);
+        match name {
+            "label" => {
+                report_error_if_not_applied_to_span(attr, &info)?;
+                Ok(self.add_spanned_subdiagnostic(binding, ident, msg))
+            }
+            "note" | "help" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => {
+                Ok(self.add_spanned_subdiagnostic(binding, ident, msg))
+            }
+            "note" | "help" if type_is_unit(&info.ty) => Ok(self.add_subdiagnostic(ident, msg)),
+            "note" | "help" => {
+                report_type_error(attr, "`Span` or `()`")?;
+            }
+            _ => unreachable!(),
+        }
+    }
+
+    fn generate_inner_field_code_suggestion(
+        &mut self,
+        attr: &Attribute,
+        info: FieldInfo<'_>,
+    ) -> Result<TokenStream, SessionDiagnosticDeriveError> {
+        let diag = &self.diag;
+
+        let mut meta = attr.parse_meta()?;
+        let Meta::List(MetaList { ref path, ref mut nested, .. }) = meta  else { unreachable!() };
+
+        let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?;
+
+        let mut msg = None;
+        let mut code = None;
+
+        let mut nested_iter = nested.into_iter().peekable();
+        if let Some(nested_attr) = nested_iter.peek() {
+            if let NestedMeta::Meta(Meta::Path(path)) = nested_attr {
+                msg = Some(path.clone());
+            }
+        };
+        // Move the iterator forward if a path was found (don't otherwise so that
+        // code/applicability can be found or an error emitted).
+        if msg.is_some() {
+            let _ = nested_iter.next();
+        }
+
+        for nested_attr in nested_iter {
+            let meta = match nested_attr {
+                syn::NestedMeta::Meta(ref meta) => meta,
+                syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr),
+            };
+
+            let nested_name = meta.path().segments.last().unwrap().ident.to_string();
+            let nested_name = nested_name.as_str();
+            match meta {
+                Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
+                    let span = meta.span().unwrap();
+                    match nested_name {
+                        "code" => {
+                            let formatted_str = self.build_format(&s.value(), s.span());
+                            code = Some(formatted_str);
+                        }
+                        "applicability" => {
+                            applicability = match applicability {
+                                Some(v) => {
+                                    span_err(
+                                        span,
+                                        "applicability cannot be set in both the field and \
+                                         attribute",
+                                    )
+                                    .emit();
+                                    Some(v)
                                 }
-                                "applicability" => {
-                                    applicability = match applicability {
-                                        Some(v) => {
-                                            span_err(
-                                                span,
-                                                "applicability cannot be set in both the field and attribute"
-                                            ).emit();
-                                            Some(v)
-                                        }
-                                        None => match Applicability::from_str(&s.value()) {
-                                            Ok(v) => Some(quote! { #v }),
-                                            Err(()) => {
-                                                span_err(span, "invalid applicability").emit();
-                                                None
-                                            }
-                                        },
+                                None => match Applicability::from_str(&s.value()) {
+                                    Ok(v) => Some(quote! { #v }),
+                                    Err(()) => {
+                                        span_err(span, "invalid applicability").emit();
+                                        None
                                     }
-                                }
-                                _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
-                                    diag.help(
-                                        "only `message`, `code` and `applicability` are valid field attributes",
-                                    )
-                                }),
+                                },
                             }
                         }
-                        _ => throw_invalid_nested_attr!(attr, &nested_attr),
+                        _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+                            diag.help(
+                                "only `message`, `code` and `applicability` are valid field \
+                                 attributes",
+                            )
+                        }),
                     }
                 }
+                _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+                    if matches!(meta, Meta::Path(_)) {
+                        diag.help("a diagnostic slug must be the first argument to the attribute")
+                    } else {
+                        diag
+                    }
+                }),
+            }
+        }
 
-                let applicability = applicability
-                    .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified));
+        let applicability =
+            applicability.unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified));
 
-                let method = format_ident!("span_{}", name);
+        let name = path.segments.last().unwrap().ident.to_string();
+        let method = format_ident!("span_{}", name);
 
-                let msg = msg.as_deref().unwrap_or("suggestion");
-                let msg = quote! { rustc_errors::SubdiagnosticMessage::attr(#msg) };
-                let code = code.unwrap_or_else(|| quote! { String::new() });
+        let msg = msg.unwrap_or_else(|| parse_quote! { _subdiag::suggestion });
+        let msg = quote! { rustc_errors::fluent::#msg };
+        let code = code.unwrap_or_else(|| quote! { String::new() });
 
-                Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); })
-            }
-            _ => throw_invalid_attr!(attr, &meta),
-        }
+        Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); })
     }
 
     /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug
@@ -526,24 +626,24 @@ impl SessionDiagnosticDeriveBuilder {
         &self,
         field_binding: TokenStream,
         kind: &Ident,
-        fluent_attr_identifier: &str,
+        fluent_attr_identifier: Path,
     ) -> TokenStream {
         let diag = &self.diag;
         let fn_name = format_ident!("span_{}", kind);
         quote! {
             #diag.#fn_name(
                 #field_binding,
-                rustc_errors::SubdiagnosticMessage::attr(#fluent_attr_identifier)
+                rustc_errors::fluent::#fluent_attr_identifier
             );
         }
     }
 
     /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug
     /// and `fluent_attr_identifier`.
-    fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: &str) -> TokenStream {
+    fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream {
         let diag = &self.diag;
         quote! {
-            #diag.#kind(rustc_errors::SubdiagnosticMessage::attr(#fluent_attr_identifier));
+            #diag.#kind(rustc_errors::fluent::#fluent_attr_identifier);
         }
     }
 
@@ -569,7 +669,8 @@ impl SessionDiagnosticDeriveBuilder {
                         } else {
                             throw_span_err!(
                                 info.span.unwrap(),
-                                "type of field annotated with `#[suggestion(...)]` contains more than one `Span`"
+                                "type of field annotated with `#[suggestion(...)]` contains more \
+                                 than one `Span`"
                             );
                         }
                     } else if type_matches_path(elem, &["rustc_errors", "Applicability"]) {
@@ -578,7 +679,8 @@ impl SessionDiagnosticDeriveBuilder {
                         } else {
                             throw_span_err!(
                                 info.span.unwrap(),
-                                "type of field annotated with `#[suggestion(...)]` contains more than one Applicability"
+                                "type of field annotated with `#[suggestion(...)]` contains more \
+                                 than one Applicability"
                             );
                         }
                     }
@@ -595,12 +697,18 @@ impl SessionDiagnosticDeriveBuilder {
                 }
 
                 throw_span_err!(info.span.unwrap(), "wrong types for suggestion", |diag| {
-                    diag.help("`#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`")
+                    diag.help(
+                        "`#[suggestion(...)]` on a tuple field must be applied to fields of type \
+                         `(Span, Applicability)`",
+                    )
                 });
             }
             // If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error.
             _ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| {
-                diag.help("`#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`")
+                diag.help(
+                    "`#[suggestion(...)]` should be applied to fields of type `Span` or \
+                     `(Span, Applicability)`",
+                )
             }),
         }
     }
diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs
index fd1dc2f307397..d088402abc6da 100644
--- a/compiler/rustc_macros/src/diagnostics/error.rs
+++ b/compiler/rustc_macros/src/diagnostics/error.rs
@@ -39,6 +39,19 @@ pub(crate) fn _throw_err(
     SessionDiagnosticDeriveError::ErrorHandled
 }
 
+/// Helper function for printing `syn::Path` - doesn't handle arguments in paths and these are
+/// unlikely to come up much in use of the macro.
+fn path_to_string(path: &syn::Path) -> String {
+    let mut out = String::new();
+    for (i, segment) in path.segments.iter().enumerate() {
+        if i > 0 || path.leading_colon.is_some() {
+            out.push_str("::");
+        }
+        out.push_str(&segment.ident.to_string());
+    }
+    out
+}
+
 /// Returns an error diagnostic on span `span` with msg `msg`.
 pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic {
     Diagnostic::spanned(span, Level::Error, msg)
@@ -61,15 +74,13 @@ pub(crate) use throw_span_err;
 /// Returns an error diagnostic for an invalid attribute.
 pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic {
     let span = attr.span().unwrap();
-    let name = attr.path.segments.last().unwrap().ident.to_string();
-    let name = name.as_str();
-
+    let path = path_to_string(&attr.path);
     match meta {
-        Meta::Path(_) => span_err(span, &format!("`#[{}]` is not a valid attribute", name)),
+        Meta::Path(_) => span_err(span, &format!("`#[{}]` is not a valid attribute", path)),
         Meta::NameValue(_) => {
-            span_err(span, &format!("`#[{} = ...]` is not a valid attribute", name))
+            span_err(span, &format!("`#[{} = ...]` is not a valid attribute", path))
         }
-        Meta::List(_) => span_err(span, &format!("`#[{}(...)]` is not a valid attribute", name)),
+        Meta::List(_) => span_err(span, &format!("`#[{}(...)]` is not a valid attribute", path)),
     }
 }
 
@@ -101,18 +112,16 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag
     };
 
     let span = meta.span().unwrap();
-    let nested_name = meta.path().segments.last().unwrap().ident.to_string();
-    let nested_name = nested_name.as_str();
+    let path = path_to_string(meta.path());
     match meta {
-        Meta::NameValue(..) => span_err(
-            span,
-            &format!("`#[{}({} = ...)]` is not a valid attribute", name, nested_name),
-        ),
+        Meta::NameValue(..) => {
+            span_err(span, &format!("`#[{}({} = ...)]` is not a valid attribute", name, path))
+        }
         Meta::Path(..) => {
-            span_err(span, &format!("`#[{}({})]` is not a valid attribute", name, nested_name))
+            span_err(span, &format!("`#[{}({})]` is not a valid attribute", name, path))
         }
         Meta::List(..) => {
-            span_err(span, &format!("`#[{}({}(...))]` is not a valid attribute", name, nested_name))
+            span_err(span, &format!("`#[{}({}(...))]` is not a valid attribute", name, path))
         }
     }
 }
diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs
index 42a9bf477a41c..2317186e65502 100644
--- a/compiler/rustc_macros/src/diagnostics/fluent.rs
+++ b/compiler/rustc_macros/src/diagnostics/fluent.rs
@@ -254,6 +254,17 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
             ];
 
             #generated
+
+            pub mod _subdiag {
+                pub const note: crate::SubdiagnosticMessage =
+                    crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note"));
+                pub const help: crate::SubdiagnosticMessage =
+                    crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help"));
+                pub const label: crate::SubdiagnosticMessage =
+                    crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label"));
+                pub const suggestion: crate::SubdiagnosticMessage =
+                    crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion"));
+            }
         }
     }
     .into()
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index 69573d904d4a9..2eee4bfb5dd45 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -22,14 +22,14 @@ use synstructure::Structure;
 /// # extern crate rust_middle;
 /// # use rustc_middle::ty::Ty;
 /// #[derive(SessionDiagnostic)]
-/// #[error(code = "E0505", slug = "borrowck-move-out-of-borrow")]
+/// #[error(borrowck::move_out_of_borrow, code = "E0505")]
 /// pub struct MoveOutOfBorrowError<'tcx> {
 ///     pub name: Ident,
 ///     pub ty: Ty<'tcx>,
 ///     #[primary_span]
 ///     #[label]
 ///     pub span: Span,
-///     #[label = "first-borrow-label"]
+///     #[label(borrowck::first_borrow_label)]
 ///     pub first_borrow_span: Span,
 ///     #[suggestion(code = "{name}.clone()")]
 ///     pub clone_sugg: Option<(Span, Applicability)>
@@ -72,12 +72,12 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
 /// ```ignore (rust)
 /// #[derive(SessionSubdiagnostic)]
 /// pub enum ExpectedIdentifierLabel<'tcx> {
-///     #[label(slug = "parser-expected-identifier")]
+///     #[label(parser::expected_identifier)]
 ///     WithoutFound {
 ///         #[primary_span]
 ///         span: Span,
 ///     }
-///     #[label(slug = "parser-expected-identifier-found")]
+///     #[label(parser::expected_identifier_found)]
 ///     WithFound {
 ///         #[primary_span]
 ///         span: Span,
@@ -86,7 +86,7 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
 /// }
 ///
 /// #[derive(SessionSubdiagnostic)]
-/// #[suggestion_verbose(slug = "parser-raw-identifier")]
+/// #[suggestion_verbose(parser::raw_identifier)]
 /// pub struct RawIdentifierSuggestion<'tcx> {
 ///     #[primary_span]
 ///     span: Span,
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 9aeb484bfd52d..eab954a9c1bf9 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -13,7 +13,7 @@ use quote::{format_ident, quote};
 use std::collections::HashMap;
 use std::fmt;
 use std::str::FromStr;
-use syn::{spanned::Spanned, Meta, MetaList, MetaNameValue};
+use syn::{parse_quote, spanned::Spanned, Meta, MetaList, MetaNameValue, NestedMeta, Path};
 use synstructure::{BindingInfo, Structure, VariantInfo};
 
 /// Which kind of suggestion is being created?
@@ -194,8 +194,8 @@ struct SessionSubdiagnosticDeriveBuilder<'a> {
     kind: Option<(SubdiagnosticKind, proc_macro::Span)>,
 
     /// Slug of the subdiagnostic - corresponds to the Fluent identifier for the message - from the
-    /// `#[kind(slug = "...")]` attribute on the type or variant.
-    slug: Option<(String, proc_macro::Span)>,
+    /// `#[kind(slug)]` attribute on the type or variant.
+    slug: Option<(Path, proc_macro::Span)>,
     /// If a suggestion, the code to suggest as a replacement - from the `#[kind(code = "...")]`
     /// attribute on the type or variant.
     code: Option<(TokenStream, proc_macro::Span)>,
@@ -224,9 +224,34 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
             let meta = attr.parse_meta()?;
             let kind = match meta {
                 Meta::List(MetaList { ref nested, .. }) => {
-                    for nested_attr in nested {
+                    let mut nested_iter = nested.into_iter();
+                    if let Some(nested_attr) = nested_iter.next() {
+                        match nested_attr {
+                            NestedMeta::Meta(Meta::Path(path)) => {
+                                self.slug.set_once((path.clone(), span));
+                            }
+                            NestedMeta::Meta(meta @ Meta::NameValue(_))
+                                if matches!(
+                                    meta.path().segments.last().unwrap().ident.to_string().as_str(),
+                                    "code" | "applicability"
+                                ) =>
+                            {
+                                // don't error for valid follow-up attributes
+                            }
+                            nested_attr => {
+                                throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+                                    diag.help(
+                                        "first argument of the attribute should be the diagnostic \
+                                         slug",
+                                    )
+                                })
+                            }
+                        };
+                    }
+
+                    for nested_attr in nested_iter {
                         let meta = match nested_attr {
-                            syn::NestedMeta::Meta(ref meta) => meta,
+                            NestedMeta::Meta(ref meta) => meta,
                             _ => throw_invalid_nested_attr!(attr, &nested_attr),
                         };
 
@@ -241,7 +266,6 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
                                         let formatted_str = self.build_format(&s.value(), s.span());
                                         self.code.set_once((formatted_str, span));
                                     }
-                                    "slug" => self.slug.set_once((s.value(), span)),
                                     "applicability" => {
                                         let value = match Applicability::from_str(&s.value()) {
                                             Ok(v) => v,
@@ -253,11 +277,23 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
                                         self.applicability.set_once((quote! { #value }, span));
                                     }
                                     _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
-                                        diag.help("only `code`, `slug` and `applicability` are valid nested attributes")
+                                        diag.help(
+                                            "only `code` and `applicability` are valid nested \
+                                             attributes",
+                                        )
                                     }),
                                 }
                             }
-                            _ => throw_invalid_nested_attr!(attr, &nested_attr),
+                            _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+                                if matches!(meta, Meta::Path(_)) {
+                                    diag.help(
+                                        "a diagnostic slug must be the first argument to the \
+                                         attribute",
+                                    )
+                                } else {
+                                    diag
+                                }
+                            }),
                         }
                     }
 
@@ -281,10 +317,27 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
                 );
             }
 
+            if matches!(
+                kind,
+                SubdiagnosticKind::Label | SubdiagnosticKind::Help | SubdiagnosticKind::Note
+            ) && self.applicability.is_some()
+            {
+                throw_span_err!(
+                    span,
+                    &format!(
+                        "`applicability` is not a valid nested attribute of a `{}` attribute",
+                        name
+                    )
+                );
+            }
+
             if self.slug.is_none() {
                 throw_span_err!(
                     span,
-                    &format!("`slug` must be set in a `#[{}(...)]` attribute", name)
+                    &format!(
+                        "diagnostic slug must be first argument of a `#[{}(...)]` attribute",
+                        name
+                    )
                 );
             }
 
@@ -335,7 +388,10 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
                         return Ok(quote! {});
                     }
                     _ => throw_invalid_attr!(attr, &meta, |diag| {
-                        diag.help("only `primary_span`, `applicability` and `skip_arg` are valid field attributes")
+                        diag.help(
+                            "only `primary_span`, `applicability` and `skip_arg` are valid field \
+                             attributes",
+                        )
                     }),
                 },
                 _ => throw_invalid_attr!(attr, &meta),
@@ -375,7 +431,11 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
         }
 
         // Missing slug errors will already have been reported.
-        let slug = self.slug.as_ref().map(|(slug, _)| &**slug).unwrap_or("missing-slug");
+        let slug = self
+            .slug
+            .as_ref()
+            .map(|(slug, _)| slug.clone())
+            .unwrap_or_else(|| parse_quote! { you::need::to::specify::a::slug });
         let code = match self.code.as_ref() {
             Some((code, _)) => Some(quote! { #code }),
             None if is_suggestion => {
@@ -397,7 +457,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
 
         let diag = &self.diag;
         let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
-        let message = quote! { rustc_errors::SubdiagnosticMessage::message(#slug) };
+        let message = quote! { rustc_errors::fluent::#slug };
         let call = if matches!(kind, SubdiagnosticKind::Suggestion(..)) {
             if let Some(span) = span_field {
                 quote! { #diag.#name(#span, #message, #code, #applicability); }
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index f3bdd63ee6dd4..113af328a91fa 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(let_chains)]
 #![feature(let_else)]
 #![feature(never_type)]
+#![feature(rustc_attrs)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index ba325d704228d..0869ed65ad2f3 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -244,7 +244,7 @@ impl MultiSugg {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "parser-maybe-report-ambiguous-plus")]
+#[error(parser::maybe_report_ambiguous_plus)]
 struct AmbiguousPlus {
     pub sum_ty: String,
     #[primary_span]
@@ -253,7 +253,7 @@ struct AmbiguousPlus {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0178", slug = "parser-maybe-recover-from-bad-type-plus")]
+#[error(parser::maybe_recover_from_bad_type_plus, code = "E0178")]
 struct BadTypePlus {
     pub ty: String,
     #[primary_span]
@@ -265,7 +265,7 @@ struct BadTypePlus {
 #[derive(SessionSubdiagnostic)]
 pub enum BadTypePlusSub {
     #[suggestion(
-        slug = "parser-add-paren",
+        parser::add_paren,
         code = "{sum_with_parens}",
         applicability = "machine-applicable"
     )]
@@ -274,12 +274,12 @@ pub enum BadTypePlusSub {
         #[primary_span]
         span: Span,
     },
-    #[label(slug = "parser-forgot-paren")]
+    #[label(parser::forgot_paren)]
     ForgotParen {
         #[primary_span]
         span: Span,
     },
-    #[label(slug = "parser-expect-path")]
+    #[label(parser::expect_path)]
     ExpectPath {
         #[primary_span]
         span: Span,
@@ -287,7 +287,7 @@ pub enum BadTypePlusSub {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "parser-maybe-recover-from-bad-qpath-stage-2")]
+#[error(parser::maybe_recover_from_bad_qpath_stage_2)]
 struct BadQPathStage2 {
     #[primary_span]
     #[suggestion(applicability = "maybe-incorrect")]
@@ -296,7 +296,7 @@ struct BadQPathStage2 {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "parser-incorrect-semicolon")]
+#[error(parser::incorrect_semicolon)]
 struct IncorrectSemicolon<'a> {
     #[primary_span]
     #[suggestion_short(applicability = "machine-applicable")]
@@ -307,26 +307,26 @@ struct IncorrectSemicolon<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "parser-incorrect-use-of-await")]
+#[error(parser::incorrect_use_of_await)]
 struct IncorrectUseOfAwait {
     #[primary_span]
-    #[suggestion(message = "parentheses-suggestion", applicability = "machine-applicable")]
+    #[suggestion(parser::parentheses_suggestion, applicability = "machine-applicable")]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "parser-incorrect-use-of-await")]
+#[error(parser::incorrect_use_of_await)]
 struct IncorrectAwait {
     #[primary_span]
     span: Span,
-    #[suggestion(message = "postfix-suggestion", code = "{expr}.await{question_mark}")]
+    #[suggestion(parser::postfix_suggestion, code = "{expr}.await{question_mark}")]
     sugg_span: (Span, Applicability),
     expr: String,
     question_mark: &'static str,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "parser-in-in-typo")]
+#[error(parser::in_in_typo)]
 struct InInTypo {
     #[primary_span]
     span: Span,
@@ -357,6 +357,7 @@ impl<'a> DerefMut for SnapshotParser<'a> {
 }
 
 impl<'a> Parser<'a> {
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub(super) fn span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -365,6 +366,7 @@ impl<'a> Parser<'a> {
         err.span_err(sp, self.diagnostic())
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 81bab0e3513c9..2c43563b10474 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -7,6 +7,7 @@ use super::{
 };
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
+use core::mem;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::Spacing;
@@ -26,7 +27,6 @@ use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::source_map::{self, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Pos};
-use std::mem;
 
 /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
 /// dropped into the token stream, which happens while parsing the result of
@@ -2343,7 +2343,9 @@ impl<'a> Parser<'a> {
 
     /// Parses the condition of a `if` or `while` expression.
     fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
-        let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
+        let cond = self.with_let_management(true, |local_self| {
+            local_self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)
+        })?;
 
         if let ExprKind::Let(..) = cond.kind {
             // Remove the last feature gating of a `let` expression since it's stable.
@@ -2356,6 +2358,13 @@ impl<'a> Parser<'a> {
     /// Parses a `let $pat = $expr` pseudo-expression.
     /// The `let` token has already been eaten.
     fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        if !self.let_expr_allowed {
+            self.struct_span_err(
+                self.prev_token.span,
+                "expected expression, found `let` statement",
+            )
+            .emit();
+        }
         let lo = self.prev_token.span;
         let pat = self.parse_pat_allow_top_alt(
             None,
@@ -2672,6 +2681,8 @@ impl<'a> Parser<'a> {
     }
 
     pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
+        // Used to check the `let_chains` and `if_let_guard` features mostly by scaning
+        // `&&` tokens.
         fn check_let_expr(expr: &Expr) -> (bool, bool) {
             match expr.kind {
                 ExprKind::Binary(_, ref lhs, ref rhs) => {
@@ -2694,7 +2705,7 @@ impl<'a> Parser<'a> {
             )?;
             let guard = if this.eat_keyword(kw::If) {
                 let if_span = this.prev_token.span;
-                let cond = this.parse_expr()?;
+                let cond = this.with_let_management(true, |local_this| local_this.parse_expr())?;
                 let (has_let_expr, does_not_have_bin_op) = check_let_expr(&cond);
                 if has_let_expr {
                     if does_not_have_bin_op {
@@ -3256,4 +3267,17 @@ impl<'a> Parser<'a> {
             Ok((res, trailing))
         })
     }
+
+    // Calls `f` with the internal `let_expr_allowed` set to `let_expr_allowed` and then
+    // sets the internal `let_expr_allowed` back to its original value.
+    fn with_let_management<T>(
+        &mut self,
+        let_expr_allowed: bool,
+        f: impl FnOnce(&mut Self) -> T,
+    ) -> T {
+        let last_let_expr_allowed = mem::replace(&mut self.let_expr_allowed, let_expr_allowed);
+        let rslt = f(self);
+        self.let_expr_allowed = last_let_expr_allowed;
+        rslt
+    }
 }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 6d6667717f0a3..acdf121522ad9 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -147,12 +147,15 @@ pub struct Parser<'a> {
     /// This allows us to recover when the user forget to add braces around
     /// multiple statements in the closure body.
     pub current_closure: Option<ClosureSpans>,
+    /// Used to track where `let`s are allowed. For example, `if true && let 1 = 1` is valid
+    /// but `[1, 2, 3][let _ = ()]` is not.
+    let_expr_allowed: bool,
 }
 
 // This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure
 // it doesn't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Parser<'_>, 328);
+rustc_data_structures::static_assert_size!(Parser<'_>, 336);
 
 /// Stores span information about a closure.
 #[derive(Clone)]
@@ -455,6 +458,7 @@ impl<'a> Parser<'a> {
                 inner_attr_ranges: Default::default(),
             },
             current_closure: None,
+            let_expr_allowed: false,
         };
 
         // Make parser point to the first token.
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index d952e288a6477..5785921fb1eda 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -4,14 +4,15 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-rustc_middle = { path = "../rustc_middle" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
+rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
-rustc_typeck = { path = "../rustc_typeck" }
+rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
+rustc_typeck = { path = "../rustc_typeck" }
 tracing = "0.1"
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
new file mode 100644
index 0000000000000..f33efc7f6ab7b
--- /dev/null
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -0,0 +1,75 @@
+use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_span::{Span, Symbol};
+
+#[derive(SessionDiagnostic)]
+#[error(code = "E0451", slug = "privacy-field-is-private")]
+pub struct FieldIsPrivate {
+    #[primary_span]
+    pub span: Span,
+    pub field_name: Symbol,
+    pub variant_descr: &'static str,
+    pub def_path_str: String,
+    #[subdiagnostic]
+    pub label: FieldIsPrivateLabel,
+}
+
+#[derive(SessionSubdiagnostic)]
+pub enum FieldIsPrivateLabel {
+    #[label(slug = "privacy-field-is-private-is-update-syntax-label")]
+    IsUpdateSyntax {
+        #[primary_span]
+        span: Span,
+        field_name: Symbol,
+    },
+    #[label(slug = "privacy-field-is-private-label")]
+    Other {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(SessionDiagnostic)]
+#[error(slug = "privacy-item-is-private")]
+pub struct ItemIsPrivate<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub kind: &'a str,
+    pub descr: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(slug = "privacy-unnamed-item-is-private")]
+pub struct UnnamedItemIsPrivate {
+    #[primary_span]
+    pub span: Span,
+    pub kind: &'static str,
+}
+
+// Duplicate of `InPublicInterface` but with a different error code, shares the same slug.
+#[derive(SessionDiagnostic)]
+#[error(code = "E0445", slug = "privacy-in-public-interface")]
+pub struct InPublicInterfaceTraits<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub vis_descr: &'static str,
+    pub kind: &'a str,
+    pub descr: String,
+    #[label = "visibility-label"]
+    pub vis_span: Span,
+}
+
+// Duplicate of `InPublicInterfaceTraits` but with a different error code, shares the same slug.
+#[derive(SessionDiagnostic)]
+#[error(code = "E0446", slug = "privacy-in-public-interface")]
+pub struct InPublicInterface<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub vis_descr: &'static str,
+    pub kind: &'a str,
+    pub descr: String,
+    #[label = "visibility-label"]
+    pub vis_span: Span,
+}
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index b27c986d0f9da..238c917bbc33f 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1,15 +1,19 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(associated_type_defaults)]
 #![feature(control_flow_enum)]
+#![feature(rustc_private)]
 #![feature(try_blocks)]
-#![feature(associated_type_defaults)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
+#![cfg_attr(not(bootstrap), deny(rustc::untranslatable_diagnostic))]
+#![cfg_attr(not(bootstrap), deny(rustc::diagnostic_outside_of_impl))]
+
+mod errors;
 
 use rustc_ast::MacroDef;
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::intern::Interned;
-use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
@@ -34,6 +38,11 @@ use std::marker::PhantomData;
 use std::ops::ControlFlow;
 use std::{cmp, fmt, mem};
 
+use errors::{
+    FieldIsPrivate, FieldIsPrivateLabel, InPublicInterface, InPublicInterfaceTraits, ItemIsPrivate,
+    UnnamedItemIsPrivate,
+};
+
 ////////////////////////////////////////////////////////////////////////////////
 /// Generic infrastructure used to implement specific visitors below.
 ////////////////////////////////////////////////////////////////////////////////
@@ -935,23 +944,17 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
         let hir_id = self.tcx.hir().local_def_id_to_hir_id(self.current_item);
         let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1;
         if !field.vis.is_accessible_from(def_id, self.tcx) {
-            let label = if in_update_syntax {
-                format!("field `{}` is private", field.name)
-            } else {
-                "private field".to_string()
-            };
-
-            struct_span_err!(
-                self.tcx.sess,
+            self.tcx.sess.emit_err(FieldIsPrivate {
                 span,
-                E0451,
-                "field `{}` of {} `{}` is private",
-                field.name,
-                def.variant_descr(),
-                self.tcx.def_path_str(def.did())
-            )
-            .span_label(span, label)
-            .emit();
+                field_name: field.name,
+                variant_descr: def.variant_descr(),
+                def_path_str: self.tcx.def_path_str(def.did()),
+                label: if in_update_syntax {
+                    FieldIsPrivateLabel::IsUpdateSyntax { span, field_name: field.name }
+                } else {
+                    FieldIsPrivateLabel::Other { span }
+                },
+            });
         }
     }
 }
@@ -1075,11 +1078,11 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
     fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
         let is_error = !self.item_is_accessible(def_id);
         if is_error {
-            self.tcx
-                .sess
-                .struct_span_err(self.span, &format!("{} `{}` is private", kind, descr))
-                .span_label(self.span, &format!("private {}", kind))
-                .emit();
+            self.tcx.sess.emit_err(ItemIsPrivate {
+                span: self.span,
+                kind,
+                descr: descr.to_string(),
+            });
         }
         is_error
     }
@@ -1250,13 +1253,10 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
                     hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
                 };
                 let kind = kind.descr(def_id);
-                let msg = match name {
-                    Some(name) => format!("{} `{}` is private", kind, name),
-                    None => format!("{} is private", kind),
+                let _ = match name {
+                    Some(name) => sess.emit_err(ItemIsPrivate { span, kind, descr: name }),
+                    None => sess.emit_err(UnnamedItemIsPrivate { span, kind }),
                 };
-                sess.struct_span_err(span, &msg)
-                    .span_label(span, &format!("private {}", kind))
-                    .emit();
                 return;
             }
         }
@@ -1753,22 +1753,31 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
                     }
                 }
             };
-            let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr);
             let span = self.tcx.def_span(self.item_def_id.to_def_id());
             if self.has_old_errors
                 || self.in_assoc_ty
                 || self.tcx.resolutions(()).has_pub_restricted
             {
-                let mut err = if kind == "trait" {
-                    struct_span_err!(self.tcx.sess, span, E0445, "{}", make_msg())
-                } else {
-                    struct_span_err!(self.tcx.sess, span, E0446, "{}", make_msg())
-                };
+                let descr = descr.to_string();
                 let vis_span =
                     self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id));
-                err.span_label(span, format!("can't leak {} {}", vis_descr, kind));
-                err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr));
-                err.emit();
+                if kind == "trait" {
+                    self.tcx.sess.emit_err(InPublicInterfaceTraits {
+                        span,
+                        vis_descr,
+                        kind,
+                        descr,
+                        vis_span,
+                    });
+                } else {
+                    self.tcx.sess.emit_err(InPublicInterface {
+                        span,
+                        vis_descr,
+                        kind,
+                        descr,
+                        vis_span,
+                    });
+                }
             } else {
                 let err_code = if kind == "trait" { "E0445" } else { "E0446" };
                 self.tcx.struct_span_lint_hir(
@@ -1776,7 +1785,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
                     hir_id,
                     span,
                     |lint| {
-                        lint.build(&format!("{} (error {})", make_msg(), err_code)).emit();
+                        lint.build(&format!(
+                            "{} (error {})",
+                            format!("{} {} `{}` in public interface", vis_descr, kind, descr),
+                            err_code
+                        ))
+                        .emit();
                     },
                 );
             }
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index f1814eebfa6fd..b5058fd699aca 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -280,6 +280,7 @@ impl Session {
         self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_warn<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -287,6 +288,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_span_warn(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -295,6 +297,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_span_warn_with_expectation(sp, msg, id)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -303,9 +306,11 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_span_warn_with_code(sp, msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_warn(msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_warn_with_expectation(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -313,6 +318,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_warn_with_expectation(msg, id)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_allow<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -320,9 +326,11 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_span_allow(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_allow(msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_expect(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -330,6 +338,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_expect(msg, id)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -337,6 +346,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         self.diagnostic().struct_span_err(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -346,12 +356,14 @@ impl Session {
         self.diagnostic().struct_span_err_with_code(sp, msg, code)
     }
     // FIXME: This method should be removed (every error should have an associated error code).
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_err(
         &self,
         msg: impl Into<DiagnosticMessage>,
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         self.parse_sess.struct_err(msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_err_with_code(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -359,6 +371,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         self.diagnostic().struct_err_with_code(msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_warn_with_code(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -366,6 +379,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_warn_with_code(msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_fatal<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -373,6 +387,7 @@ impl Session {
     ) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_span_fatal(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -381,13 +396,16 @@ impl Session {
     ) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_fatal(msg)
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
         self.diagnostic().span_fatal(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_fatal_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -396,9 +414,11 @@ impl Session {
     ) -> ! {
         self.diagnostic().span_fatal_with_code(sp, msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! {
         self.diagnostic().fatal(msg).raise()
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_err_or_warn<S: Into<MultiSpan>>(
         &self,
         is_warning: bool,
@@ -411,6 +431,7 @@ impl Session {
             self.span_err(sp, msg);
         }
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -418,6 +439,7 @@ impl Session {
     ) -> ErrorGuaranteed {
         self.diagnostic().span_err(sp, msg)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_err_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -426,6 +448,7 @@ impl Session {
     ) {
         self.diagnostic().span_err_with_code(sp, msg, code)
     }
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
         self.diagnostic().err(msg)
     }
diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs
index 67a3d4a4d020c..4cdec615d8290 100644
--- a/compiler/rustc_typeck/src/errors.rs
+++ b/compiler/rustc_typeck/src/errors.rs
@@ -6,18 +6,18 @@ use rustc_session::{parse::ParseSess, SessionDiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0062", slug = "typeck-field-multiply-specified-in-initializer")]
+#[error(typeck::field_multiply_specified_in_initializer, code = "E0062")]
 pub struct FieldMultiplySpecifiedInInitializer {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label = "previous-use-label"]
+    #[label(typeck::previous_use_label)]
     pub prev_span: Span,
     pub ident: Ident,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0092", slug = "typeck-unrecognized-atomic-operation")]
+#[error(typeck::unrecognized_atomic_operation, code = "E0092")]
 pub struct UnrecognizedAtomicOperation<'a> {
     #[primary_span]
     #[label]
@@ -26,7 +26,7 @@ pub struct UnrecognizedAtomicOperation<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0094", slug = "typeck-wrong-number-of-generic-arguments-to-intrinsic")]
+#[error(typeck::wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
 pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
     #[primary_span]
     #[label]
@@ -37,7 +37,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0093", slug = "typeck-unrecognized-intrinsic-function")]
+#[error(typeck::unrecognized_intrinsic_function, code = "E0093")]
 pub struct UnrecognizedIntrinsicFunction {
     #[primary_span]
     #[label]
@@ -46,19 +46,19 @@ pub struct UnrecognizedIntrinsicFunction {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0195", slug = "typeck-lifetimes-or-bounds-mismatch-on-trait")]
+#[error(typeck::lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
 pub struct LifetimesOrBoundsMismatchOnTrait {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label = "generics-label"]
+    #[label(typeck::generics_label)]
     pub generics_span: Option<Span>,
     pub item_kind: &'static str,
     pub ident: Ident,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0120", slug = "typeck-drop-impl-on-wrong-item")]
+#[error(typeck::drop_impl_on_wrong_item, code = "E0120")]
 pub struct DropImplOnWrongItem {
     #[primary_span]
     #[label]
@@ -66,18 +66,18 @@ pub struct DropImplOnWrongItem {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0124", slug = "typeck-field-already-declared")]
+#[error(typeck::field_already_declared, code = "E0124")]
 pub struct FieldAlreadyDeclared {
     pub field_name: Ident,
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label = "previous-decl-label"]
+    #[label(typeck::previous_decl_label)]
     pub prev_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0184", slug = "typeck-copy-impl-on-type-with-dtor")]
+#[error(typeck::copy_impl_on_type_with_dtor, code = "E0184")]
 pub struct CopyImplOnTypeWithDtor {
     #[primary_span]
     #[label]
@@ -85,14 +85,14 @@ pub struct CopyImplOnTypeWithDtor {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0203", slug = "typeck-multiple-relaxed-default-bounds")]
+#[error(typeck::multiple_relaxed_default_bounds, code = "E0203")]
 pub struct MultipleRelaxedDefaultBounds {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0206", slug = "typeck-copy-impl-on-non-adt")]
+#[error(typeck::copy_impl_on_non_adt, code = "E0206")]
 pub struct CopyImplOnNonAdt {
     #[primary_span]
     #[label]
@@ -100,23 +100,23 @@ pub struct CopyImplOnNonAdt {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0224", slug = "typeck-trait-object-declared-with-no-traits")]
+#[error(typeck::trait_object_declared_with_no_traits, code = "E0224")]
 pub struct TraitObjectDeclaredWithNoTraits {
     #[primary_span]
     pub span: Span,
-    #[label = "alias-span"]
+    #[label(typeck::alias_span)]
     pub trait_alias_span: Option<Span>,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0227", slug = "typeck-ambiguous-lifetime-bound")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0227")]
 pub struct AmbiguousLifetimeBound {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0229", slug = "typeck-assoc-type-binding-not-allowed")]
+#[error(typeck::assoc_type_binding_not_allowed, code = "E0229")]
 pub struct AssocTypeBindingNotAllowed {
     #[primary_span]
     #[label]
@@ -124,14 +124,14 @@ pub struct AssocTypeBindingNotAllowed {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0436", slug = "typeck-functional-record-update-on-non-struct")]
+#[error(typeck::functional_record_update_on_non_struct, code = "E0436")]
 pub struct FunctionalRecordUpdateOnNonStruct {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0516", slug = "typeck-typeof-reserved-keyword-used")]
+#[error(typeck::typeof_reserved_keyword_used, code = "E0516")]
 pub struct TypeofReservedKeywordUsed<'tcx> {
     pub ty: Ty<'tcx>,
     #[primary_span]
@@ -142,25 +142,25 @@ pub struct TypeofReservedKeywordUsed<'tcx> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0572", slug = "typeck-return-stmt-outside-of-fn-body")]
+#[error(typeck::return_stmt_outside_of_fn_body, code = "E0572")]
 pub struct ReturnStmtOutsideOfFnBody {
     #[primary_span]
     pub span: Span,
-    #[label = "encl-body-label"]
+    #[label(typeck::encl_body_label)]
     pub encl_body_span: Option<Span>,
-    #[label = "encl-fn-label"]
+    #[label(typeck::encl_fn_label)]
     pub encl_fn_span: Option<Span>,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0627", slug = "typeck-yield-expr-outside-of-generator")]
+#[error(typeck::yield_expr_outside_of_generator, code = "E0627")]
 pub struct YieldExprOutsideOfGenerator {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0639", slug = "typeck-struct-expr-non-exhaustive")]
+#[error(typeck::struct_expr_non_exhaustive, code = "E0639")]
 pub struct StructExprNonExhaustive {
     #[primary_span]
     pub span: Span,
@@ -168,26 +168,26 @@ pub struct StructExprNonExhaustive {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0699", slug = "typeck-method-call-on-unknown-type")]
+#[error(typeck::method_call_on_unknown_type, code = "E0699")]
 pub struct MethodCallOnUnknownType {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0719", slug = "typeck-value-of-associated-struct-already-specified")]
+#[error(typeck::value_of_associated_struct_already_specified, code = "E0719")]
 pub struct ValueOfAssociatedStructAlreadySpecified {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label = "previous-bound-label"]
+    #[label(typeck::previous_bound_label)]
     pub prev_span: Span,
     pub item_name: Ident,
     pub def_path: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0745", slug = "typeck-address-of-temporary-taken")]
+#[error(typeck::address_of_temporary_taken, code = "E0745")]
 pub struct AddressOfTemporaryTaken {
     #[primary_span]
     #[label]
@@ -197,7 +197,7 @@ pub struct AddressOfTemporaryTaken {
 #[derive(SessionSubdiagnostic)]
 pub enum AddReturnTypeSuggestion<'tcx> {
     #[suggestion(
-        slug = "typeck-add-return-type-add",
+        typeck::add_return_type_add,
         code = "-> {found} ",
         applicability = "machine-applicable"
     )]
@@ -207,7 +207,7 @@ pub enum AddReturnTypeSuggestion<'tcx> {
         found: Ty<'tcx>,
     },
     #[suggestion(
-        slug = "typeck-add-return-type-missing-here",
+        typeck::add_return_type_missing_here,
         code = "-> _ ",
         applicability = "has-placeholders"
     )]
@@ -219,12 +219,12 @@ pub enum AddReturnTypeSuggestion<'tcx> {
 
 #[derive(SessionSubdiagnostic)]
 pub enum ExpectedReturnTypeLabel<'tcx> {
-    #[label(slug = "typeck-expected-default-return-type")]
+    #[label(typeck::expected_default_return_type)]
     Unit {
         #[primary_span]
         span: Span,
     },
-    #[label(slug = "typeck-expected-return-type")]
+    #[label(typeck::expected_return_type)]
     Other {
         #[primary_span]
         span: Span,
@@ -233,7 +233,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "typeck-unconstrained-opaque-type")]
+#[error(typeck::unconstrained_opaque_type)]
 #[note]
 pub struct UnconstrainedOpaqueType {
     #[primary_span]
@@ -301,7 +301,7 @@ impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0183", slug = "typeck-manual-implementation")]
+#[error(typeck::manual_implementation, code = "E0183")]
 #[help]
 pub struct ManualImplementation {
     #[primary_span]
@@ -311,7 +311,7 @@ pub struct ManualImplementation {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "typeck-substs-on-overridden-impl")]
+#[error(typeck::substs_on_overridden_impl)]
 pub struct SubstsOnOverriddenImpl {
     #[primary_span]
     pub span: Span,
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 2f9afbec91e98..b144fef7a9693 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -70,6 +70,214 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     unsafe { crate::ptr::drop_in_place(to_drop) }
 }
 
+// These have been renamed.
+#[cfg(bootstrap)]
+extern "rust-intrinsic" {
+    pub fn atomic_cxchg<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_acq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_rel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_acqrel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_failacq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_acq_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_acqrel_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_acq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_rel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_acqrel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_failacq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_acq_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_acqrel_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_load<T: Copy>(src: *const T) -> T;
+    pub fn atomic_load_acq<T: Copy>(src: *const T) -> T;
+    pub fn atomic_load_relaxed<T: Copy>(src: *const T) -> T;
+    pub fn atomic_load_unordered<T: Copy>(src: *const T) -> T;
+    pub fn atomic_store<T: Copy>(dst: *mut T, val: T);
+    pub fn atomic_store_rel<T: Copy>(dst: *mut T, val: T);
+    pub fn atomic_store_relaxed<T: Copy>(dst: *mut T, val: T);
+    pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
+    pub fn atomic_xchg<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xchg_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xchg_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xchg_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xchg_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xadd<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xadd_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xadd_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xadd_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xadd_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xsub<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xsub_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xsub_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xsub_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xsub_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_and<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_and_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_and_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_and_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_and_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_nand<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_nand_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_nand_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_nand_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_nand_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_or<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_or_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_or_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_or_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_or_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xor<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xor_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xor_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xor_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xor_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_max<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_max_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_max_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_max_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_max_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_min<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_min_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_min_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_min_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_min_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umin<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umin_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umin_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umin_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umin_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umax<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umax_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umax_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umax_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umax_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_fence();
+    pub fn atomic_fence_acq();
+    pub fn atomic_fence_rel();
+    pub fn atomic_fence_acqrel();
+    pub fn atomic_singlethreadfence();
+    pub fn atomic_singlethreadfence_acq();
+    pub fn atomic_singlethreadfence_rel();
+    pub fn atomic_singlethreadfence_acqrel();
+}
+
+// These have been renamed.
+#[cfg(bootstrap)]
+mod atomics {
+    pub use super::atomic_cxchg as atomic_cxchg_seqcst_seqcst;
+    pub use super::atomic_cxchg_acq as atomic_cxchg_acquire_acquire;
+    pub use super::atomic_cxchg_acq_failrelaxed as atomic_cxchg_acquire_relaxed;
+    pub use super::atomic_cxchg_acqrel as atomic_cxchg_acqrel_acquire;
+    pub use super::atomic_cxchg_acqrel_failrelaxed as atomic_cxchg_acqrel_relaxed;
+    pub use super::atomic_cxchg_failacq as atomic_cxchg_seqcst_acquire;
+    pub use super::atomic_cxchg_failrelaxed as atomic_cxchg_seqcst_relaxed;
+    pub use super::atomic_cxchg_rel as atomic_cxchg_release_relaxed;
+    pub use super::atomic_cxchg_relaxed as atomic_cxchg_relaxed_relaxed;
+
+    pub use super::atomic_cxchgweak as atomic_cxchgweak_seqcst_seqcst;
+    pub use super::atomic_cxchgweak_acq as atomic_cxchgweak_acquire_acquire;
+    pub use super::atomic_cxchgweak_acq_failrelaxed as atomic_cxchgweak_acquire_relaxed;
+    pub use super::atomic_cxchgweak_acqrel as atomic_cxchgweak_acqrel_acquire;
+    pub use super::atomic_cxchgweak_acqrel_failrelaxed as atomic_cxchgweak_acqrel_relaxed;
+    pub use super::atomic_cxchgweak_failacq as atomic_cxchgweak_seqcst_acquire;
+    pub use super::atomic_cxchgweak_failrelaxed as atomic_cxchgweak_seqcst_relaxed;
+    pub use super::atomic_cxchgweak_rel as atomic_cxchgweak_release_relaxed;
+    pub use super::atomic_cxchgweak_relaxed as atomic_cxchgweak_relaxed_relaxed;
+
+    pub use super::atomic_load as atomic_load_seqcst;
+    pub use super::atomic_load_acq as atomic_load_acquire;
+    pub use super::atomic_load_relaxed;
+    pub use super::atomic_load_unordered;
+
+    pub use super::atomic_store as atomic_store_seqcst;
+    pub use super::atomic_store_rel as atomic_store_release;
+    pub use super::atomic_store_relaxed;
+    pub use super::atomic_store_unordered;
+
+    pub use super::atomic_xchg as atomic_xchg_seqcst;
+    pub use super::atomic_xchg_acq as atomic_xchg_acquire;
+    pub use super::atomic_xchg_acqrel;
+    pub use super::atomic_xchg_rel as atomic_xchg_release;
+    pub use super::atomic_xchg_relaxed;
+
+    pub use super::atomic_xadd as atomic_xadd_seqcst;
+    pub use super::atomic_xadd_acq as atomic_xadd_acquire;
+    pub use super::atomic_xadd_acqrel;
+    pub use super::atomic_xadd_rel as atomic_xadd_release;
+    pub use super::atomic_xadd_relaxed;
+
+    pub use super::atomic_xsub as atomic_xsub_seqcst;
+    pub use super::atomic_xsub_acq as atomic_xsub_acquire;
+    pub use super::atomic_xsub_acqrel;
+    pub use super::atomic_xsub_rel as atomic_xsub_release;
+    pub use super::atomic_xsub_relaxed;
+
+    pub use super::atomic_and as atomic_and_seqcst;
+    pub use super::atomic_and_acq as atomic_and_acquire;
+    pub use super::atomic_and_acqrel;
+    pub use super::atomic_and_rel as atomic_and_release;
+    pub use super::atomic_and_relaxed;
+
+    pub use super::atomic_nand as atomic_nand_seqcst;
+    pub use super::atomic_nand_acq as atomic_nand_acquire;
+    pub use super::atomic_nand_acqrel;
+    pub use super::atomic_nand_rel as atomic_nand_release;
+    pub use super::atomic_nand_relaxed;
+
+    pub use super::atomic_or as atomic_or_seqcst;
+    pub use super::atomic_or_acq as atomic_or_acquire;
+    pub use super::atomic_or_acqrel;
+    pub use super::atomic_or_rel as atomic_or_release;
+    pub use super::atomic_or_relaxed;
+
+    pub use super::atomic_xor as atomic_xor_seqcst;
+    pub use super::atomic_xor_acq as atomic_xor_acquire;
+    pub use super::atomic_xor_acqrel;
+    pub use super::atomic_xor_rel as atomic_xor_release;
+    pub use super::atomic_xor_relaxed;
+
+    pub use super::atomic_max as atomic_max_seqcst;
+    pub use super::atomic_max_acq as atomic_max_acquire;
+    pub use super::atomic_max_acqrel;
+    pub use super::atomic_max_rel as atomic_max_release;
+    pub use super::atomic_max_relaxed;
+
+    pub use super::atomic_min as atomic_min_seqcst;
+    pub use super::atomic_min_acq as atomic_min_acquire;
+    pub use super::atomic_min_acqrel;
+    pub use super::atomic_min_rel as atomic_min_release;
+    pub use super::atomic_min_relaxed;
+
+    pub use super::atomic_umin as atomic_umin_seqcst;
+    pub use super::atomic_umin_acq as atomic_umin_acquire;
+    pub use super::atomic_umin_acqrel;
+    pub use super::atomic_umin_rel as atomic_umin_release;
+    pub use super::atomic_umin_relaxed;
+
+    pub use super::atomic_umax as atomic_umax_seqcst;
+    pub use super::atomic_umax_acq as atomic_umax_acquire;
+    pub use super::atomic_umax_acqrel;
+    pub use super::atomic_umax_rel as atomic_umax_release;
+    pub use super::atomic_umax_relaxed;
+
+    pub use super::atomic_fence as atomic_fence_seqcst;
+    pub use super::atomic_fence_acq as atomic_fence_acquire;
+    pub use super::atomic_fence_acqrel;
+    pub use super::atomic_fence_rel as atomic_fence_release;
+
+    pub use super::atomic_singlethreadfence as atomic_singlethreadfence_seqcst;
+    pub use super::atomic_singlethreadfence_acq as atomic_singlethreadfence_acquire;
+    pub use super::atomic_singlethreadfence_acqrel;
+    pub use super::atomic_singlethreadfence_rel as atomic_singlethreadfence_release;
+}
+
+#[cfg(bootstrap)]
+pub use atomics::*;
+
+#[cfg(not(bootstrap))]
 extern "rust-intrinsic" {
     // N.B., these intrinsics take raw pointers because they mutate aliased
     // memory, which is not valid for either `&` or `&mut`.
@@ -78,142 +286,226 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange` method by passing
-    /// [`Ordering::SeqCst`] as both the `success` and `failure` parameters.
+    /// [`Ordering::Relaxed`] as both the success and failure parameters.
     /// For example, [`AtomicBool::compare_exchange`].
-    pub fn atomic_cxchg<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_relaxed_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange` method by passing
-    /// [`Ordering::Acquire`] as both the `success` and `failure` parameters.
+    /// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters.
     /// For example, [`AtomicBool::compare_exchange`].
-    pub fn atomic_cxchg_acq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_relaxed_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange` method by passing
-    /// [`Ordering::Release`] as the `success` and [`Ordering::Relaxed`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
-    pub fn atomic_cxchg_rel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange` method by passing
-    /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Acquire`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
-    pub fn atomic_cxchg_acqrel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_acquire_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange` method by passing
-    /// [`Ordering::Relaxed`] as both the `success` and `failure` parameters.
+    /// [`Ordering::Acquire`] as both the success and failure parameters.
     /// For example, [`AtomicBool::compare_exchange`].
-    pub fn atomic_cxchg_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_acquire_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange` method by passing
-    /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Relaxed`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
-    pub fn atomic_cxchg_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange` method by passing
-    /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Acquire`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
-    pub fn atomic_cxchg_failacq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_release_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange` method by passing
-    /// [`Ordering::Acquire`] as the `success` and [`Ordering::Relaxed`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
-    pub fn atomic_cxchg_acq_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_release_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange` method by passing
-    /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Relaxed`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
-    pub fn atomic_cxchg_acqrel_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::SeqCst`] as both the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
+    pub fn atomic_cxchg_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange_weak` method by passing
-    /// [`Ordering::SeqCst`] as both the `success` and `failure` parameters.
+    /// [`Ordering::Relaxed`] as both the success and failure parameters.
     /// For example, [`AtomicBool::compare_exchange_weak`].
-    pub fn atomic_cxchgweak<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_relaxed_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange_weak` method by passing
-    /// [`Ordering::Acquire`] as both the `success` and `failure` parameters.
+    /// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters.
     /// For example, [`AtomicBool::compare_exchange_weak`].
-    pub fn atomic_cxchgweak_acq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_relaxed_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange_weak` method by passing
-    /// [`Ordering::Release`] as the `success` and [`Ordering::Relaxed`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
-    pub fn atomic_cxchgweak_rel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange_weak` method by passing
-    /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Acquire`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
-    pub fn atomic_cxchgweak_acqrel<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_acquire_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange_weak` method by passing
-    /// [`Ordering::Relaxed`] as both the `success` and `failure` parameters.
+    /// [`Ordering::Acquire`] as both the success and failure parameters.
     /// For example, [`AtomicBool::compare_exchange_weak`].
-    pub fn atomic_cxchgweak_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_acquire_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange_weak` method by passing
-    /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Relaxed`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
-    pub fn atomic_cxchgweak_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange_weak` method by passing
-    /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Acquire`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
-    pub fn atomic_cxchgweak_failacq<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_release_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange_weak` method by passing
-    /// [`Ordering::Acquire`] as the `success` and [`Ordering::Relaxed`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
-    pub fn atomic_cxchgweak_acq_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_release_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `compare_exchange_weak` method by passing
-    /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Relaxed`] as the
-    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
-    pub fn atomic_cxchgweak_acqrel_failrelaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+    /// Stores a value if the current value is the same as the `old` value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::SeqCst`] as both the success and failure parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
+    pub fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
 
     /// Loads the current value of the pointer.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `load` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`].
-    pub fn atomic_load<T: Copy>(src: *const T) -> T;
+    pub fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
     /// Loads the current value of the pointer.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `load` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`].
-    pub fn atomic_load_acq<T: Copy>(src: *const T) -> T;
+    pub fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
     /// Loads the current value of the pointer.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -227,13 +519,13 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `store` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::store`].
-    pub fn atomic_store<T: Copy>(dst: *mut T, val: T);
+    pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T);
     /// Stores the value at the specified memory location.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `store` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::store`].
-    pub fn atomic_store_rel<T: Copy>(dst: *mut T, val: T);
+    pub fn atomic_store_release<T: Copy>(dst: *mut T, val: T);
     /// Stores the value at the specified memory location.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -247,19 +539,19 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `swap` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::swap`].
-    pub fn atomic_xchg<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xchg_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
     /// Stores the value at the specified memory location, returning the old value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `swap` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::swap`].
-    pub fn atomic_xchg_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xchg_acquire<T: Copy>(dst: *mut T, src: T) -> T;
     /// Stores the value at the specified memory location, returning the old value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `swap` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::swap`].
-    pub fn atomic_xchg_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xchg_release<T: Copy>(dst: *mut T, src: T) -> T;
     /// Stores the value at the specified memory location, returning the old value.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -278,19 +570,19 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_add` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_add`].
-    pub fn atomic_xadd<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xadd_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
     /// Adds to the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_add` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_add`].
-    pub fn atomic_xadd_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xadd_acquire<T: Copy>(dst: *mut T, src: T) -> T;
     /// Adds to the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_add` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_add`].
-    pub fn atomic_xadd_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xadd_release<T: Copy>(dst: *mut T, src: T) -> T;
     /// Adds to the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -309,19 +601,19 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_sub` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
-    pub fn atomic_xsub<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xsub_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
     /// Subtract from the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_sub` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
-    pub fn atomic_xsub_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xsub_acquire<T: Copy>(dst: *mut T, src: T) -> T;
     /// Subtract from the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_sub` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
-    pub fn atomic_xsub_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xsub_release<T: Copy>(dst: *mut T, src: T) -> T;
     /// Subtract from the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -340,19 +632,19 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_and` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_and`].
-    pub fn atomic_and<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_and_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise and with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_and` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_and`].
-    pub fn atomic_and_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_and_acquire<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise and with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_and` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_and`].
-    pub fn atomic_and_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_and_release<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise and with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -371,19 +663,19 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`AtomicBool`] type via the `fetch_nand` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_nand`].
-    pub fn atomic_nand<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_nand_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise nand with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`AtomicBool`] type via the `fetch_nand` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_nand`].
-    pub fn atomic_nand_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_nand_acquire<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise nand with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`AtomicBool`] type via the `fetch_nand` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_nand`].
-    pub fn atomic_nand_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_nand_release<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise nand with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -402,19 +694,19 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_or` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_or`].
-    pub fn atomic_or<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_or_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise or with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_or` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_or`].
-    pub fn atomic_or_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_or_acquire<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise or with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_or` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_or`].
-    pub fn atomic_or_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_or_release<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise or with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -433,19 +725,19 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_xor` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_xor`].
-    pub fn atomic_xor<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xor_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise xor with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_xor` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_xor`].
-    pub fn atomic_xor_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xor_acquire<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise xor with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] types via the `fetch_xor` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_xor`].
-    pub fn atomic_xor_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_xor_release<T: Copy>(dst: *mut T, src: T) -> T;
     /// Bitwise xor with the current value, returning the previous value.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -464,19 +756,19 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] signed integer types via the `fetch_max` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_max`].
-    pub fn atomic_max<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_max_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
     /// Maximum with the current value using a signed comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] signed integer types via the `fetch_max` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_max`].
-    pub fn atomic_max_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_max_acquire<T: Copy>(dst: *mut T, src: T) -> T;
     /// Maximum with the current value using a signed comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] signed integer types via the `fetch_max` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_max`].
-    pub fn atomic_max_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_max_release<T: Copy>(dst: *mut T, src: T) -> T;
     /// Maximum with the current value using a signed comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -495,19 +787,19 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] signed integer types via the `fetch_min` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_min`].
-    pub fn atomic_min<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_min_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
     /// Minimum with the current value using a signed comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] signed integer types via the `fetch_min` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_min`].
-    pub fn atomic_min_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_min_acquire<T: Copy>(dst: *mut T, src: T) -> T;
     /// Minimum with the current value using a signed comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] signed integer types via the `fetch_min` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_min`].
-    pub fn atomic_min_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_min_release<T: Copy>(dst: *mut T, src: T) -> T;
     /// Minimum with the current value using a signed comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -526,19 +818,19 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_min`].
-    pub fn atomic_umin<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umin_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
     /// Minimum with the current value using an unsigned comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_min`].
-    pub fn atomic_umin_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umin_acquire<T: Copy>(dst: *mut T, src: T) -> T;
     /// Minimum with the current value using an unsigned comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_min`].
-    pub fn atomic_umin_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umin_release<T: Copy>(dst: *mut T, src: T) -> T;
     /// Minimum with the current value using an unsigned comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -557,19 +849,19 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
     /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_max`].
-    pub fn atomic_umax<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umax_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
     /// Maximum with the current value using an unsigned comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
     /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_max`].
-    pub fn atomic_umax_acq<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umax_acquire<T: Copy>(dst: *mut T, src: T) -> T;
     /// Maximum with the current value using an unsigned comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
     /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
     /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_max`].
-    pub fn atomic_umax_rel<T: Copy>(dst: *mut T, src: T) -> T;
+    pub fn atomic_umax_release<T: Copy>(dst: *mut T, src: T) -> T;
     /// Maximum with the current value using an unsigned comparison.
     ///
     /// The stabilized version of this intrinsic is available on the
@@ -583,67 +875,24 @@ extern "rust-intrinsic" {
     /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_max`].
     pub fn atomic_umax_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
-    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
-    /// if supported; otherwise, it is a no-op.
-    /// Prefetches have no effect on the behavior of the program but can change its performance
-    /// characteristics.
-    ///
-    /// The `locality` argument must be a constant integer and is a temporal locality specifier
-    /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    pub fn prefetch_read_data<T>(data: *const T, locality: i32);
-    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
-    /// if supported; otherwise, it is a no-op.
-    /// Prefetches have no effect on the behavior of the program but can change its performance
-    /// characteristics.
-    ///
-    /// The `locality` argument must be a constant integer and is a temporal locality specifier
-    /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    pub fn prefetch_write_data<T>(data: *const T, locality: i32);
-    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
-    /// if supported; otherwise, it is a no-op.
-    /// Prefetches have no effect on the behavior of the program but can change its performance
-    /// characteristics.
-    ///
-    /// The `locality` argument must be a constant integer and is a temporal locality specifier
-    /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    pub fn prefetch_read_instruction<T>(data: *const T, locality: i32);
-    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
-    /// if supported; otherwise, it is a no-op.
-    /// Prefetches have no effect on the behavior of the program but can change its performance
-    /// characteristics.
-    ///
-    /// The `locality` argument must be a constant integer and is a temporal locality specifier
-    /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    pub fn prefetch_write_instruction<T>(data: *const T, locality: i32);
-}
-
-extern "rust-intrinsic" {
     /// An atomic fence.
     ///
     /// The stabilized version of this intrinsic is available in
     /// [`atomic::fence`] by passing [`Ordering::SeqCst`]
     /// as the `order`.
-    pub fn atomic_fence();
+    pub fn atomic_fence_seqcst();
     /// An atomic fence.
     ///
     /// The stabilized version of this intrinsic is available in
     /// [`atomic::fence`] by passing [`Ordering::Acquire`]
     /// as the `order`.
-    pub fn atomic_fence_acq();
+    pub fn atomic_fence_acquire();
     /// An atomic fence.
     ///
     /// The stabilized version of this intrinsic is available in
     /// [`atomic::fence`] by passing [`Ordering::Release`]
     /// as the `order`.
-    pub fn atomic_fence_rel();
+    pub fn atomic_fence_release();
     /// An atomic fence.
     ///
     /// The stabilized version of this intrinsic is available in
@@ -661,7 +910,7 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available in
     /// [`atomic::compiler_fence`] by passing [`Ordering::SeqCst`]
     /// as the `order`.
-    pub fn atomic_singlethreadfence();
+    pub fn atomic_singlethreadfence_seqcst();
     /// A compiler-only memory barrier.
     ///
     /// Memory accesses will never be reordered across this barrier by the
@@ -672,7 +921,7 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available in
     /// [`atomic::compiler_fence`] by passing [`Ordering::Acquire`]
     /// as the `order`.
-    pub fn atomic_singlethreadfence_acq();
+    pub fn atomic_singlethreadfence_acquire();
     /// A compiler-only memory barrier.
     ///
     /// Memory accesses will never be reordered across this barrier by the
@@ -683,7 +932,7 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is available in
     /// [`atomic::compiler_fence`] by passing [`Ordering::Release`]
     /// as the `order`.
-    pub fn atomic_singlethreadfence_rel();
+    pub fn atomic_singlethreadfence_release();
     /// A compiler-only memory barrier.
     ///
     /// Memory accesses will never be reordered across this barrier by the
@@ -695,6 +944,68 @@ extern "rust-intrinsic" {
     /// [`atomic::compiler_fence`] by passing [`Ordering::AcqRel`]
     /// as the `order`.
     pub fn atomic_singlethreadfence_acqrel();
+}
+
+// These have been renamed.
+//
+// These are the aliases for the old names, to be removed when stdarch has been updated.
+#[cfg(not(bootstrap))]
+mod atomics {
+    pub use super::atomic_cxchg_acqrel_acquire as atomic_cxchg_acqrel;
+    pub use super::atomic_cxchg_acqrel_relaxed as atomic_cxchg_acqrel_failrelaxed;
+    pub use super::atomic_cxchg_acquire_acquire as atomic_cxchg_acq;
+    pub use super::atomic_cxchg_acquire_relaxed as atomic_cxchg_acq_failrelaxed;
+    pub use super::atomic_cxchg_relaxed_relaxed as atomic_cxchg_relaxed;
+    pub use super::atomic_cxchg_release_relaxed as atomic_cxchg_rel;
+    pub use super::atomic_cxchg_seqcst_acquire as atomic_cxchg_failacq;
+    pub use super::atomic_cxchg_seqcst_relaxed as atomic_cxchg_failrelaxed;
+    pub use super::atomic_cxchg_seqcst_seqcst as atomic_cxchg;
+}
+
+#[cfg(not(bootstrap))]
+pub use atomics::*;
+
+extern "rust-intrinsic" {
+    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+    /// if supported; otherwise, it is a no-op.
+    /// Prefetches have no effect on the behavior of the program but can change its performance
+    /// characteristics.
+    ///
+    /// The `locality` argument must be a constant integer and is a temporal locality specifier
+    /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+    ///
+    /// This intrinsic does not have a stable counterpart.
+    pub fn prefetch_read_data<T>(data: *const T, locality: i32);
+    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+    /// if supported; otherwise, it is a no-op.
+    /// Prefetches have no effect on the behavior of the program but can change its performance
+    /// characteristics.
+    ///
+    /// The `locality` argument must be a constant integer and is a temporal locality specifier
+    /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+    ///
+    /// This intrinsic does not have a stable counterpart.
+    pub fn prefetch_write_data<T>(data: *const T, locality: i32);
+    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+    /// if supported; otherwise, it is a no-op.
+    /// Prefetches have no effect on the behavior of the program but can change its performance
+    /// characteristics.
+    ///
+    /// The `locality` argument must be a constant integer and is a temporal locality specifier
+    /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+    ///
+    /// This intrinsic does not have a stable counterpart.
+    pub fn prefetch_read_instruction<T>(data: *const T, locality: i32);
+    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+    /// if supported; otherwise, it is a no-op.
+    /// Prefetches have no effect on the behavior of the program but can change its performance
+    /// characteristics.
+    ///
+    /// The `locality` argument must be a constant integer and is a temporal locality specifier
+    /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+    ///
+    /// This intrinsic does not have a stable counterpart.
+    pub fn prefetch_write_instruction<T>(data: *const T, locality: i32);
 
     /// Magic intrinsic that derives its meaning from attributes
     /// attached to the function.
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 70969edd6eaf7..e570d831cc607 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -316,7 +316,6 @@ macro_rules! nonzero_unsigned_operations {
                 /// # Examples
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -331,7 +330,8 @@ macro_rules! nonzero_unsigned_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -351,7 +351,6 @@ macro_rules! nonzero_unsigned_operations {
                 /// # Examples
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -366,7 +365,8 @@ macro_rules! nonzero_unsigned_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -415,7 +415,6 @@ macro_rules! nonzero_unsigned_operations {
                 /// # Examples
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -432,7 +431,8 @@ macro_rules! nonzero_unsigned_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -521,7 +521,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -534,7 +533,8 @@ macro_rules! nonzero_signed_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -551,7 +551,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -566,7 +565,8 @@ macro_rules! nonzero_signed_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -586,7 +586,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -602,7 +601,8 @@ macro_rules! nonzero_signed_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -621,7 +621,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -642,7 +641,8 @@ macro_rules! nonzero_signed_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -657,7 +657,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -677,7 +676,8 @@ macro_rules! nonzero_signed_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -692,7 +692,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 #[doc = concat!("# use std::num::", stringify!($Uty), ";")]
                 ///
@@ -712,7 +711,8 @@ macro_rules! nonzero_signed_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -746,7 +746,6 @@ macro_rules! nonzero_unsigned_signed_operations {
                 /// # Examples
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -761,7 +760,8 @@ macro_rules! nonzero_unsigned_signed_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -782,7 +782,6 @@ macro_rules! nonzero_unsigned_signed_operations {
                 /// # Examples
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -797,7 +796,8 @@ macro_rules! nonzero_unsigned_signed_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -855,7 +855,6 @@ macro_rules! nonzero_unsigned_signed_operations {
                 /// # Examples
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -870,7 +869,8 @@ macro_rules! nonzero_unsigned_signed_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -899,7 +899,6 @@ macro_rules! nonzero_unsigned_signed_operations {
                 /// # Examples
                 ///
                 /// ```
-                /// #![feature(nonzero_ops)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 /// # fn main() { test().unwrap(); }
@@ -914,7 +913,8 @@ macro_rules! nonzero_unsigned_signed_operations {
                 /// # Some(())
                 /// # }
                 /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
+                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index a66ecc35bbdb1..a68c6080e3a17 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -2575,11 +2575,11 @@ unsafe fn atomic_store<T: Copy>(dst: *mut T, val: T, order: Ordering) {
     // SAFETY: the caller must uphold the safety contract for `atomic_store`.
     unsafe {
         match order {
-            Release => intrinsics::atomic_store_rel(dst, val),
             Relaxed => intrinsics::atomic_store_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_store(dst, val),
+            Release => intrinsics::atomic_store_release(dst, val),
+            SeqCst => intrinsics::atomic_store_seqcst(dst, val),
             Acquire => panic!("there is no such thing as an acquire store"),
-            AcqRel => panic!("there is no such thing as an acquire/release store"),
+            AcqRel => panic!("there is no such thing as an acquire-release store"),
         }
     }
 }
@@ -2589,11 +2589,11 @@ unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_load`.
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_load_acq(dst),
             Relaxed => intrinsics::atomic_load_relaxed(dst),
-            SeqCst => intrinsics::atomic_load(dst),
+            Acquire => intrinsics::atomic_load_acquire(dst),
+            SeqCst => intrinsics::atomic_load_seqcst(dst),
             Release => panic!("there is no such thing as a release load"),
-            AcqRel => panic!("there is no such thing as an acquire/release load"),
+            AcqRel => panic!("there is no such thing as an acquire-release load"),
         }
     }
 }
@@ -2604,11 +2604,11 @@ unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_swap`.
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_xchg_acq(dst, val),
-            Release => intrinsics::atomic_xchg_rel(dst, val),
-            AcqRel => intrinsics::atomic_xchg_acqrel(dst, val),
             Relaxed => intrinsics::atomic_xchg_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_xchg(dst, val),
+            Acquire => intrinsics::atomic_xchg_acquire(dst, val),
+            Release => intrinsics::atomic_xchg_release(dst, val),
+            AcqRel => intrinsics::atomic_xchg_acqrel(dst, val),
+            SeqCst => intrinsics::atomic_xchg_seqcst(dst, val),
         }
     }
 }
@@ -2620,11 +2620,11 @@ unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_add`.
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_xadd_acq(dst, val),
-            Release => intrinsics::atomic_xadd_rel(dst, val),
-            AcqRel => intrinsics::atomic_xadd_acqrel(dst, val),
             Relaxed => intrinsics::atomic_xadd_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_xadd(dst, val),
+            Acquire => intrinsics::atomic_xadd_acquire(dst, val),
+            Release => intrinsics::atomic_xadd_release(dst, val),
+            AcqRel => intrinsics::atomic_xadd_acqrel(dst, val),
+            SeqCst => intrinsics::atomic_xadd_seqcst(dst, val),
         }
     }
 }
@@ -2636,11 +2636,11 @@ unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_sub`.
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_xsub_acq(dst, val),
-            Release => intrinsics::atomic_xsub_rel(dst, val),
-            AcqRel => intrinsics::atomic_xsub_acqrel(dst, val),
             Relaxed => intrinsics::atomic_xsub_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_xsub(dst, val),
+            Acquire => intrinsics::atomic_xsub_acquire(dst, val),
+            Release => intrinsics::atomic_xsub_release(dst, val),
+            AcqRel => intrinsics::atomic_xsub_acqrel(dst, val),
+            SeqCst => intrinsics::atomic_xsub_seqcst(dst, val),
         }
     }
 }
@@ -2657,16 +2657,22 @@ unsafe fn atomic_compare_exchange<T: Copy>(
     // SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange`.
     let (val, ok) = unsafe {
         match (success, failure) {
-            (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new),
-            (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new),
-            (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new),
-            (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new),
-            (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new),
-            (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new),
-            (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new),
-            (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new),
-            (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new),
-            (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
+            (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed_relaxed(dst, old, new),
+            //(Relaxed, Acquire) => intrinsics::atomic_cxchg_relaxed_acquire(dst, old, new),
+            //(Relaxed, SeqCst) => intrinsics::atomic_cxchg_relaxed_seqcst(dst, old, new),
+            (Acquire, Relaxed) => intrinsics::atomic_cxchg_acquire_relaxed(dst, old, new),
+            (Acquire, Acquire) => intrinsics::atomic_cxchg_acquire_acquire(dst, old, new),
+            //(Acquire, SeqCst) => intrinsics::atomic_cxchg_acquire_seqcst(dst, old, new),
+            (Release, Relaxed) => intrinsics::atomic_cxchg_release_relaxed(dst, old, new),
+            //(Release, Acquire) => intrinsics::atomic_cxchg_release_acquire(dst, old, new),
+            //(Release, SeqCst) => intrinsics::atomic_cxchg_release_seqcst(dst, old, new),
+            (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_relaxed(dst, old, new),
+            (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel_acquire(dst, old, new),
+            //(AcqRel, SeqCst) => intrinsics::atomic_cxchg_acqrel_seqcst(dst, old, new),
+            (SeqCst, Relaxed) => intrinsics::atomic_cxchg_seqcst_relaxed(dst, old, new),
+            (SeqCst, Acquire) => intrinsics::atomic_cxchg_seqcst_acquire(dst, old, new),
+            (SeqCst, SeqCst) => intrinsics::atomic_cxchg_seqcst_seqcst(dst, old, new),
+            (_, AcqRel) => panic!("there is no such thing as an acquire-release failure ordering"),
             (_, Release) => panic!("there is no such thing as a release failure ordering"),
             _ => panic!("a failure ordering can't be stronger than a success ordering"),
         }
@@ -2686,16 +2692,22 @@ unsafe fn atomic_compare_exchange_weak<T: Copy>(
     // SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange_weak`.
     let (val, ok) = unsafe {
         match (success, failure) {
-            (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new),
-            (Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new),
-            (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new),
-            (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed(dst, old, new),
-            (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new),
-            (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acq_failrelaxed(dst, old, new),
-            (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new),
-            (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new),
-            (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new),
-            (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
+            (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed_relaxed(dst, old, new),
+            //(Relaxed, Acquire) => intrinsics::atomic_cxchgweak_relaxed_acquire(dst, old, new),
+            //(Relaxed, SeqCst) => intrinsics::atomic_cxchgweak_relaxed_seqcst(dst, old, new),
+            (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acquire_relaxed(dst, old, new),
+            (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acquire_acquire(dst, old, new),
+            //(Acquire, SeqCst) => intrinsics::atomic_cxchgweak_acquire_seqcst(dst, old, new),
+            (Release, Relaxed) => intrinsics::atomic_cxchgweak_release_relaxed(dst, old, new),
+            //(Release, Acquire) => intrinsics::atomic_cxchgweak_release_acquire(dst, old, new),
+            //(Release, SeqCst) => intrinsics::atomic_cxchgweak_release_seqcst(dst, old, new),
+            (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_relaxed(dst, old, new),
+            (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel_acquire(dst, old, new),
+            //(AcqRel, SeqCst) => intrinsics::atomic_cxchgweak_acqrel_seqcst(dst, old, new),
+            (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_seqcst_relaxed(dst, old, new),
+            (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_seqcst_acquire(dst, old, new),
+            (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak_seqcst_seqcst(dst, old, new),
+            (_, AcqRel) => panic!("there is no such thing as an acquire-release failure ordering"),
             (_, Release) => panic!("there is no such thing as a release failure ordering"),
             _ => panic!("a failure ordering can't be stronger than a success ordering"),
         }
@@ -2709,11 +2721,11 @@ unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_and`
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_and_acq(dst, val),
-            Release => intrinsics::atomic_and_rel(dst, val),
-            AcqRel => intrinsics::atomic_and_acqrel(dst, val),
             Relaxed => intrinsics::atomic_and_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_and(dst, val),
+            Acquire => intrinsics::atomic_and_acquire(dst, val),
+            Release => intrinsics::atomic_and_release(dst, val),
+            AcqRel => intrinsics::atomic_and_acqrel(dst, val),
+            SeqCst => intrinsics::atomic_and_seqcst(dst, val),
         }
     }
 }
@@ -2724,11 +2736,11 @@ unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_nand`
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_nand_acq(dst, val),
-            Release => intrinsics::atomic_nand_rel(dst, val),
-            AcqRel => intrinsics::atomic_nand_acqrel(dst, val),
             Relaxed => intrinsics::atomic_nand_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_nand(dst, val),
+            Acquire => intrinsics::atomic_nand_acquire(dst, val),
+            Release => intrinsics::atomic_nand_release(dst, val),
+            AcqRel => intrinsics::atomic_nand_acqrel(dst, val),
+            SeqCst => intrinsics::atomic_nand_seqcst(dst, val),
         }
     }
 }
@@ -2739,11 +2751,11 @@ unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_or`
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_or_acq(dst, val),
-            Release => intrinsics::atomic_or_rel(dst, val),
+            SeqCst => intrinsics::atomic_or_seqcst(dst, val),
+            Acquire => intrinsics::atomic_or_acquire(dst, val),
+            Release => intrinsics::atomic_or_release(dst, val),
             AcqRel => intrinsics::atomic_or_acqrel(dst, val),
             Relaxed => intrinsics::atomic_or_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_or(dst, val),
         }
     }
 }
@@ -2754,11 +2766,11 @@ unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_xor`
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_xor_acq(dst, val),
-            Release => intrinsics::atomic_xor_rel(dst, val),
+            SeqCst => intrinsics::atomic_xor_seqcst(dst, val),
+            Acquire => intrinsics::atomic_xor_acquire(dst, val),
+            Release => intrinsics::atomic_xor_release(dst, val),
             AcqRel => intrinsics::atomic_xor_acqrel(dst, val),
             Relaxed => intrinsics::atomic_xor_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_xor(dst, val),
         }
     }
 }
@@ -2770,11 +2782,11 @@ unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_max`
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_max_acq(dst, val),
-            Release => intrinsics::atomic_max_rel(dst, val),
-            AcqRel => intrinsics::atomic_max_acqrel(dst, val),
             Relaxed => intrinsics::atomic_max_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_max(dst, val),
+            Acquire => intrinsics::atomic_max_acquire(dst, val),
+            Release => intrinsics::atomic_max_release(dst, val),
+            AcqRel => intrinsics::atomic_max_acqrel(dst, val),
+            SeqCst => intrinsics::atomic_max_seqcst(dst, val),
         }
     }
 }
@@ -2786,11 +2798,11 @@ unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_min`
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_min_acq(dst, val),
-            Release => intrinsics::atomic_min_rel(dst, val),
-            AcqRel => intrinsics::atomic_min_acqrel(dst, val),
             Relaxed => intrinsics::atomic_min_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_min(dst, val),
+            Acquire => intrinsics::atomic_min_acquire(dst, val),
+            Release => intrinsics::atomic_min_release(dst, val),
+            AcqRel => intrinsics::atomic_min_acqrel(dst, val),
+            SeqCst => intrinsics::atomic_min_seqcst(dst, val),
         }
     }
 }
@@ -2802,11 +2814,11 @@ unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_umax`
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_umax_acq(dst, val),
-            Release => intrinsics::atomic_umax_rel(dst, val),
-            AcqRel => intrinsics::atomic_umax_acqrel(dst, val),
             Relaxed => intrinsics::atomic_umax_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_umax(dst, val),
+            Acquire => intrinsics::atomic_umax_acquire(dst, val),
+            Release => intrinsics::atomic_umax_release(dst, val),
+            AcqRel => intrinsics::atomic_umax_acqrel(dst, val),
+            SeqCst => intrinsics::atomic_umax_seqcst(dst, val),
         }
     }
 }
@@ -2818,11 +2830,11 @@ unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_umin`
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_umin_acq(dst, val),
-            Release => intrinsics::atomic_umin_rel(dst, val),
-            AcqRel => intrinsics::atomic_umin_acqrel(dst, val),
             Relaxed => intrinsics::atomic_umin_relaxed(dst, val),
-            SeqCst => intrinsics::atomic_umin(dst, val),
+            Acquire => intrinsics::atomic_umin_acquire(dst, val),
+            Release => intrinsics::atomic_umin_release(dst, val),
+            AcqRel => intrinsics::atomic_umin_acqrel(dst, val),
+            SeqCst => intrinsics::atomic_umin_seqcst(dst, val),
         }
     }
 }
@@ -2908,10 +2920,10 @@ pub fn fence(order: Ordering) {
     // SAFETY: using an atomic fence is safe.
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_fence_acq(),
-            Release => intrinsics::atomic_fence_rel(),
+            Acquire => intrinsics::atomic_fence_acquire(),
+            Release => intrinsics::atomic_fence_release(),
             AcqRel => intrinsics::atomic_fence_acqrel(),
-            SeqCst => intrinsics::atomic_fence(),
+            SeqCst => intrinsics::atomic_fence_seqcst(),
             Relaxed => panic!("there is no such thing as a relaxed fence"),
         }
     }
@@ -2990,10 +3002,10 @@ pub fn compiler_fence(order: Ordering) {
     // SAFETY: using an atomic fence is safe.
     unsafe {
         match order {
-            Acquire => intrinsics::atomic_singlethreadfence_acq(),
-            Release => intrinsics::atomic_singlethreadfence_rel(),
+            Acquire => intrinsics::atomic_singlethreadfence_acquire(),
+            Release => intrinsics::atomic_singlethreadfence_release(),
             AcqRel => intrinsics::atomic_singlethreadfence_acqrel(),
-            SeqCst => intrinsics::atomic_singlethreadfence(),
+            SeqCst => intrinsics::atomic_singlethreadfence_seqcst(),
             Relaxed => panic!("there is no such thing as a relaxed compiler fence"),
         }
     }
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index f46997b807ab2..cd43e1cadae9a 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -184,6 +184,11 @@ pub struct DirEntry(fs_imp::DirEntry);
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OpenOptions(fs_imp::OpenOptions);
 
+/// Representation of the various timestamps on a file.
+#[derive(Copy, Clone, Debug, Default)]
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub struct FileTimes(fs_imp::FileTimes);
+
 /// Representation of the various permissions on a file.
 ///
 /// This module only currently provides one bit of information,
@@ -590,6 +595,58 @@ impl File {
     pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
         self.inner.set_permissions(perm.0)
     }
+
+    /// Changes the timestamps of the underlying file.
+    ///
+    /// # Platform-specific behavior
+    ///
+    /// This function currently corresponds to the `futimens` function on Unix (falling back to
+    /// `futimes` on macOS before 10.13) and the `SetFileTime` function on Windows. Note that this
+    /// [may change in the future][changes].
+    ///
+    /// [changes]: io#platform-specific-behavior
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the user lacks permission to change timestamps on the
+    /// underlying file. It may also return an error in other os-specific unspecified cases.
+    ///
+    /// This function may return an error if the operating system lacks support to change one or
+    /// more of the timestamps set in the `FileTimes` structure.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(file_set_times)]
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     use std::fs::{self, File, FileTimes};
+    ///
+    ///     let src = fs::metadata("src")?;
+    ///     let dest = File::options().write(true).open("dest")?;
+    ///     let times = FileTimes::new()
+    ///         .set_accessed(src.accessed()?)
+    ///         .set_modified(src.modified()?);
+    ///     dest.set_times(times)?;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    #[doc(alias = "futimens")]
+    #[doc(alias = "futimes")]
+    #[doc(alias = "SetFileTime")]
+    pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
+        self.inner.set_times(times.0)
+    }
+
+    /// Changes the modification time of the underlying file.
+    ///
+    /// This is an alias for `set_times(FileTimes::new().set_modified(time))`.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    #[inline]
+    pub fn set_modified(&self, time: SystemTime) -> io::Result<()> {
+        self.set_times(FileTimes::new().set_modified(time))
+    }
 }
 
 // In addition to the `impl`s here, `File` also has `impl`s for
@@ -1246,6 +1303,30 @@ impl FromInner<fs_imp::FileAttr> for Metadata {
     }
 }
 
+impl FileTimes {
+    /// Create a new `FileTimes` with no times set.
+    ///
+    /// Using the resulting `FileTimes` in [`File::set_times`] will not modify any timestamps.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    /// Set the last access time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    pub fn set_accessed(mut self, t: SystemTime) -> Self {
+        self.0.set_accessed(t.into_inner());
+        self
+    }
+
+    /// Set the last modified time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    pub fn set_modified(mut self, t: SystemTime) -> Self {
+        self.0.set_modified(t.into_inner());
+        self
+    }
+}
+
 impl Permissions {
     /// Returns `true` if these permissions describe a readonly (unwritable) file.
     ///
diff --git a/library/std/src/sys/itron/abi.rs b/library/std/src/sys/itron/abi.rs
index f99ee4fa897ea..5eb14bb7e534b 100644
--- a/library/std/src/sys/itron/abi.rs
+++ b/library/std/src/sys/itron/abi.rs
@@ -30,15 +30,32 @@ pub type ER = int_t;
 /// Error code type, `ID` on success
 pub type ER_ID = int_t;
 
+/// Service call operational mode
+pub type MODE = uint_t;
+
+/// OR waiting condition for an eventflag
+pub const TWF_ORW: MODE = 0x01;
+
+/// Object attributes
+pub type ATR = uint_t;
+
+/// FIFO wait order
+pub const TA_FIFO: ATR = 0;
+/// Only one task is allowed to be in the waiting state for the eventflag
+pub const TA_WSGL: ATR = 0;
+/// The eventflag’s bit pattern is cleared when a task is released from the
+/// waiting state for that eventflag.
+pub const TA_CLR: ATR = 0x04;
+
+/// Bit pattern of an eventflag
+pub type FLGPTN = uint_t;
+
 /// Task or interrupt priority
 pub type PRI = int_t;
 
 /// The special value of `PRI` representing the current task's priority.
 pub const TPRI_SELF: PRI = 0;
 
-/// Object attributes
-pub type ATR = uint_t;
-
 /// Use the priority inheritance protocol
 #[cfg(target_os = "solid_asp3")]
 pub const TA_INHERIT: ATR = 0x02;
@@ -90,6 +107,13 @@ pub struct T_CSEM {
     pub maxsem: uint_t,
 }
 
+#[derive(Clone, Copy)]
+#[repr(C)]
+pub struct T_CFLG {
+    pub flgatr: ATR,
+    pub iflgptn: FLGPTN,
+}
+
 #[derive(Clone, Copy)]
 #[repr(C)]
 pub struct T_CMTX {
@@ -139,6 +163,24 @@ extern "C" {
     pub fn sns_dsp() -> bool_t;
     #[link_name = "__asp3_get_tim"]
     pub fn get_tim(p_systim: *mut SYSTIM) -> ER;
+    #[link_name = "__asp3_acre_flg"]
+    pub fn acre_flg(pk_cflg: *const T_CFLG) -> ER_ID;
+    #[link_name = "__asp3_del_flg"]
+    pub fn del_flg(flgid: ID) -> ER;
+    #[link_name = "__asp3_set_flg"]
+    pub fn set_flg(flgid: ID, setptn: FLGPTN) -> ER;
+    #[link_name = "__asp3_clr_flg"]
+    pub fn clr_flg(flgid: ID, clrptn: FLGPTN) -> ER;
+    #[link_name = "__asp3_wai_flg"]
+    pub fn wai_flg(flgid: ID, waiptn: FLGPTN, wfmode: MODE, p_flgptn: *mut FLGPTN) -> ER;
+    #[link_name = "__asp3_twai_flg"]
+    pub fn twai_flg(
+        flgid: ID,
+        waiptn: FLGPTN,
+        wfmode: MODE,
+        p_flgptn: *mut FLGPTN,
+        tmout: TMO,
+    ) -> ER;
     #[link_name = "__asp3_acre_mtx"]
     pub fn acre_mtx(pk_cmtx: *const T_CMTX) -> ER_ID;
     #[link_name = "__asp3_del_mtx"]
diff --git a/library/std/src/sys/itron/wait_flag.rs b/library/std/src/sys/itron/wait_flag.rs
new file mode 100644
index 0000000000000..e432edd207754
--- /dev/null
+++ b/library/std/src/sys/itron/wait_flag.rs
@@ -0,0 +1,72 @@
+use crate::mem::MaybeUninit;
+use crate::time::Duration;
+
+use super::{
+    abi,
+    error::{expect_success, fail},
+    time::with_tmos,
+};
+
+const CLEAR: abi::FLGPTN = 0;
+const RAISED: abi::FLGPTN = 1;
+
+/// A thread parking primitive that is not susceptible to race conditions,
+/// but provides no atomic ordering guarantees and allows only one `raise` per wait.
+pub struct WaitFlag {
+    flag: abi::ID,
+}
+
+impl WaitFlag {
+    /// Creates a new wait flag.
+    pub fn new() -> WaitFlag {
+        let flag = expect_success(
+            unsafe {
+                abi::acre_flg(&abi::T_CFLG {
+                    flgatr: abi::TA_FIFO | abi::TA_WSGL | abi::TA_CLR,
+                    iflgptn: CLEAR,
+                })
+            },
+            &"acre_flg",
+        );
+
+        WaitFlag { flag }
+    }
+
+    /// Wait for the wait flag to be raised.
+    pub fn wait(&self) {
+        let mut token = MaybeUninit::uninit();
+        expect_success(
+            unsafe { abi::wai_flg(self.flag, RAISED, abi::TWF_ORW, token.as_mut_ptr()) },
+            &"wai_flg",
+        );
+    }
+
+    /// Wait for the wait flag to be raised or the timeout to occur.
+    ///
+    /// Returns whether the flag was raised (`true`) or the operation timed out (`false`).
+    pub fn wait_timeout(&self, dur: Duration) -> bool {
+        let mut token = MaybeUninit::uninit();
+        let res = with_tmos(dur, |tmout| unsafe {
+            abi::twai_flg(self.flag, RAISED, abi::TWF_ORW, token.as_mut_ptr(), tmout)
+        });
+
+        match res {
+            abi::E_OK => true,
+            abi::E_TMOUT => false,
+            error => fail(error, &"twai_flg"),
+        }
+    }
+
+    /// Raise the wait flag.
+    ///
+    /// Calls to this function should be balanced with the number of successful waits.
+    pub fn raise(&self) {
+        expect_success(unsafe { abi::set_flg(self.flag, RAISED) }, &"set_flg");
+    }
+}
+
+impl Drop for WaitFlag {
+    fn drop(&mut self) {
+        expect_success(unsafe { abi::del_flg(self.flag) }, &"del_flg");
+    }
+}
diff --git a/library/std/src/sys/solid/mod.rs b/library/std/src/sys/solid/mod.rs
index 5ffa381f2e50f..2d21e4764fc21 100644
--- a/library/std/src/sys/solid/mod.rs
+++ b/library/std/src/sys/solid/mod.rs
@@ -15,6 +15,7 @@ mod itron {
     pub mod thread;
     pub(super) mod time;
     use super::unsupported;
+    pub mod wait_flag;
 }
 
 pub mod alloc;
@@ -43,6 +44,7 @@ pub mod memchr;
 pub mod thread_local_dtor;
 pub mod thread_local_key;
 pub mod time;
+pub use self::itron::wait_flag;
 
 mod rwlock;
 
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 8b0bbd6a55c6b..f33ab3a3e14b2 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -311,6 +311,9 @@ pub struct FilePermissions {
     mode: mode_t,
 }
 
+#[derive(Copy, Clone)]
+pub struct FileTimes([libc::timespec; 2]);
+
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct FileType {
     mode: mode_t,
@@ -503,6 +506,43 @@ impl FilePermissions {
     }
 }
 
+impl FileTimes {
+    pub fn set_accessed(&mut self, t: SystemTime) {
+        self.0[0] = t.t.to_timespec().expect("Invalid system time");
+    }
+
+    pub fn set_modified(&mut self, t: SystemTime) {
+        self.0[1] = t.t.to_timespec().expect("Invalid system time");
+    }
+}
+
+struct TimespecDebugAdapter<'a>(&'a libc::timespec);
+
+impl fmt::Debug for TimespecDebugAdapter<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("timespec")
+            .field("tv_sec", &self.0.tv_sec)
+            .field("tv_nsec", &self.0.tv_nsec)
+            .finish()
+    }
+}
+
+impl fmt::Debug for FileTimes {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("FileTimes")
+            .field("accessed", &TimespecDebugAdapter(&self.0[0]))
+            .field("modified", &TimespecDebugAdapter(&self.0[1]))
+            .finish()
+    }
+}
+
+impl Default for FileTimes {
+    fn default() -> Self {
+        let omit = libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT };
+        Self([omit; 2])
+    }
+}
+
 impl FileType {
     pub fn is_dir(&self) -> bool {
         self.is(libc::S_IFDIR)
@@ -1021,6 +1061,30 @@ impl File {
         cvt_r(|| unsafe { libc::fchmod(self.as_raw_fd(), perm.mode) })?;
         Ok(())
     }
+
+    pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
+        cfg_if::cfg_if! {
+            // futimens requires macOS 10.13
+            if #[cfg(target_os = "macos")] {
+                fn ts_to_tv(ts: &libc::timespec) -> libc::timeval {
+                    libc::timeval { tv_sec: ts.tv_sec, tv_usec: (ts.tv_nsec / 1000) as _ }
+                }
+                cvt(unsafe {
+                    weak!(fn futimens(c_int, *const libc::timespec) -> c_int);
+                    futimens.get()
+                        .map(|futimens| futimens(self.as_raw_fd(), times.0.as_ptr()))
+                        .unwrap_or_else(|| {
+                            let timevals = [ts_to_tv(&times.0[0]), ts_to_tv(&times.0[1])];
+                            libc::futimes(self.as_raw_fd(), timevals.as_ptr())
+                        })
+                })?;
+            } else {
+                cvt(unsafe { libc::futimens(self.as_raw_fd(), times.0.as_ptr()) })?;
+            }
+        }
+
+        Ok(())
+    }
 }
 
 impl DirBuilder {
diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs
index d1d2847cd33be..0e1a6257ed763 100644
--- a/library/std/src/sys/unsupported/fs.rs
+++ b/library/std/src/sys/unsupported/fs.rs
@@ -17,6 +17,9 @@ pub struct DirEntry(!);
 #[derive(Clone, Debug)]
 pub struct OpenOptions {}
 
+#[derive(Copy, Clone, Debug, Default)]
+pub struct FileTimes {}
+
 pub struct FilePermissions(!);
 
 pub struct FileType(!);
@@ -86,6 +89,11 @@ impl fmt::Debug for FilePermissions {
     }
 }
 
+impl FileTimes {
+    pub fn set_accessed(&mut self, _t: SystemTime) {}
+    pub fn set_modified(&mut self, _t: SystemTime) {}
+}
+
 impl FileType {
     pub fn is_dir(&self) -> bool {
         self.0
@@ -237,6 +245,10 @@ impl File {
     pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
         self.0
     }
+
+    pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
+        self.0
+    }
 }
 
 impl DirBuilder {
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index cd6815bfc2136..6614ae397b57f 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -63,6 +63,12 @@ pub struct FilePermissions {
     readonly: bool,
 }
 
+#[derive(Copy, Clone, Debug, Default)]
+pub struct FileTimes {
+    accessed: Option<wasi::Timestamp>,
+    modified: Option<wasi::Timestamp>,
+}
+
 #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
 pub struct FileType {
     bits: wasi::Filetype,
@@ -112,6 +118,16 @@ impl FilePermissions {
     }
 }
 
+impl FileTimes {
+    pub fn set_accessed(&mut self, t: SystemTime) {
+        self.accessed = Some(t.to_wasi_timestamp_or_panic());
+    }
+
+    pub fn set_modified(&mut self, t: SystemTime) {
+        self.modified = Some(t.to_wasi_timestamp_or_panic());
+    }
+}
+
 impl FileType {
     pub fn is_dir(&self) -> bool {
         self.bits == wasi::FILETYPE_DIRECTORY
@@ -459,6 +475,15 @@ impl File {
         unsupported()
     }
 
+    pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
+        self.fd.filestat_set_times(
+            times.accessed.unwrap_or(0),
+            times.modified.unwrap_or(0),
+            times.accessed.map_or(0, |_| wasi::FSTFLAGS_ATIM)
+                | times.modified.map_or(0, |_| wasi::FSTFLAGS_MTIM),
+        )
+    }
+
     pub fn read_link(&self, file: &Path) -> io::Result<PathBuf> {
         read_link(&self.fd, file)
     }
diff --git a/library/std/src/sys/wasi/time.rs b/library/std/src/sys/wasi/time.rs
index 088585654b948..3d326e49106ca 100644
--- a/library/std/src/sys/wasi/time.rs
+++ b/library/std/src/sys/wasi/time.rs
@@ -47,6 +47,10 @@ impl SystemTime {
         SystemTime(Duration::from_nanos(ts))
     }
 
+    pub fn to_wasi_timestamp_or_panic(&self) -> wasi::Timestamp {
+        self.0.as_nanos().try_into().expect("time does not fit in WASI timestamp")
+    }
+
     pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
         self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
     }
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index 5469487df1eed..abb471213d251 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -607,7 +607,7 @@ pub struct SOCKADDR {
 }
 
 #[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug, Default)]
 pub struct FILETIME {
     pub dwLowDateTime: DWORD,
     pub dwHighDateTime: DWORD,
@@ -875,6 +875,12 @@ extern "system" {
     pub fn GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT;
     pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
     pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL;
+    pub fn SetFileTime(
+        hFile: BorrowedHandle<'_>,
+        lpCreationTime: Option<&FILETIME>,
+        lpLastAccessTime: Option<&FILETIME>,
+        lpLastWriteTime: Option<&FILETIME>,
+    ) -> BOOL;
     pub fn SetLastError(dwErrCode: DWORD);
     pub fn GetCommandLineW() -> LPWSTR;
     pub fn GetTempPathW(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD;
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index e9b1006907741..b543d8f040aa8 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -83,6 +83,12 @@ pub struct FilePermissions {
     attrs: c::DWORD,
 }
 
+#[derive(Copy, Clone, Debug, Default)]
+pub struct FileTimes {
+    accessed: Option<c::FILETIME>,
+    modified: Option<c::FILETIME>,
+}
+
 #[derive(Debug)]
 pub struct DirBuilder;
 
@@ -551,6 +557,21 @@ impl File {
         })?;
         Ok(())
     }
+
+    pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
+        let is_zero = |t: c::FILETIME| t.dwLowDateTime == 0 && t.dwHighDateTime == 0;
+        if times.accessed.map_or(false, is_zero) || times.modified.map_or(false, is_zero) {
+            return Err(io::const_io_error!(
+                io::ErrorKind::InvalidInput,
+                "Cannot set file timestamp to 0",
+            ));
+        }
+        cvt(unsafe {
+            c::SetFileTime(self.as_handle(), None, times.accessed.as_ref(), times.modified.as_ref())
+        })?;
+        Ok(())
+    }
+
     /// Get only basic file information such as attributes and file times.
     fn basic_info(&self) -> io::Result<c::FILE_BASIC_INFO> {
         unsafe {
@@ -898,6 +919,16 @@ impl FilePermissions {
     }
 }
 
+impl FileTimes {
+    pub fn set_accessed(&mut self, t: SystemTime) {
+        self.accessed = Some(t.into_inner());
+    }
+
+    pub fn set_modified(&mut self, t: SystemTime) {
+        self.modified = Some(t.into_inner());
+    }
+}
+
 impl FileType {
     fn new(attrs: c::DWORD, reparse_tag: c::DWORD) -> FileType {
         FileType { attributes: attrs, reparse_tag }
diff --git a/library/std/src/sys/windows/time.rs b/library/std/src/sys/windows/time.rs
index 8f46781c75340..b8209a8544585 100644
--- a/library/std/src/sys/windows/time.rs
+++ b/library/std/src/sys/windows/time.rs
@@ -2,6 +2,7 @@ use crate::cmp::Ordering;
 use crate::fmt;
 use crate::mem;
 use crate::sys::c;
+use crate::sys_common::IntoInner;
 use crate::time::Duration;
 
 use core::hash::{Hash, Hasher};
@@ -136,6 +137,12 @@ impl From<c::FILETIME> for SystemTime {
     }
 }
 
+impl IntoInner<c::FILETIME> for SystemTime {
+    fn into_inner(self) -> c::FILETIME {
+        self.t
+    }
+}
+
 impl Hash for SystemTime {
     fn hash<H: Hasher>(&self, state: &mut H) {
         self.intervals().hash(state)
diff --git a/library/std/src/sys_common/thread_parker/mod.rs b/library/std/src/sys_common/thread_parker/mod.rs
index 7e8bfb2565e45..cbd7832eb7a4c 100644
--- a/library/std/src/sys_common/thread_parker/mod.rs
+++ b/library/std/src/sys_common/thread_parker/mod.rs
@@ -10,9 +10,10 @@ cfg_if::cfg_if! {
     ))] {
         mod futex;
         pub use futex::Parker;
-    } else if #[cfg(windows)] {
-        pub use crate::sys::thread_parker::Parker;
-    } else if #[cfg(target_family = "unix")] {
+    } else if #[cfg(target_os = "solid_asp3")] {
+        mod wait_flag;
+        pub use wait_flag::Parker;
+    } else if #[cfg(any(windows, target_family = "unix"))] {
         pub use crate::sys::thread_parker::Parker;
     } else {
         mod generic;
diff --git a/library/std/src/sys_common/thread_parker/wait_flag.rs b/library/std/src/sys_common/thread_parker/wait_flag.rs
new file mode 100644
index 0000000000000..6561c186655a5
--- /dev/null
+++ b/library/std/src/sys_common/thread_parker/wait_flag.rs
@@ -0,0 +1,102 @@
+//! A wait-flag-based thread parker.
+//!
+//! Some operating systems provide low-level parking primitives like wait counts,
+//! event flags or semaphores which are not susceptible to race conditions (meaning
+//! the wakeup can occur before the wait operation). To implement the `std` thread
+//! parker on top of these primitives, we only have to ensure that parking is fast
+//! when the thread token is available, the atomic ordering guarantees are maintained
+//! and spurious wakeups are minimized.
+//!
+//! To achieve this, this parker uses an atomic variable with three states: `EMPTY`,
+//! `PARKED` and `NOTIFIED`:
+//! * `EMPTY` means the token has not been made available, but the thread is not
+//!    currently waiting on it.
+//! * `PARKED` means the token is not available and the thread is parked.
+//! * `NOTIFIED` means the token is available.
+//!
+//! `park` and `park_timeout` change the state from `EMPTY` to `PARKED` and from
+//! `NOTIFIED` to `EMPTY`. If the state was `NOTIFIED`, the thread was unparked and
+//! execution can continue without calling into the OS. If the state was `EMPTY`,
+//! the token is not available and the thread waits on the primitive (here called
+//! "wait flag").
+//!
+//! `unpark` changes the state to `NOTIFIED`. If the state was `PARKED`, the thread
+//! is or will be sleeping on the wait flag, so we raise it.
+
+use crate::pin::Pin;
+use crate::sync::atomic::AtomicI8;
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::sys::wait_flag::WaitFlag;
+use crate::time::Duration;
+
+const EMPTY: i8 = 0;
+const PARKED: i8 = -1;
+const NOTIFIED: i8 = 1;
+
+pub struct Parker {
+    state: AtomicI8,
+    wait_flag: WaitFlag,
+}
+
+impl Parker {
+    /// Construct a parker for the current thread. The UNIX parker
+    /// implementation requires this to happen in-place.
+    pub unsafe fn new(parker: *mut Parker) {
+        parker.write(Parker { state: AtomicI8::new(EMPTY), wait_flag: WaitFlag::new() })
+    }
+
+    // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
+    pub unsafe fn park(self: Pin<&Self>) {
+        match self.state.fetch_sub(1, Acquire) {
+            // NOTIFIED => EMPTY
+            NOTIFIED => return,
+            // EMPTY => PARKED
+            EMPTY => (),
+            _ => panic!("inconsistent park state"),
+        }
+
+        // Avoid waking up from spurious wakeups (these are quite likely, see below).
+        loop {
+            self.wait_flag.wait();
+
+            match self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Relaxed) {
+                Ok(_) => return,
+                Err(PARKED) => (),
+                Err(_) => panic!("inconsistent park state"),
+            }
+        }
+    }
+
+    // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
+    pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
+        match self.state.fetch_sub(1, Acquire) {
+            NOTIFIED => return,
+            EMPTY => (),
+            _ => panic!("inconsistent park state"),
+        }
+
+        self.wait_flag.wait_timeout(dur);
+
+        // Either a wakeup or a timeout occurred. Wakeups may be spurious, as there can be
+        // a race condition when `unpark` is performed between receiving the timeout and
+        // resetting the state, resulting in the eventflag being set unnecessarily. `park`
+        // is protected against this by looping until the token is actually given, but
+        // here we cannot easily tell.
+
+        // Use `swap` to provide acquire ordering.
+        match self.state.swap(EMPTY, Acquire) {
+            NOTIFIED => (),
+            PARKED => (),
+            _ => panic!("inconsistent park state"),
+        }
+    }
+
+    // This implementation doesn't require `Pin`, but other implementations do.
+    pub fn unpark(self: Pin<&Self>) {
+        let state = self.state.swap(NOTIFIED, Release);
+
+        if state == PARKED {
+            self.wait_flag.raise();
+        }
+    }
+}
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index b2014f462bd34..759a59e1f98d2 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -38,7 +38,7 @@ use crate::error::Error;
 use crate::fmt;
 use crate::ops::{Add, AddAssign, Sub, SubAssign};
 use crate::sys::time;
-use crate::sys_common::FromInner;
+use crate::sys_common::{FromInner, IntoInner};
 
 #[stable(feature = "time", since = "1.3.0")]
 pub use core::time::Duration;
@@ -686,3 +686,9 @@ impl FromInner<time::SystemTime> for SystemTime {
         SystemTime(time)
     }
 }
+
+impl IntoInner<time::SystemTime> for SystemTime {
+    fn into_inner(self) -> time::SystemTime {
+        self.0
+    }
+}
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index b4b7790eebba1..5d0756d30fb53 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -983,42 +983,51 @@ table,
 	font-weight: normal;
 }
 
-body.blur > :not(#help) {
-	filter: blur(8px);
-	-webkit-filter: blur(8px);
-	opacity: .7;
+.popover {
+	font-size: 1rem;
+	position: absolute;
+	right: 0;
+	z-index: 2;
+	display: block;
+	margin-top: 7px;
+	border-radius: 3px;
+	border: 1px solid;
+	font-size: 1rem;
 }
 
-#help {
-	width: 100%;
-	height: 100vh;
-	position: fixed;
-	top: 0;
-	left: 0;
-	display: flex;
-	justify-content: center;
-	align-items: center;
+/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */
+.popover::before {
+	content: '';
+	position: absolute;
+	right: 11px;
+	border: solid;
+	border-width: 1px 1px 0 0;
+	display: inline-block;
+	padding: 4px;
+	transform: rotate(-45deg);
+	top: -5px;
 }
-#help > div {
-	flex: 0 0 auto;
-	box-shadow: 0 0 6px rgba(0,0,0,.2);
-	width: 550px;
-	height: auto;
-	border: 1px solid;
+
+#help-button .popover {
+	max-width: 600px;
 }
-#help dt {
+
+#help-button .popover::before {
+	right: 48px;
+}
+
+#help-button dt {
 	float: left;
 	clear: left;
 	display: block;
 	margin-right: 0.5rem;
 }
-#help span.top, #help span.bottom {
+#help-button span.top, #help-button span.bottom {
 	text-align: center;
 	display: block;
 	font-size: 1.125rem;
-
 }
-#help span.top {
+#help-button span.top {
 	text-align: center;
 	display: block;
 	margin: 10px 0;
@@ -1026,17 +1035,17 @@ body.blur > :not(#help) {
 	padding-bottom: 4px;
 	margin-bottom: 6px;
 }
-#help span.bottom {
+#help-button span.bottom {
 	clear: both;
 	border-top: 1px solid;
 }
-#help dd { margin: 5px 35px; }
-#help .infos { padding-left: 0; }
-#help h1, #help h2 { margin-top: 0; }
-#help > div div {
+.side-by-side {
+	text-align: initial;
+}
+.side-by-side > div {
 	width: 50%;
 	float: left;
-	padding: 0 20px 20px 17px;;
+	padding: 0 20px 20px 17px;
 }
 
 .item-info .stab {
@@ -1391,7 +1400,7 @@ pre.rust {
 #copy-path {
 	height: 34px;
 }
-#settings-menu > a, #help-button, #copy-path {
+#settings-menu > a, #help-button > button, #copy-path {
 	padding: 5px;
 	width: 33px;
 	border: 1px solid;
@@ -1401,9 +1410,8 @@ pre.rust {
 #settings-menu {
 	padding: 0;
 }
-#settings-menu > a {
+#settings-menu > a, #help-button > button {
 	padding: 5px;
-	width: 100%;
 	height: 100%;
 	display: block;
 }
@@ -1420,7 +1428,7 @@ pre.rust {
 	animation: rotating 2s linear infinite;
 }
 
-#help-button {
+#help-button > button {
 	font-family: "Fira Sans", Arial, sans-serif;
 	text-align: center;
 	/* Rare exception to specifying font sizes in rem. Since this is acting
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index 1cd8e39e03648..e531e6ce6bbde 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -86,27 +86,6 @@ input:checked + .slider:before {
 	display: block;
 }
 
-div#settings {
-	position: absolute;
-	right: 0;
-	z-index: 1;
-	display: block;
-	margin-top: 7px;
-	border-radius: 3px;
-	border: 1px solid;
-}
 #settings .setting-line {
 	margin: 1.2em 0.6em;
 }
-/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */
-div#settings::before {
-	content: '';
-	position: absolute;
-	right: 11px;
-	border: solid;
-	border-width: 1px 1px 0 0;
-	display: inline-block;
-	padding: 4px;
-	transform: rotate(-45deg);
-	top: -5px;
-}
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 5b37ecf19da94..b7d0db1f0020f 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -5,7 +5,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 
 /* General structure and fonts */
 
-body, #settings-menu #settings, #settings-menu #settings::before {
+body, .popover, .popover::before {
 	background-color: #0f1419;
 	color: #c5c5c5;
 }
@@ -567,7 +567,7 @@ kbd {
 	box-shadow: inset 0 -1px 0 #5c6773;
 }
 
-#settings-menu > a, #help-button {
+#settings-menu > a, #help-button > button {
 	border-color: #5c6773;
 	background-color: #0f1419;
 	color: #fff;
@@ -577,7 +577,8 @@ kbd {
 	filter: invert(100);
 }
 
-#settings-menu #settings, #settings-menu #settings::before {
+.popover, .popover::before,
+#help-button span.top, #help-button span.bottom {
 	border-color: #5c6773;
 }
 
@@ -592,7 +593,7 @@ kbd {
 }
 
 #settings-menu > a:hover, #settings-menu > a:focus,
-#help-button:hover, #help-button:focus {
+#help-button > button:hover, #help-button > button:focus {
 	border-color: #e0e0e0;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index ffb59f7762b6d..eb64ef3e7710b 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -1,4 +1,4 @@
-body, #settings-menu #settings, #settings-menu #settings::before {
+body, .popover, .popover::before {
 	background-color: #353535;
 	color: #ddd;
 }
@@ -442,18 +442,19 @@ kbd {
 	box-shadow: inset 0 -1px 0 #c6cbd1;
 }
 
-#settings-menu > a, #help-button {
+#settings-menu > a, #help-button > button {
 	border-color: #e0e0e0;
 	background: #f0f0f0;
 	color: #000;
 }
 
 #settings-menu > a:hover, #settings-menu > a:focus,
-#help-button:hover, #help-button:focus {
+#help-button > button:hover, #help-button > button:focus {
 	border-color: #ffb900;
 }
 
-#settings-menu #settings, #settings-menu #settings::before {
+.popover, .popover::before,
+#help-button span.top, #help-button span.bottom {
 	border-color: #d2d2d2;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index ba798ee2a0eea..00cdf83589716 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -1,6 +1,6 @@
 /* General structure and fonts */
 
-body, #settings-menu #settings, #settings-menu #settings::before {
+body, .popover, .popover::before {
 	background-color: white;
 	color: black;
 }
@@ -427,17 +427,18 @@ kbd {
 	box-shadow: inset 0 -1px 0 #c6cbd1;
 }
 
-#settings-menu > a, #help-button {
+#settings-menu > a, #help-button > button {
 	border-color: #e0e0e0;
 	background-color: #fff;
 }
 
 #settings-menu > a:hover, #settings-menu > a:focus,
-#help-button:hover, #help-button:focus {
+#help-button > button:hover, #help-button > button:focus {
 	border-color: #717171;
 }
 
-#settings-menu #settings, #settings-menu #settings::before {
+.popover, .popover::before,
+#help-button span.top, #help-button span.bottom {
 	border-color: #DDDDDD;
 }
 
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index b320db9104612..70dbfd4442540 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -63,6 +63,24 @@ function showMain() {
     removeClass(document.getElementById(MAIN_ID), "hidden");
 }
 
+function elemIsInParent(elem, parent) {
+    while (elem && elem !== document.body) {
+        if (elem === parent) {
+            return true;
+        }
+        elem = elem.parentElement;
+    }
+    return false;
+}
+
+function blurHandler(event, parentElem, hideCallback) {
+    if (!elemIsInParent(document.activeElement, parentElem) &&
+        !elemIsInParent(event.relatedTarget, parentElem)
+    ) {
+        hideCallback();
+    }
+}
+
 (function() {
     window.rootPath = getVar("root-path");
     window.currentCrate = getVar("current-crate");
@@ -104,20 +122,21 @@ const MAIN_ID = "main-content";
 const SETTINGS_BUTTON_ID = "settings-menu";
 const ALTERNATIVE_DISPLAY_ID = "alternative-display";
 const NOT_DISPLAYED_ID = "not-displayed";
+const HELP_BUTTON_ID = "help-button";
 
 function getSettingsButton() {
     return document.getElementById(SETTINGS_BUTTON_ID);
 }
 
+function getHelpButton() {
+    return document.getElementById(HELP_BUTTON_ID);
+}
+
 // Returns the current URL without any query parameter or hash.
 function getNakedUrl() {
     return window.location.href.split("?")[0].split("#")[0];
 }
 
-window.hideSettings = () => {
-    // Does nothing by default.
-};
-
 /**
  * This function inserts `newNode` after `referenceNode`. It doesn't work if `referenceNode`
  * doesn't have a parent node.
@@ -381,55 +400,16 @@ function loadCss(cssFileName) {
         openParentDetails(document.getElementById(id));
     }
 
-    function getHelpElement(build) {
-        if (build) {
-            buildHelperPopup();
-        }
-        return document.getElementById("help");
-    }
-
-    /**
-     * Show the help popup.
-     *
-     * @param {boolean} display    - Whether to show or hide the popup
-     * @param {Event}   ev         - The event that triggered this call
-     * @param {Element} [help]     - The help element if it already exists
-     */
-    function displayHelp(display, ev, help) {
-        if (display) {
-            help = help ? help : getHelpElement(true);
-            if (hasClass(help, "hidden")) {
-                ev.preventDefault();
-                removeClass(help, "hidden");
-                addClass(document.body, "blur");
-            }
-        } else {
-            // No need to build the help popup if we want to hide it in case it hasn't been
-            // built yet...
-            help = help ? help : getHelpElement(false);
-            if (help && !hasClass(help, "hidden")) {
-                ev.preventDefault();
-                addClass(help, "hidden");
-                removeClass(document.body, "blur");
-            }
-        }
-    }
-
     function handleEscape(ev) {
         searchState.clearInputTimeout();
-        const help = getHelpElement(false);
-        if (help && !hasClass(help, "hidden")) {
-            displayHelp(false, ev, help);
-        } else {
-            switchDisplayedElement(null);
-            if (browserSupportsHistoryApi()) {
-                history.replaceState(null, window.currentCrate + " - Rust",
-                    getNakedUrl() + window.location.hash);
-            }
-            ev.preventDefault();
+        switchDisplayedElement(null);
+        if (browserSupportsHistoryApi()) {
+            history.replaceState(null, window.currentCrate + " - Rust",
+                getNakedUrl() + window.location.hash);
         }
+        ev.preventDefault();
         searchState.defocus();
-        window.hideSettings();
+        window.hidePopoverMenus();
     }
 
     const disableShortcuts = getSettingValue("disable-shortcuts") === "true";
@@ -453,7 +433,6 @@ function loadCss(cssFileName) {
 
             case "s":
             case "S":
-                displayHelp(false, ev);
                 ev.preventDefault();
                 searchState.focus();
                 break;
@@ -465,7 +444,7 @@ function loadCss(cssFileName) {
                 break;
 
             case "?":
-                displayHelp(true, ev);
+                showHelp();
                 break;
 
             default:
@@ -796,9 +775,6 @@ function loadCss(cssFileName) {
             elem.addEventListener("click", f);
         }
     }
-    handleClick("help-button", ev => {
-        displayHelp(true, ev);
-    });
     handleClick(MAIN_ID, () => {
         hideSidebar();
     });
@@ -842,24 +818,16 @@ function loadCss(cssFileName) {
         });
     }
 
-    let buildHelperPopup = () => {
-        const popup = document.createElement("aside");
-        addClass(popup, "hidden");
-        popup.id = "help";
-
-        popup.addEventListener("click", ev => {
-            if (ev.target === popup) {
-                // Clicked the blurred zone outside the help popup; dismiss help.
-                displayHelp(false, ev);
-            }
-        });
+    function helpBlurHandler(event) {
+        blurHandler(event, getHelpButton(), window.hidePopoverMenus);
+    }
 
+    function buildHelpMenu() {
         const book_info = document.createElement("span");
         book_info.className = "top";
         book_info.innerHTML = "You can find more information in \
             <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
 
-        const container = document.createElement("div");
         const shortcuts = [
             ["?", "Show this help dialog"],
             ["S", "Focus the search field"],
@@ -895,24 +863,85 @@ function loadCss(cssFileName) {
         addClass(div_infos, "infos");
         div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
 
-        container.appendChild(book_info);
-        container.appendChild(div_shortcuts);
-        container.appendChild(div_infos);
-
         const rustdoc_version = document.createElement("span");
         rustdoc_version.className = "bottom";
         const rustdoc_version_code = document.createElement("code");
         rustdoc_version_code.innerText = "rustdoc " + getVar("rustdoc-version");
         rustdoc_version.appendChild(rustdoc_version_code);
 
+        const container = document.createElement("div");
+        container.className = "popover";
+        container.style.display = "none";
+
+        const side_by_side = document.createElement("div");
+        side_by_side.className = "side-by-side";
+        side_by_side.appendChild(div_shortcuts);
+        side_by_side.appendChild(div_infos);
+
+        container.appendChild(book_info);
+        container.appendChild(side_by_side);
         container.appendChild(rustdoc_version);
 
-        popup.appendChild(container);
-        insertAfter(popup, document.querySelector("main"));
-        // So that it's only built once and then it'll do nothing when called!
-        buildHelperPopup = () => {};
+        const help_button = getHelpButton();
+        help_button.appendChild(container);
+
+        container.onblur = helpBlurHandler;
+        container.onclick = event => {
+            event.preventDefault();
+        };
+        help_button.onblur = helpBlurHandler;
+        help_button.children[0].onblur = helpBlurHandler;
+
+        return container;
+    }
+
+    /**
+     * Hide all the popover menus.
+     */
+    window.hidePopoverMenus = function() {
+        onEachLazy(document.querySelectorAll(".search-container .popover"), elem => {
+            elem.style.display = "none";
+        });
     };
 
+    /**
+     * Returns the help menu element (not the button).
+     *
+     * @param {boolean} buildNeeded - If this argument is `false`, the help menu element won't be
+     *                                built if it doesn't exist.
+     *
+     * @return {HTMLElement}
+     */
+    function getHelpMenu(buildNeeded) {
+        let menu = getHelpButton().querySelector(".popover");
+        if (!menu && buildNeeded) {
+            menu = buildHelpMenu();
+        }
+        return menu;
+    }
+
+    /**
+     * Show the help popup menu.
+     */
+    function showHelp() {
+        const menu = getHelpMenu(true);
+        if (menu.style.display === "none") {
+            menu.style.display = "";
+        }
+    }
+
+    document.querySelector(`#${HELP_BUTTON_ID} > button`).addEventListener("click", event => {
+        const target = event.target;
+        if (target.tagName !== "BUTTON" || target.parentElement.id !== HELP_BUTTON_ID) {
+            return;
+        }
+        const menu = getHelpMenu(true);
+        const shouldShowHelp = menu.style.display === "none";
+        if (shouldShowHelp) {
+            showHelp();
+        }
+    });
+
     setMobileTopbar();
     addSidebarItems();
     addSidebarCrates();
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 41bf0ec895580..797b931afc643 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -1,6 +1,6 @@
 // Local js definitions:
 /* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */
-/* global addClass, removeClass, onEach, onEachLazy */
+/* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */
 /* global MAIN_ID, getVar, getSettingsButton */
 
 "use strict";
@@ -209,6 +209,7 @@
         const innerHTML = `<div class="settings">${buildSettingsPageSections(settings)}</div>`;
         const el = document.createElement(elementKind);
         el.id = "settings";
+        el.className = "popover";
         el.innerHTML = innerHTML;
 
         if (isSettingsPage) {
@@ -226,23 +227,8 @@
         settingsMenu.style.display = "";
     }
 
-    function elemIsInParent(elem, parent) {
-        while (elem && elem !== document.body) {
-            if (elem === parent) {
-                return true;
-            }
-            elem = elem.parentElement;
-        }
-        return false;
-    }
-
-    function blurHandler(event) {
-        const settingsButton = getSettingsButton();
-        if (!elemIsInParent(document.activeElement, settingsButton) &&
-            !elemIsInParent(event.relatedTarget, settingsButton)
-        ) {
-            window.hideSettings();
-        }
+    function settingsBlurHandler(event) {
+        blurHandler(event, getSettingsButton(), window.hidePopoverMenus);
     }
 
     if (isSettingsPage) {
@@ -254,26 +240,24 @@
         // We replace the existing "onclick" callback.
         const settingsButton = getSettingsButton();
         const settingsMenu = document.getElementById("settings");
-        window.hideSettings = function() {
-            settingsMenu.style.display = "none";
-        };
         settingsButton.onclick = function(event) {
             if (elemIsInParent(event.target, settingsMenu)) {
                 return;
             }
             event.preventDefault();
-            if (settingsMenu.style.display !== "none") {
-                window.hideSettings();
-            } else {
+            const shouldDisplaySettings = settingsMenu.style.display === "none";
+
+            window.hidePopoverMenus();
+            if (shouldDisplaySettings) {
                 displaySettings();
             }
         };
-        settingsButton.onblur = blurHandler;
-        settingsButton.querySelector("a").onblur = blurHandler;
+        settingsButton.onblur = settingsBlurHandler;
+        settingsButton.querySelector("a").onblur = settingsBlurHandler;
         onEachLazy(settingsMenu.querySelectorAll("input"), el => {
-            el.onblur = blurHandler;
+            el.onblur = settingsBlurHandler;
         });
-        settingsMenu.onblur = blurHandler;
+        settingsMenu.onblur = settingsBlurHandler;
     }
 
     // We now wait a bit for the web browser to end re-computing the DOM...
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index c4999e2c74fce..dfb3e4e6a2ccd 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -119,7 +119,9 @@ <h2 class="location"></h2>
                                 spellcheck="false" {# -#}
                                 placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
                                 type="search"> {#- -#}
-                            <button type="button" id="help-button" title="help">?</button> {#- -#}
+                            <div id="help-button" title="help" tabindex="-1"> {#- -#}
+                                <button type="button">?</button> {#- -#}
+                            </div> {#- -#}
                             <div id="settings-menu" tabindex="-1">
                                 <a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
                                     <img width="22" height="22" alt="Change settings" {# -#}
diff --git a/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs b/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs
index e9b28504a907a..47d90b1856be5 100644
--- a/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs
+++ b/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs
@@ -3,7 +3,7 @@
 #![no_core]
 
 extern "rust-intrinsic" {
-    fn atomic_xadd<T>(dst: *mut T, src: T) -> T;
+    fn atomic_xadd_seqcst<T>(dst: *mut T, src: T) -> T;
 }
 
 #[lang = "sized"]
@@ -17,50 +17,50 @@ impl<T: ?Sized> Copy for *mut T {}
 
 #[cfg(target_has_atomic = "8")]
 pub unsafe fn atomic_u8(x: *mut u8) {
-    atomic_xadd(x, 1);
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
 #[cfg(target_has_atomic = "8")]
 pub unsafe fn atomic_i8(x: *mut i8) {
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
 #[cfg(target_has_atomic = "16")]
 pub unsafe fn atomic_u16(x: *mut u16) {
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
 #[cfg(target_has_atomic = "16")]
 pub unsafe fn atomic_i16(x: *mut i16) {
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
 #[cfg(target_has_atomic = "32")]
 pub unsafe fn atomic_u32(x: *mut u32) {
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
 #[cfg(target_has_atomic = "32")]
 pub unsafe fn atomic_i32(x: *mut i32) {
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
 #[cfg(target_has_atomic = "64")]
 pub unsafe fn atomic_u64(x: *mut u64) {
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
 #[cfg(target_has_atomic = "64")]
 pub unsafe fn atomic_i64(x: *mut i64) {
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
 #[cfg(target_has_atomic = "128")]
 pub unsafe fn atomic_u128(x: *mut u128) {
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
 #[cfg(target_has_atomic = "128")]
 pub unsafe fn atomic_i128(x: *mut i128) {
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
 #[cfg(target_has_atomic = "ptr")]
 pub unsafe fn atomic_usize(x: *mut usize) {
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
 #[cfg(target_has_atomic = "ptr")]
 pub unsafe fn atomic_isize(x: *mut isize) {
-    atomic_xadd(x, 1);
+    atomic_xadd_seqcst(x, 1);
 }
diff --git a/src/test/rustdoc-gui/escape-key.goml b/src/test/rustdoc-gui/escape-key.goml
index 8713bf65c8432..d083b0ae0c931 100644
--- a/src/test/rustdoc-gui/escape-key.goml
+++ b/src/test/rustdoc-gui/escape-key.goml
@@ -21,17 +21,6 @@ wait-for: "#alternative-display #search"
 assert-attribute: ("#main-content", {"class": "content hidden"})
 assert-document-property: ({"URL": "index.html?search=test"}, ENDS_WITH)
 
-// Now let's check that when the help popup is displayed and we press Escape, it doesn't
-// hide the search results too.
-click: "#help-button"
-assert-document-property: ({"URL": "index.html?search=test"}, [ENDS_WITH])
-assert-attribute: ("#help", {"class": ""})
-press-key: "Escape"
-wait-for: "#alternative-display #search"
-assert-attribute: ("#help", {"class": "hidden"})
-assert-attribute: ("#main-content", {"class": "content hidden"})
-assert-document-property: ({"URL": "index.html?search=test"}, [ENDS_WITH])
-
 // Check that Escape hides the search results when a search result is focused.
 focus: ".search-input"
 assert: ".search-input:focus"
@@ -39,7 +28,6 @@ press-key: "ArrowDown"
 assert-false: ".search-input:focus"
 assert: "#results a:focus"
 press-key: "Escape"
-assert-attribute: ("#help", {"class": "hidden"})
 wait-for: "#not-displayed #search"
 assert-false: "#alternative-display #search"
 assert-attribute: ("#main-content", {"class": "content"})
diff --git a/src/test/rustdoc-gui/pocket-menu.goml b/src/test/rustdoc-gui/pocket-menu.goml
new file mode 100644
index 0000000000000..ba2986e969a35
--- /dev/null
+++ b/src/test/rustdoc-gui/pocket-menu.goml
@@ -0,0 +1,72 @@
+// This test ensures that the "pocket menus" are working as expected.
+goto: file://|DOC_PATH|/test_docs/index.html
+// First we check that the help menu doesn't exist yet.
+assert-false: "#help-button .popover"
+// Then we display the help menu.
+click: "#help-button"
+assert: "#help-button .popover"
+assert-css: ("#help-button .popover", {"display": "block"})
+
+// Now we click somewhere else on the page to ensure it is handling the blur event
+// correctly.
+click: ".sidebar"
+assert-css: ("#help-button .popover", {"display": "none"})
+
+// Now we will check that we cannot have two "pocket menus" displayed at the same time.
+click: "#help-button"
+assert-css: ("#help-button .popover", {"display": "block"})
+click: "#settings-menu"
+assert-css: ("#help-button .popover", {"display": "none"})
+assert-css: ("#settings-menu .popover", {"display": "block"})
+
+// Now the other way.
+click: "#help-button"
+assert-css: ("#help-button .popover", {"display": "block"})
+assert-css: ("#settings-menu .popover", {"display": "none"})
+
+// We check the borders color now:
+
+// Ayu theme
+local-storage: {
+    "rustdoc-theme": "ayu",
+    "rustdoc-use-system-theme": "false",
+}
+reload:
+
+click: "#help-button"
+assert-css: (
+    "#help-button .popover",
+    {"display": "block", "border-color": "rgb(92, 103, 115)"},
+)
+compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
+compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
+
+// Dark theme
+local-storage: {
+    "rustdoc-theme": "dark",
+    "rustdoc-use-system-theme": "false",
+}
+reload:
+
+click: "#help-button"
+assert-css: (
+    "#help-button .popover",
+    {"display": "block", "border-color": "rgb(210, 210, 210)"},
+)
+compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
+compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
+
+// Light theme
+local-storage: {
+    "rustdoc-theme": "light",
+    "rustdoc-use-system-theme": "false",
+}
+reload:
+
+click: "#help-button"
+assert-css: (
+    "#help-button .popover",
+    {"display": "block", "border-color": "rgb(221, 221, 221)"},
+)
+compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
+compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
diff --git a/src/test/rustdoc-gui/shortcuts.goml b/src/test/rustdoc-gui/shortcuts.goml
index 37a7c1662949d..1f20a0eaa9982 100644
--- a/src/test/rustdoc-gui/shortcuts.goml
+++ b/src/test/rustdoc-gui/shortcuts.goml
@@ -8,7 +8,6 @@ press-key: "Escape"
 assert-false: "input.search-input:focus"
 // We now check for the help popup.
 press-key: "?"
-assert-css: ("#help", {"display": "flex"})
-assert-false: "#help.hidden"
+assert-css: ("#help-button .popover", {"display": "block"})
 press-key: "Escape"
-assert-css: ("#help.hidden", {"display": "none"})
+assert-css: ("#help-button .popover", {"display": "none"})
diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.rs b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
index 817d8531da905..d6f63d44ba6a8 100644
--- a/src/test/ui-fulldeps/internal-lints/diagnostics.rs
+++ b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
@@ -16,14 +16,14 @@ use rustc_session::{parse::ParseSess, SessionDiagnostic};
 use rustc_span::Span;
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "parser-expect-path")]
+#[error(parser::expect_path)]
 struct DeriveSessionDiagnostic {
     #[primary_span]
     span: Span,
 }
 
 #[derive(SessionSubdiagnostic)]
-#[note(slug = "note")]
+#[note(parser::add_paren)]
 struct Note {
     #[primary_span]
     span: Span,
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index 84d5de173091b..7bec1897fa53e 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -26,15 +26,15 @@ use rustc_errors::Applicability;
 extern crate rustc_session;
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "hello-world")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct Hello {}
 
 #[derive(SessionDiagnostic)]
-#[warning(code = "E0123", slug = "hello-world")]
+#[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct HelloWarn {}
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 //~^ ERROR `#[derive(SessionDiagnostic)]` can only be used on structs
 enum SessionDiagnosticOnEnum {
     Foo,
@@ -42,13 +42,13 @@ enum SessionDiagnosticOnEnum {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[error = "E0123"]
 //~^ ERROR `#[error = ...]` is not a valid attribute
 struct WrongStructAttrStyle {}
 
 #[derive(SessionDiagnostic)]
-#[nonsense(code = "E0123", slug = "foo")]
+#[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
 //~^ ERROR `#[nonsense(...)]` is not a valid attribute
 //~^^ ERROR diagnostic kind not specified
 //~^^^ ERROR cannot find attribute `nonsense` in this scope
@@ -57,31 +57,39 @@ struct InvalidStructAttr {}
 #[derive(SessionDiagnostic)]
 #[error("E0123")]
 //~^ ERROR `#[error("...")]` is not a valid attribute
-//~^^ ERROR `slug` not specified
+//~^^ ERROR diagnostic slug not specified
 struct InvalidLitNestedAttr {}
 
 #[derive(SessionDiagnostic)]
-#[error(nonsense, code = "E0123", slug = "foo")]
-//~^ ERROR `#[error(nonsense)]` is not a valid attribute
+#[error(nonsense, code = "E0123")]
+//~^ ERROR cannot find value `nonsense` in module `rustc_errors::fluent`
 struct InvalidNestedStructAttr {}
 
 #[derive(SessionDiagnostic)]
 #[error(nonsense("foo"), code = "E0123", slug = "foo")]
 //~^ ERROR `#[error(nonsense(...))]` is not a valid attribute
+//~^^ ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr1 {}
 
 #[derive(SessionDiagnostic)]
 #[error(nonsense = "...", code = "E0123", slug = "foo")]
 //~^ ERROR `#[error(nonsense = ...)]` is not a valid attribute
+//~^^ ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr2 {}
 
 #[derive(SessionDiagnostic)]
 #[error(nonsense = 4, code = "E0123", slug = "foo")]
 //~^ ERROR `#[error(nonsense = ...)]` is not a valid attribute
+//~^^ ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr3 {}
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
+//~^ ERROR `#[error(slug = ...)]` is not a valid attribute
+struct InvalidNestedStructAttr4 {}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct WrongPlaceField {
     #[suggestion = "bar"]
     //~^ ERROR `#[suggestion = ...]` is not a valid attribute
@@ -89,44 +97,45 @@ struct WrongPlaceField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
-#[error(code = "E0456", slug = "bar")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
 //~^ ERROR specified multiple times
 //~^^ ERROR specified multiple times
 //~^^^ ERROR specified multiple times
 struct ErrorSpecifiedTwice {}
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
-#[warning(code = "E0293", slug = "bar")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
 //~^ ERROR specified multiple times
 //~^^ ERROR specified multiple times
 //~^^^ ERROR specified multiple times
 struct WarnSpecifiedAfterError {}
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0456", code = "E0457", slug = "bar")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
 //~^ ERROR specified multiple times
 struct CodeSpecifiedTwice {}
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0456", slug = "foo", slug = "bar")]
-//~^ ERROR specified multiple times
+#[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
+//~^ ERROR `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
 struct SlugSpecifiedTwice {}
 
 #[derive(SessionDiagnostic)]
 struct KindNotProvided {} //~ ERROR diagnostic kind not specified
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0456")] //~ ERROR `slug` not specified
+#[error(code = "E0456")]
+//~^ ERROR diagnostic slug not specified
 struct SlugNotProvided {}
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound)]
 struct CodeNotProvided {}
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct MessageWrongType {
     #[primary_span]
     //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span`
@@ -134,7 +143,7 @@ struct MessageWrongType {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct InvalidPathFieldAttr {
     #[nonsense]
     //~^ ERROR `#[nonsense]` is not a valid attribute
@@ -143,34 +152,34 @@ struct InvalidPathFieldAttr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithField {
     name: String,
-    #[label = "bar"]
+    #[label(typeck::label)]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithMessageAppliedToField {
-    #[label = "bar"]
-    //~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span`
+    #[label(typeck::label)]
+    //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span`
     name: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithNonexistentField {
-    #[suggestion(message = "bar", code = "{name}")]
+    #[suggestion(typeck::suggestion, code = "{name}")]
     //~^ ERROR `name` doesn't refer to a field on this type
     suggestion: (Span, Applicability),
 }
 
 #[derive(SessionDiagnostic)]
 //~^ ERROR invalid format string: expected `'}'`
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorMissingClosingBrace {
-    #[suggestion(message = "bar", code = "{name")]
+    #[suggestion(typeck::suggestion, code = "{name")]
     suggestion: (Span, Applicability),
     name: String,
     val: usize,
@@ -178,48 +187,48 @@ struct ErrorMissingClosingBrace {
 
 #[derive(SessionDiagnostic)]
 //~^ ERROR invalid format string: unmatched `}`
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorMissingOpeningBrace {
-    #[suggestion(message = "bar", code = "name}")]
+    #[suggestion(typeck::suggestion, code = "name}")]
     suggestion: (Span, Applicability),
     name: String,
     val: usize,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelOnSpan {
-    #[label = "bar"]
+    #[label(typeck::label)]
     sp: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelOnNonSpan {
-    #[label = "bar"]
-    //~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span`
+    #[label(typeck::label)]
+    //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span`
     id: u32,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct Suggest {
-    #[suggestion(message = "bar", code = "This is the suggested code")]
-    #[suggestion_short(message = "qux", code = "This is the suggested code")]
-    #[suggestion_hidden(message = "foobar", code = "This is the suggested code")]
-    #[suggestion_verbose(message = "fooqux", code = "This is the suggested code")]
+    #[suggestion(typeck::suggestion, code = "This is the suggested code")]
+    #[suggestion_short(typeck::suggestion, code = "This is the suggested code")]
+    #[suggestion_hidden(typeck::suggestion, code = "This is the suggested code")]
+    #[suggestion_verbose(typeck::suggestion, code = "This is the suggested code")]
     suggestion: (Span, Applicability),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithoutCode {
-    #[suggestion(message = "bar")]
+    #[suggestion(typeck::suggestion)]
     suggestion: (Span, Applicability),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithBadKey {
     #[suggestion(nonsense = "bar")]
     //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute
@@ -227,7 +236,7 @@ struct SuggestWithBadKey {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithShorthandMsg {
     #[suggestion(msg = "bar")]
     //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute
@@ -235,91 +244,91 @@ struct SuggestWithShorthandMsg {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithoutMsg {
     #[suggestion(code = "bar")]
     suggestion: (Span, Applicability),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithTypesSwapped {
-    #[suggestion(message = "bar", code = "This is suggested code")]
+    #[suggestion(typeck::suggestion, code = "This is suggested code")]
     suggestion: (Applicability, Span),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithWrongTypeApplicabilityOnly {
-    #[suggestion(message = "bar", code = "This is suggested code")]
+    #[suggestion(typeck::suggestion, code = "This is suggested code")]
     //~^ ERROR wrong field type for suggestion
     suggestion: Applicability,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithSpanOnly {
-    #[suggestion(message = "bar", code = "This is suggested code")]
+    #[suggestion(typeck::suggestion, code = "This is suggested code")]
     suggestion: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithDuplicateSpanAndApplicability {
-    #[suggestion(message = "bar", code = "This is suggested code")]
+    #[suggestion(typeck::suggestion, code = "This is suggested code")]
     //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span`
     suggestion: (Span, Span, Applicability),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithDuplicateApplicabilityAndSpan {
-    #[suggestion(message = "bar", code = "This is suggested code")]
+    #[suggestion(typeck::suggestion, code = "This is suggested code")]
     //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one
     suggestion: (Applicability, Applicability, Span),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct WrongKindOfAnnotation {
-    #[label("bar")]
-    //~^ ERROR `#[label(...)]` is not a valid attribute
+    #[label = "bar"]
+    //~^ ERROR `#[label = ...]` is not a valid attribute
     z: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct OptionsInErrors {
-    #[label = "bar"]
+    #[label(typeck::label)]
     label: Option<Span>,
-    #[suggestion(message = "bar")]
+    #[suggestion(typeck::suggestion)]
     opt_sugg: Option<(Span, Applicability)>,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0456", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
 struct MoveOutOfBorrowError<'tcx> {
     name: Ident,
     ty: Ty<'tcx>,
     #[primary_span]
-    #[label = "bar"]
+    #[label(typeck::label)]
     span: Span,
-    #[label = "qux"]
+    #[label(typeck::label)]
     other_span: Span,
-    #[suggestion(message = "bar", code = "{name}.clone()")]
+    #[suggestion(typeck::suggestion, code = "{name}.clone()")]
     opt_sugg: Option<(Span, Applicability)>,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithLifetime<'a> {
-    #[label = "bar"]
+    #[label(typeck::label)]
     span: Span,
     name: &'a str,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithDefaultLabelAttr<'a> {
     #[label]
     span: Span,
@@ -328,7 +337,7 @@ struct ErrorWithDefaultLabelAttr<'a> {
 
 #[derive(SessionDiagnostic)]
 //~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ArgFieldWithoutSkip {
     #[primary_span]
     span: Span,
@@ -336,7 +345,7 @@ struct ArgFieldWithoutSkip {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ArgFieldWithSkip {
     #[primary_span]
     span: Span,
@@ -347,132 +356,132 @@ struct ArgFieldWithSkip {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedNote {
     #[note]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedNoteCustom {
-    #[note = "bar"]
+    #[note(typeck::note)]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[note]
 struct ErrorWithNote {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
-#[note = "bar"]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[note(typeck::note)]
 struct ErrorWithNoteCustom {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedHelp {
     #[help]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedHelpCustom {
-    #[help = "bar"]
+    #[help(typeck::help)]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[help]
 struct ErrorWithHelp {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
-#[help = "bar"]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[help(typeck::help)]
 struct ErrorWithHelpCustom {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
 #[help]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithHelpWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[help = "bar"]
-#[error(code = "E0123", slug = "foo")]
+#[help(typeck::help)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithHelpCustomWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
 #[note]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithNoteWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[note = "bar"]
-#[error(code = "E0123", slug = "foo")]
+#[note(typeck::note)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithNoteCustomWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ApplicabilityInBoth {
-    #[suggestion(message = "bar", code = "...", applicability = "maybe-incorrect")]
+    #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
     //~^ ERROR applicability cannot be set in both the field and attribute
     suggestion: (Span, Applicability),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct InvalidApplicability {
-    #[suggestion(message = "bar", code = "...", applicability = "batman")]
+    #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
     //~^ ERROR invalid applicability
     suggestion: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ValidApplicability {
-    #[suggestion(message = "bar", code = "...", applicability = "maybe-incorrect")]
+    #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
     suggestion: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct NoApplicability {
-    #[suggestion(message = "bar", code = "...")]
+    #[suggestion(typeck::suggestion, code = "...")]
     suggestion: Span,
 }
 
 #[derive(SessionSubdiagnostic)]
-#[note(slug = "note")]
+#[note(parser::add_paren)]
 struct Note;
 
 #[derive(SessionDiagnostic)]
-#[error(slug = "subdiagnostic")]
+#[error(typeck::ambiguous_lifetime_bound)]
 struct Subdiagnostic {
     #[subdiagnostic]
     note: Note,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct VecField {
     #[primary_span]
     #[label]
@@ -480,23 +489,47 @@ struct VecField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct UnitField {
     #[primary_span]
     spans: Span,
     #[help]
     foo: (),
-    #[help = "a"]
+    #[help(typeck::help)]
     bar: (),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0123", slug = "foo")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct OptUnitField {
     #[primary_span]
     spans: Span,
     #[help]
     foo: Option<()>,
-    #[help = "a"]
+    #[help(typeck::help)]
     bar: Option<()>,
 }
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct LabelWithTrailingPath {
+    #[label(typeck::label, foo)]
+    //~^ ERROR `#[label(...)]` is not a valid attribute
+    span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct LabelWithTrailingNameValue {
+    #[label(typeck::label, foo = "...")]
+    //~^ ERROR `#[label(...)]` is not a valid attribute
+    span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct LabelWithTrailingList {
+    #[label(typeck::label, foo("..."))]
+    //~^ ERROR `#[label(...)]` is not a valid attribute
+    span: Span,
+}
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 85ea44ec278c0..0d9690e1f5a99 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -1,7 +1,7 @@
 error: `#[derive(SessionDiagnostic)]` can only be used on structs
   --> $DIR/diagnostic-derive.rs:37:1
    |
-LL | / #[error(code = "E0123", slug = "foo")]
+LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 LL | |
 LL | | enum SessionDiagnosticOnEnum {
 LL | |     Foo,
@@ -18,15 +18,15 @@ LL | #[error = "E0123"]
 error: `#[nonsense(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:51:1
    |
-LL | #[nonsense(code = "E0123", slug = "foo")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: only `error` and `warning` are valid attributes
+   = help: only `error`, `warning`, `help` and `note` are valid attributes
 
 error: diagnostic kind not specified
   --> $DIR/diagnostic-derive.rs:51:1
    |
-LL | / #[nonsense(code = "E0123", slug = "foo")]
+LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
 LL | |
 LL | |
 LL | |
@@ -40,8 +40,10 @@ error: `#[error("...")]` is not a valid attribute
    |
 LL | #[error("E0123")]
    |         ^^^^^^^
+   |
+   = help: first argument of the attribute should be the diagnostic slug
 
-error: `slug` not specified
+error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:58:1
    |
 LL | / #[error("E0123")]
@@ -50,183 +52,215 @@ LL | |
 LL | | struct InvalidLitNestedAttr {}
    | |______________________________^
    |
-   = help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug
-
-error: `#[error(nonsense)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:64:9
-   |
-LL | #[error(nonsense, code = "E0123", slug = "foo")]
-   |         ^^^^^^^^
+   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
 
 error: `#[error(nonsense(...))]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:69:9
    |
 LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")]
    |         ^^^^^^^^^^^^^^^
+   |
+   = help: first argument of the attribute should be the diagnostic slug
+
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:69:1
+   |
+LL | / #[error(nonsense("foo"), code = "E0123", slug = "foo")]
+LL | |
+LL | |
+LL | | struct InvalidNestedStructAttr1 {}
+   | |__________________________________^
+   |
+   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
 
 error: `#[error(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:74:9
+  --> $DIR/diagnostic-derive.rs:75:9
    |
 LL | #[error(nonsense = "...", code = "E0123", slug = "foo")]
    |         ^^^^^^^^^^^^^^^^
    |
-   = help: only `slug` and `code` are valid nested attributes
+   = help: first argument of the attribute should be the diagnostic slug
+
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:75:1
+   |
+LL | / #[error(nonsense = "...", code = "E0123", slug = "foo")]
+LL | |
+LL | |
+LL | | struct InvalidNestedStructAttr2 {}
+   | |__________________________________^
+   |
+   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
 
 error: `#[error(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:79:9
+  --> $DIR/diagnostic-derive.rs:81:9
    |
 LL | #[error(nonsense = 4, code = "E0123", slug = "foo")]
    |         ^^^^^^^^^^^^
+   |
+   = help: first argument of the attribute should be the diagnostic slug
 
-error: `#[suggestion = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:86:5
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:81:1
    |
-LL |     #[suggestion = "bar"]
-   |     ^^^^^^^^^^^^^^^^^^^^^
+LL | / #[error(nonsense = 4, code = "E0123", slug = "foo")]
+LL | |
+LL | |
+LL | | struct InvalidNestedStructAttr3 {}
+   | |__________________________________^
    |
-   = help: only `label`, `note` and `help` are valid field attributes
+   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
 
-error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:93:1
+error: `#[error(slug = ...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:87:59
    |
-LL | #[error(code = "E0456", slug = "bar")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
+   |                                                           ^^^^^^^^^^^^
    |
-note: previously specified here
-  --> $DIR/diagnostic-derive.rs:92:1
+   = help: only `code` is a valid nested attributes following the slug
+
+error: `#[suggestion = ...]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:94:5
    |
-LL | #[error(code = "E0123", slug = "foo")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[suggestion = "bar"]
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:93:16
+  --> $DIR/diagnostic-derive.rs:101:1
    |
-LL | #[error(code = "E0456", slug = "bar")]
-   |                ^^^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:92:16
+  --> $DIR/diagnostic-derive.rs:100:1
    |
-LL | #[error(code = "E0123", slug = "foo")]
-   |                ^^^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:93:32
+  --> $DIR/diagnostic-derive.rs:101:1
    |
-LL | #[error(code = "E0456", slug = "bar")]
-   |                                ^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:92:32
+  --> $DIR/diagnostic-derive.rs:100:1
    |
-LL | #[error(code = "E0123", slug = "foo")]
-   |                                ^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:101:1
+  --> $DIR/diagnostic-derive.rs:101:50
    |
-LL | #[warning(code = "E0293", slug = "bar")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
+   |                                                  ^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:100:1
+  --> $DIR/diagnostic-derive.rs:100:50
    |
-LL | #[error(code = "E0123", slug = "foo")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |                                                  ^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:101:18
+  --> $DIR/diagnostic-derive.rs:109:1
    |
-LL | #[warning(code = "E0293", slug = "bar")]
-   |                  ^^^^^^^
+LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:100:16
+  --> $DIR/diagnostic-derive.rs:108:1
    |
-LL | #[error(code = "E0123", slug = "foo")]
-   |                ^^^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:101:34
+  --> $DIR/diagnostic-derive.rs:109:1
    |
-LL | #[warning(code = "E0293", slug = "bar")]
-   |                                  ^^^^^
+LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:100:32
+  --> $DIR/diagnostic-derive.rs:108:1
    |
-LL | #[error(code = "E0123", slug = "foo")]
-   |                                ^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:108:32
+  --> $DIR/diagnostic-derive.rs:109:52
    |
-LL | #[error(code = "E0456", code = "E0457", slug = "bar")]
-   |                                ^^^^^^^
+LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
+   |                                                    ^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:108:16
+  --> $DIR/diagnostic-derive.rs:108:50
    |
-LL | #[error(code = "E0456", code = "E0457", slug = "bar")]
-   |                ^^^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |                                                  ^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:113:46
+  --> $DIR/diagnostic-derive.rs:116:66
    |
-LL | #[error(code = "E0456", slug = "foo", slug = "bar")]
-   |                                              ^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
+   |                                                                  ^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:113:32
+  --> $DIR/diagnostic-derive.rs:116:50
    |
-LL | #[error(code = "E0456", slug = "foo", slug = "bar")]
-   |                                ^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
+   |                                                  ^^^^^^^
+
+error: `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:121:43
+   |
+LL | #[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic kind not specified
-  --> $DIR/diagnostic-derive.rs:118:1
+  --> $DIR/diagnostic-derive.rs:126:1
    |
 LL | struct KindNotProvided {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use the `#[error(...)]` attribute to create an error
 
-error: `slug` not specified
-  --> $DIR/diagnostic-derive.rs:121:1
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:129:1
    |
 LL | / #[error(code = "E0456")]
+LL | |
 LL | | struct SlugNotProvided {}
    | |_________________________^
    |
-   = help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug
+   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span`
-  --> $DIR/diagnostic-derive.rs:131:5
+  --> $DIR/diagnostic-derive.rs:140:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: `#[nonsense]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:139:5
+  --> $DIR/diagnostic-derive.rs:148:5
    |
 LL |     #[nonsense]
    |     ^^^^^^^^^^^
    |
    = help: only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes
 
-error: the `#[label = ...]` attribute can only be applied to fields of type `Span`
-  --> $DIR/diagnostic-derive.rs:156:5
+error: the `#[label(...)]` attribute can only be applied to fields of type `Span`
+  --> $DIR/diagnostic-derive.rs:165:5
    |
-LL |     #[label = "bar"]
-   |     ^^^^^^^^^^^^^^^^
+LL |     #[label(typeck::label)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `name` doesn't refer to a field on this type
-  --> $DIR/diagnostic-derive.rs:164:42
+  --> $DIR/diagnostic-derive.rs:173:45
    |
-LL |     #[suggestion(message = "bar", code = "{name}")]
-   |                                          ^^^^^^^^
+LL |     #[suggestion(typeck::suggestion, code = "{name}")]
+   |                                             ^^^^^^^^
 
 error: invalid format string: expected `'}'` but string was terminated
-  --> $DIR/diagnostic-derive.rs:169:16
+  --> $DIR/diagnostic-derive.rs:178:16
    |
 LL | #[derive(SessionDiagnostic)]
    |           -    ^ expected `'}'` in format string
@@ -237,7 +271,7 @@ LL | #[derive(SessionDiagnostic)]
    = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: invalid format string: unmatched `}` found
-  --> $DIR/diagnostic-derive.rs:179:15
+  --> $DIR/diagnostic-derive.rs:188:15
    |
 LL | #[derive(SessionDiagnostic)]
    |               ^ unmatched `}` in format string
@@ -245,14 +279,14 @@ LL | #[derive(SessionDiagnostic)]
    = note: if you intended to print `}`, you can escape it using `}}`
    = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: the `#[label = ...]` attribute can only be applied to fields of type `Span`
-  --> $DIR/diagnostic-derive.rs:199:5
+error: the `#[label(...)]` attribute can only be applied to fields of type `Span`
+  --> $DIR/diagnostic-derive.rs:208:5
    |
-LL |     #[label = "bar"]
-   |     ^^^^^^^^^^^^^^^^
+LL |     #[label(typeck::label)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:224:18
+  --> $DIR/diagnostic-derive.rs:233:18
    |
 LL |     #[suggestion(nonsense = "bar")]
    |                  ^^^^^^^^^^^^^^^^
@@ -260,7 +294,7 @@ LL |     #[suggestion(nonsense = "bar")]
    = help: only `message`, `code` and `applicability` are valid field attributes
 
 error: `#[suggestion(msg = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:232:18
+  --> $DIR/diagnostic-derive.rs:241:18
    |
 LL |     #[suggestion(msg = "bar")]
    |                  ^^^^^^^^^^^
@@ -268,9 +302,9 @@ LL |     #[suggestion(msg = "bar")]
    = help: only `message`, `code` and `applicability` are valid field attributes
 
 error: wrong field type for suggestion
-  --> $DIR/diagnostic-derive.rs:254:5
+  --> $DIR/diagnostic-derive.rs:263:5
    |
-LL | /     #[suggestion(message = "bar", code = "This is suggested code")]
+LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
 LL | |     suggestion: Applicability,
    | |_____________________________^
@@ -278,55 +312,77 @@ LL | |     suggestion: Applicability,
    = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
 
 error: type of field annotated with `#[suggestion(...)]` contains more than one `Span`
-  --> $DIR/diagnostic-derive.rs:269:5
+  --> $DIR/diagnostic-derive.rs:278:5
    |
-LL | /     #[suggestion(message = "bar", code = "This is suggested code")]
+LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
 LL | |     suggestion: (Span, Span, Applicability),
    | |___________________________________________^
 
 error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
-  --> $DIR/diagnostic-derive.rs:277:5
+  --> $DIR/diagnostic-derive.rs:286:5
    |
-LL | /     #[suggestion(message = "bar", code = "This is suggested code")]
+LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
 LL | |     suggestion: (Applicability, Applicability, Span),
    | |____________________________________________________^
 
-error: `#[label(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:285:5
-   |
-LL |     #[label("bar")]
-   |     ^^^^^^^^^^^^^^^
+error: `#[label = ...]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:294:5
    |
-   = help: only `suggestion{,_short,_hidden,_verbose}` are valid field attributes
+LL |     #[label = "bar"]
+   |     ^^^^^^^^^^^^^^^^
 
 error: applicability cannot be set in both the field and attribute
-  --> $DIR/diagnostic-derive.rs:436:49
+  --> $DIR/diagnostic-derive.rs:445:52
    |
-LL |     #[suggestion(message = "bar", code = "...", applicability = "maybe-incorrect")]
-   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/diagnostic-derive.rs:444:49
+  --> $DIR/diagnostic-derive.rs:453:52
+   |
+LL |     #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[label(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:516:5
+   |
+LL |     #[label(typeck::label, foo)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[label(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:524:5
+   |
+LL |     #[label(typeck::label, foo = "...")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[label(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:532:5
    |
-LL |     #[suggestion(message = "bar", code = "...", applicability = "batman")]
-   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[label(typeck::label, foo("..."))]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `nonsense` in this scope
   --> $DIR/diagnostic-derive.rs:51:3
    |
-LL | #[nonsense(code = "E0123", slug = "foo")]
+LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
    |   ^^^^^^^^
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:139:7
+  --> $DIR/diagnostic-derive.rs:148:7
    |
 LL |     #[nonsense]
    |       ^^^^^^^^
 
+error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent`
+  --> $DIR/diagnostic-derive.rs:64:9
+   |
+LL | #[error(nonsense, code = "E0123")]
+   |         ^^^^^^^^ not found in `rustc_errors::fluent`
+
 error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-  --> $DIR/diagnostic-derive.rs:329:10
+  --> $DIR/diagnostic-derive.rs:338:10
    |
 LL | #[derive(SessionDiagnostic)]
    |          ^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
@@ -345,6 +401,7 @@ LL |         arg: impl IntoDiagnosticArg,
    |                   ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
    = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 39 previous errors
+error: aborting due to 46 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0425.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index bb406c35c0eef..6f4b6105b3e49 100644
--- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -20,7 +20,7 @@ use rustc_span::Span;
 use rustc_macros::SessionSubdiagnostic;
 
 #[derive(SessionSubdiagnostic)]
-#[label(slug = "label-a")]
+#[label(parser::add_paren)]
 struct A {
     #[primary_span]
     span: Span,
@@ -29,13 +29,13 @@ struct A {
 
 #[derive(SessionSubdiagnostic)]
 enum B {
-    #[label(slug = "label-b-a")]
+    #[label(parser::add_paren)]
     A {
         #[primary_span]
         span: Span,
         var: String,
     },
-    #[label(slug = "label-b-b")]
+    #[label(parser::add_paren)]
     B {
         #[primary_span]
         span: Span,
@@ -44,7 +44,7 @@ enum B {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[label(slug = "label-c")]
+#[label(parser::add_paren)]
 //~^ ERROR label without `#[primary_span]` field
 struct C {
     var: String,
@@ -116,7 +116,8 @@ struct K {
 
 #[derive(SessionSubdiagnostic)]
 #[label(slug)]
-//~^ ERROR `#[label(slug)]` is not a valid attribute
+//~^ ERROR cannot find value `slug` in module `rustc_errors::fluent`
+//~^^ NOTE not found in `rustc_errors::fluent`
 struct L {
     #[primary_span]
     span: Span,
@@ -125,7 +126,7 @@ struct L {
 
 #[derive(SessionSubdiagnostic)]
 #[label()]
-//~^ ERROR `slug` must be set in a `#[label(...)]` attribute
+//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
 struct M {
     #[primary_span]
     span: Span,
@@ -133,7 +134,7 @@ struct M {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[label(code = "...")]
+#[label(parser::add_paren, code = "...")]
 //~^ ERROR `code` is not a valid nested attribute of a `label` attribute
 struct N {
     #[primary_span]
@@ -141,12 +142,21 @@ struct N {
     var: String,
 }
 
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren, applicability = "machine-applicable")]
+//~^ ERROR `applicability` is not a valid nested attribute of a `label` attribute
+struct O {
+    #[primary_span]
+    span: Span,
+    var: String,
+}
+
 #[derive(SessionSubdiagnostic)]
 #[foo]
 //~^ ERROR cannot find attribute `foo` in this scope
 //~^^ ERROR unsupported type attribute for subdiagnostic enum
-enum O {
-    #[label(slug = "...")]
+enum P {
+    #[label(parser::add_paren)]
     A {
         #[primary_span]
         span: Span,
@@ -155,7 +165,7 @@ enum O {
 }
 
 #[derive(SessionSubdiagnostic)]
-enum P {
+enum Q {
     #[bar]
 //~^ ERROR `#[bar]` is not a valid attribute
 //~^^ ERROR cannot find attribute `bar` in this scope
@@ -167,7 +177,7 @@ enum P {
 }
 
 #[derive(SessionSubdiagnostic)]
-enum Q {
+enum R {
     #[bar = "..."]
 //~^ ERROR `#[bar = ...]` is not a valid attribute
 //~^^ ERROR cannot find attribute `bar` in this scope
@@ -179,7 +189,7 @@ enum Q {
 }
 
 #[derive(SessionSubdiagnostic)]
-enum R {
+enum S {
     #[bar = 4]
 //~^ ERROR `#[bar = ...]` is not a valid attribute
 //~^^ ERROR cannot find attribute `bar` in this scope
@@ -191,7 +201,7 @@ enum R {
 }
 
 #[derive(SessionSubdiagnostic)]
-enum S {
+enum T {
     #[bar("...")]
 //~^ ERROR `#[bar("...")]` is not a valid attribute
 //~^^ ERROR cannot find attribute `bar` in this scope
@@ -203,9 +213,9 @@ enum S {
 }
 
 #[derive(SessionSubdiagnostic)]
-enum T {
+enum U {
     #[label(code = "...")]
-//~^ ERROR `code` is not a valid nested attribute of a `label`
+//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
     A {
         #[primary_span]
         span: Span,
@@ -214,8 +224,8 @@ enum T {
 }
 
 #[derive(SessionSubdiagnostic)]
-enum U {
-    #[label(slug = "label-u")]
+enum V {
+    #[label(parser::add_paren)]
     A {
         #[primary_span]
         span: Span,
@@ -230,17 +240,17 @@ enum U {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[label(slug = "...")]
+#[label(parser::add_paren)]
 //~^ ERROR label without `#[primary_span]` field
-struct V {
+struct W {
     #[primary_span]
     //~^ ERROR the `#[primary_span]` attribute can only be applied to fields of type `Span`
     span: String,
 }
 
 #[derive(SessionSubdiagnostic)]
-#[label(slug = "...")]
-struct W {
+#[label(parser::add_paren)]
+struct X {
     #[primary_span]
     span: Span,
     #[applicability]
@@ -249,8 +259,8 @@ struct W {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[label(slug = "...")]
-struct X {
+#[label(parser::add_paren)]
+struct Y {
     #[primary_span]
     span: Span,
     #[bar]
@@ -260,8 +270,8 @@ struct X {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[label(slug = "...")]
-struct Y {
+#[label(parser::add_paren)]
+struct Z {
     #[primary_span]
     span: Span,
     #[bar = "..."]
@@ -271,8 +281,8 @@ struct Y {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[label(slug = "...")]
-struct Z {
+#[label(parser::add_paren)]
+struct AA {
     #[primary_span]
     span: Span,
     #[bar("...")]
@@ -282,8 +292,8 @@ struct Z {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[label(slug = "label-aa")]
-struct AA {
+#[label(parser::add_paren)]
+struct AB {
     #[primary_span]
     span: Span,
     #[skip_arg]
@@ -291,36 +301,35 @@ struct AA {
 }
 
 #[derive(SessionSubdiagnostic)]
-union AB {
+union AC {
 //~^ ERROR unexpected unsupported untagged union
     span: u32,
     b: u64
 }
 
 #[derive(SessionSubdiagnostic)]
-#[label(slug = "label-ac-1")]
+#[label(parser::add_paren)]
 //~^ NOTE previously specified here
 //~^^ NOTE previously specified here
-#[label(slug = "label-ac-2")]
+#[label(parser::add_paren)]
 //~^ ERROR specified multiple times
 //~^^ ERROR specified multiple times
-struct AC {
+struct AD {
     #[primary_span]
     span: Span,
 }
 
 #[derive(SessionSubdiagnostic)]
-#[label(slug = "label-ad-1", slug = "label-ad-2")]
-//~^ ERROR specified multiple times
-//~^^ NOTE previously specified here
-struct AD {
+#[label(parser::add_paren, parser::add_paren)]
+//~^ ERROR `#[label(parser::add_paren)]` is not a valid attribute
+struct AE {
     #[primary_span]
     span: Span,
 }
 
 #[derive(SessionSubdiagnostic)]
-#[label(slug = "label-ad-1")]
-struct AE {
+#[label(parser::add_paren)]
+struct AF {
     #[primary_span]
 //~^ NOTE previously specified here
     span_a: Span,
@@ -330,15 +339,15 @@ struct AE {
 }
 
 #[derive(SessionSubdiagnostic)]
-struct AF {
+struct AG {
 //~^ ERROR subdiagnostic kind not specified
     #[primary_span]
     span: Span,
 }
 
 #[derive(SessionSubdiagnostic)]
-#[suggestion(slug = "suggestion-af", code = "...")]
-struct AG {
+#[suggestion(parser::add_paren, code = "...")]
+struct AH {
     #[primary_span]
     span: Span,
     #[applicability]
@@ -347,8 +356,8 @@ struct AG {
 }
 
 #[derive(SessionSubdiagnostic)]
-enum AH {
-    #[suggestion(slug = "suggestion-ag-a", code = "...")]
+enum AI {
+    #[suggestion(parser::add_paren, code = "...")]
     A {
         #[primary_span]
         span: Span,
@@ -356,7 +365,7 @@ enum AH {
         applicability: Applicability,
         var: String,
     },
-    #[suggestion(slug = "suggestion-ag-b", code = "...")]
+    #[suggestion(parser::add_paren, code = "...")]
     B {
         #[primary_span]
         span: Span,
@@ -367,10 +376,10 @@ enum AH {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[suggestion(slug = "...", code = "...", code = "...")]
+#[suggestion(parser::add_paren, code = "...", code = "...")]
 //~^ ERROR specified multiple times
 //~^^ NOTE previously specified here
-struct AI {
+struct AJ {
     #[primary_span]
     span: Span,
     #[applicability]
@@ -378,8 +387,8 @@ struct AI {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[suggestion(slug = "...", code = "...")]
-struct AJ {
+#[suggestion(parser::add_paren, code = "...")]
+struct AK {
     #[primary_span]
     span: Span,
     #[applicability]
@@ -391,9 +400,9 @@ struct AJ {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[suggestion(slug = "...", code = "...")]
+#[suggestion(parser::add_paren, code = "...")]
 //~^ ERROR suggestion without `applicability`
-struct AK {
+struct AL {
     #[primary_span]
     span: Span,
     #[applicability]
@@ -402,17 +411,17 @@ struct AK {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[suggestion(slug = "...", code = "...")]
+#[suggestion(parser::add_paren, code = "...")]
 //~^ ERROR suggestion without `applicability`
-struct AL {
+struct AM {
     #[primary_span]
     span: Span,
 }
 
 #[derive(SessionSubdiagnostic)]
-#[suggestion(slug = "...")]
+#[suggestion(parser::add_paren)]
 //~^ ERROR suggestion without `code = "..."`
-struct AM {
+struct AN {
     #[primary_span]
     span: Span,
     #[applicability]
@@ -420,34 +429,34 @@ struct AM {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[suggestion(slug = "...", code ="...", applicability = "foo")]
+#[suggestion(parser::add_paren, code ="...", applicability = "foo")]
 //~^ ERROR invalid applicability
-struct AN {
+struct AO {
     #[primary_span]
     span: Span,
 }
 
 #[derive(SessionSubdiagnostic)]
-#[help(slug = "label-am")]
-struct AO {
+#[help(parser::add_paren)]
+struct AP {
     var: String
 }
 
 #[derive(SessionSubdiagnostic)]
-#[note(slug = "label-an")]
-struct AP;
+#[note(parser::add_paren)]
+struct AQ;
 
 #[derive(SessionSubdiagnostic)]
-#[suggestion(slug = "...", code = "...")]
+#[suggestion(parser::add_paren, code = "...")]
 //~^ ERROR suggestion without `applicability`
 //~^^ ERROR suggestion without `#[primary_span]` field
-struct AQ {
+struct AR {
     var: String,
 }
 
 #[derive(SessionSubdiagnostic)]
-#[suggestion(slug = "...", code ="...", applicability = "machine-applicable")]
-struct AR {
+#[suggestion(parser::add_paren, code ="...", applicability = "machine-applicable")]
+struct AS {
     #[primary_span]
     span: Span,
 }
@@ -455,8 +464,8 @@ struct AR {
 #[derive(SessionSubdiagnostic)]
 #[label]
 //~^ ERROR unsupported type attribute for subdiagnostic enum
-enum AS {
-    #[label(slug = "...")]
+enum AT {
+    #[label(parser::add_paren)]
     A {
         #[primary_span]
         span: Span,
@@ -465,24 +474,24 @@ enum AS {
 }
 
 #[derive(SessionSubdiagnostic)]
-#[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")]
-struct AT {
+#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+struct AU {
     #[primary_span]
     span: Span,
     var: String,
 }
 
 #[derive(SessionSubdiagnostic)]
-#[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")]
+#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
 //~^ ERROR `var` doesn't refer to a field on this type
-struct AU {
+struct AV {
     #[primary_span]
     span: Span,
 }
 
 #[derive(SessionSubdiagnostic)]
-enum AV {
-    #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")]
+enum AW {
+    #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
     A {
         #[primary_span]
         span: Span,
@@ -491,8 +500,8 @@ enum AV {
 }
 
 #[derive(SessionSubdiagnostic)]
-enum AW {
-    #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")]
+enum AX {
+    #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
 //~^ ERROR `var` doesn't refer to a field on this type
     A {
         #[primary_span]
diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
index 4984cc4b3186c..f833bd210f7f5 100644
--- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
+++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -1,7 +1,7 @@
 error: label without `#[primary_span]` field
   --> $DIR/subdiagnostic-derive.rs:47:1
    |
-LL | / #[label(slug = "label-c")]
+LL | / #[label(parser::add_paren)]
 LL | |
 LL | | struct C {
 LL | |     var: String,
@@ -32,98 +32,106 @@ error: `#[label(bug = ...)]` is not a valid attribute
 LL | #[label(bug = "...")]
    |         ^^^^^^^^^^^
    |
-   = help: only `code`, `slug` and `applicability` are valid nested attributes
+   = help: first argument of the attribute should be the diagnostic slug
 
 error: `#[label("...")]` is not a valid attribute
   --> $DIR/subdiagnostic-derive.rs:91:9
    |
 LL | #[label("...")]
    |         ^^^^^
+   |
+   = help: first argument of the attribute should be the diagnostic slug
 
 error: `#[label(slug = ...)]` is not a valid attribute
   --> $DIR/subdiagnostic-derive.rs:100:9
    |
 LL | #[label(slug = 4)]
    |         ^^^^^^^^
+   |
+   = help: first argument of the attribute should be the diagnostic slug
 
 error: `#[label(slug(...))]` is not a valid attribute
   --> $DIR/subdiagnostic-derive.rs:109:9
    |
 LL | #[label(slug("..."))]
    |         ^^^^^^^^^^^
-
-error: `#[label(slug)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:118:9
    |
-LL | #[label(slug)]
-   |         ^^^^
+   = help: first argument of the attribute should be the diagnostic slug
 
-error: `slug` must be set in a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:127:1
+error: diagnostic slug must be first argument of a `#[label(...)]` attribute
+  --> $DIR/subdiagnostic-derive.rs:128:1
    |
 LL | #[label()]
    | ^^^^^^^^^^
 
 error: `code` is not a valid nested attribute of a `label` attribute
-  --> $DIR/subdiagnostic-derive.rs:136:1
+  --> $DIR/subdiagnostic-derive.rs:137:1
+   |
+LL | #[label(parser::add_paren, code = "...")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `applicability` is not a valid nested attribute of a `label` attribute
+  --> $DIR/subdiagnostic-derive.rs:146:1
    |
-LL | #[label(code = "...")]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+LL | #[label(parser::add_paren, applicability = "machine-applicable")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:145:1
+  --> $DIR/subdiagnostic-derive.rs:155:1
    |
 LL | #[foo]
    | ^^^^^^
 
 error: `#[bar]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:159:5
+  --> $DIR/subdiagnostic-derive.rs:169:5
    |
 LL |     #[bar]
    |     ^^^^^^
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:171:5
+  --> $DIR/subdiagnostic-derive.rs:181:5
    |
 LL |     #[bar = "..."]
    |     ^^^^^^^^^^^^^^
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:183:5
+  --> $DIR/subdiagnostic-derive.rs:193:5
    |
 LL |     #[bar = 4]
    |     ^^^^^^^^^^
 
 error: `#[bar("...")]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:195:11
+  --> $DIR/subdiagnostic-derive.rs:205:11
    |
 LL |     #[bar("...")]
    |           ^^^^^
+   |
+   = help: first argument of the attribute should be the diagnostic slug
 
-error: `code` is not a valid nested attribute of a `label` attribute
-  --> $DIR/subdiagnostic-derive.rs:207:5
+error: diagnostic slug must be first argument of a `#[label(...)]` attribute
+  --> $DIR/subdiagnostic-derive.rs:217:5
    |
 LL |     #[label(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: subdiagnostic kind not specified
-  --> $DIR/subdiagnostic-derive.rs:224:5
+  --> $DIR/subdiagnostic-derive.rs:234:5
    |
 LL |     B {
    |     ^
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span`
-  --> $DIR/subdiagnostic-derive.rs:236:5
+  --> $DIR/subdiagnostic-derive.rs:246:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: label without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:233:1
+  --> $DIR/subdiagnostic-derive.rs:243:1
    |
-LL | / #[label(slug = "...")]
+LL | / #[label(parser::add_paren)]
 LL | |
-LL | | struct V {
+LL | | struct W {
 LL | |     #[primary_span]
 LL | |
 LL | |     span: String,
@@ -131,13 +139,13 @@ LL | | }
    | |_^
 
 error: `#[applicability]` is only valid on suggestions
-  --> $DIR/subdiagnostic-derive.rs:246:5
+  --> $DIR/subdiagnostic-derive.rs:256:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: `#[bar]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:256:5
+  --> $DIR/subdiagnostic-derive.rs:266:5
    |
 LL |     #[bar]
    |     ^^^^^^
@@ -145,21 +153,21 @@ LL |     #[bar]
    = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:267:5
+  --> $DIR/subdiagnostic-derive.rs:277:5
    |
 LL |     #[bar = "..."]
    |     ^^^^^^^^^^^^^^
 
 error: `#[bar(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:278:5
+  --> $DIR/subdiagnostic-derive.rs:288:5
    |
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
 
 error: unexpected unsupported untagged union
-  --> $DIR/subdiagnostic-derive.rs:294:1
+  --> $DIR/subdiagnostic-derive.rs:304:1
    |
-LL | / union AB {
+LL | / union AC {
 LL | |
 LL | |     span: u32,
 LL | |     b: u64
@@ -167,95 +175,91 @@ LL | | }
    | |_^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:304:9
+  --> $DIR/subdiagnostic-derive.rs:314:1
    |
-LL | #[label(slug = "label-ac-2")]
-   |         ^^^^^^^^^^^^^^^^^^^
+LL | #[label(parser::add_paren)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:301:9
+  --> $DIR/subdiagnostic-derive.rs:311:1
    |
-LL | #[label(slug = "label-ac-1")]
-   |         ^^^^^^^^^^^^^^^^^^^
+LL | #[label(parser::add_paren)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:304:1
+  --> $DIR/subdiagnostic-derive.rs:314:1
    |
-LL | #[label(slug = "label-ac-2")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[label(parser::add_paren)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:301:1
+  --> $DIR/subdiagnostic-derive.rs:311:1
    |
-LL | #[label(slug = "label-ac-1")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[label(parser::add_paren)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:313:30
+error: `#[label(parser::add_paren)]` is not a valid attribute
+  --> $DIR/subdiagnostic-derive.rs:323:28
    |
-LL | #[label(slug = "label-ad-1", slug = "label-ad-2")]
-   |                              ^^^^^^^^^^^^^^^^^^^
+LL | #[label(parser::add_paren, parser::add_paren)]
+   |                            ^^^^^^^^^^^^^^^^^
    |
-note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:313:9
-   |
-LL | #[label(slug = "label-ad-1", slug = "label-ad-2")]
-   |         ^^^^^^^^^^^^^^^^^^^
+   = help: a diagnostic slug must be the first argument to the attribute
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:327:5
+  --> $DIR/subdiagnostic-derive.rs:336:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:324:5
+  --> $DIR/subdiagnostic-derive.rs:333:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: subdiagnostic kind not specified
-  --> $DIR/subdiagnostic-derive.rs:333:8
+  --> $DIR/subdiagnostic-derive.rs:342:8
    |
-LL | struct AF {
+LL | struct AG {
    |        ^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:370:42
+  --> $DIR/subdiagnostic-derive.rs:379:47
    |
-LL | #[suggestion(slug = "...", code = "...", code = "...")]
-   |                                          ^^^^^^^^^^^^
+LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
+   |                                               ^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:370:28
+  --> $DIR/subdiagnostic-derive.rs:379:33
    |
-LL | #[suggestion(slug = "...", code = "...", code = "...")]
-   |                            ^^^^^^^^^^^^
+LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
+   |                                 ^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:388:5
+  --> $DIR/subdiagnostic-derive.rs:397:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:385:5
+  --> $DIR/subdiagnostic-derive.rs:394:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
-  --> $DIR/subdiagnostic-derive.rs:399:5
+  --> $DIR/subdiagnostic-derive.rs:408:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: suggestion without `applicability`
-  --> $DIR/subdiagnostic-derive.rs:394:1
+  --> $DIR/subdiagnostic-derive.rs:403:1
    |
-LL | / #[suggestion(slug = "...", code = "...")]
+LL | / #[suggestion(parser::add_paren, code = "...")]
 LL | |
-LL | | struct AK {
+LL | | struct AL {
 LL | |     #[primary_span]
 ...  |
 LL | |     applicability: Span,
@@ -263,22 +267,22 @@ LL | | }
    | |_^
 
 error: suggestion without `applicability`
-  --> $DIR/subdiagnostic-derive.rs:405:1
+  --> $DIR/subdiagnostic-derive.rs:414:1
    |
-LL | / #[suggestion(slug = "...", code = "...")]
+LL | / #[suggestion(parser::add_paren, code = "...")]
 LL | |
-LL | | struct AL {
+LL | | struct AM {
 LL | |     #[primary_span]
 LL | |     span: Span,
 LL | | }
    | |_^
 
 error: suggestion without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:413:1
+  --> $DIR/subdiagnostic-derive.rs:422:1
    |
-LL | / #[suggestion(slug = "...")]
+LL | / #[suggestion(parser::add_paren)]
 LL | |
-LL | | struct AM {
+LL | | struct AN {
 LL | |     #[primary_span]
 ...  |
 LL | |     applicability: Applicability,
@@ -286,50 +290,50 @@ LL | | }
    | |_^
 
 error: invalid applicability
-  --> $DIR/subdiagnostic-derive.rs:423:41
+  --> $DIR/subdiagnostic-derive.rs:432:46
    |
-LL | #[suggestion(slug = "...", code ="...", applicability = "foo")]
-   |                                         ^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
+   |                                              ^^^^^^^^^^^^^^^^^^^^^
 
 error: suggestion without `applicability`
-  --> $DIR/subdiagnostic-derive.rs:441:1
+  --> $DIR/subdiagnostic-derive.rs:450:1
    |
-LL | / #[suggestion(slug = "...", code = "...")]
+LL | / #[suggestion(parser::add_paren, code = "...")]
 LL | |
 LL | |
-LL | | struct AQ {
+LL | | struct AR {
 LL | |     var: String,
 LL | | }
    | |_^
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:441:1
+  --> $DIR/subdiagnostic-derive.rs:450:1
    |
-LL | / #[suggestion(slug = "...", code = "...")]
+LL | / #[suggestion(parser::add_paren, code = "...")]
 LL | |
 LL | |
-LL | | struct AQ {
+LL | | struct AR {
 LL | |     var: String,
 LL | | }
    | |_^
 
 error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:456:1
+  --> $DIR/subdiagnostic-derive.rs:465:1
    |
 LL | #[label]
    | ^^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:476:34
+  --> $DIR/subdiagnostic-derive.rs:485:39
    |
-LL | #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")]
-   |                                  ^^^^^^^
+LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+   |                                       ^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:495:38
+  --> $DIR/subdiagnostic-derive.rs:504:43
    |
-LL |     #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")]
-   |                                      ^^^^^^^
+LL |     #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+   |                                           ^^^^^^^
 
 error: cannot find attribute `foo` in this scope
   --> $DIR/subdiagnostic-derive.rs:63:3
@@ -338,52 +342,59 @@ LL | #[foo]
    |   ^^^
 
 error: cannot find attribute `foo` in this scope
-  --> $DIR/subdiagnostic-derive.rs:145:3
+  --> $DIR/subdiagnostic-derive.rs:155:3
    |
 LL | #[foo]
    |   ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:159:7
+  --> $DIR/subdiagnostic-derive.rs:169:7
    |
 LL |     #[bar]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:171:7
+  --> $DIR/subdiagnostic-derive.rs:181:7
    |
 LL |     #[bar = "..."]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:183:7
+  --> $DIR/subdiagnostic-derive.rs:193:7
    |
 LL |     #[bar = 4]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:195:7
+  --> $DIR/subdiagnostic-derive.rs:205:7
    |
 LL |     #[bar("...")]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:256:7
+  --> $DIR/subdiagnostic-derive.rs:266:7
    |
 LL |     #[bar]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:267:7
+  --> $DIR/subdiagnostic-derive.rs:277:7
    |
 LL |     #[bar = "..."]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:278:7
+  --> $DIR/subdiagnostic-derive.rs:288:7
    |
 LL |     #[bar("...")]
    |       ^^^
 
-error: aborting due to 51 previous errors
+error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
+  --> $DIR/subdiagnostic-derive.rs:118:9
+   |
+LL | #[label(slug)]
+   |         ^^^^ not found in `rustc_errors::fluent`
+
+error: aborting due to 52 previous errors
 
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/array-slice-vec/array_const_index-0.stderr b/src/test/ui/array-slice-vec/array_const_index-0.stderr
index 641705e1c6875..b44251efdea42 100644
--- a/src/test/ui/array-slice-vec/array_const_index-0.stderr
+++ b/src/test/ui/array-slice-vec/array_const_index-0.stderr
@@ -12,3 +12,16 @@ LL | const B: i32 = (&A)[1];
 
 error: aborting due to previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/array_const_index-0.rs:2:16
+   |
+LL | const B: i32 = (&A)[1];
+   | ---------------^^^^^^^-
+   |                |
+   |                index out of bounds: the length is 0 but the index is 1
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/array-slice-vec/array_const_index-1.stderr b/src/test/ui/array-slice-vec/array_const_index-1.stderr
index 4d52d38af5e17..8beebafb04c32 100644
--- a/src/test/ui/array-slice-vec/array_const_index-1.stderr
+++ b/src/test/ui/array-slice-vec/array_const_index-1.stderr
@@ -12,3 +12,16 @@ LL | const B: i32 = A[1];
 
 error: aborting due to previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/array_const_index-1.rs:2:16
+   |
+LL | const B: i32 = A[1];
+   | ---------------^^^^-
+   |                |
+   |                index out of bounds: the length is 0 but the index is 1
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr
index 7406b2ddee9b2..f04ea0b747705 100644
--- a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr
+++ b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr
@@ -29,3 +29,28 @@ LL |     assert_eq!(<() as Tr>::B, 0);    // causes the error above
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/defaults-not-assumed-fail.rs:8:19
+   |
+LL |     const B: u8 = Self::A + 1;
+   |     --------------^^^^^^^^^^^-
+   |                   |
+   |                   attempt to compute `u8::MAX + 1_u8`, which would overflow
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: erroneous constant used
+  --> $DIR/defaults-not-assumed-fail.rs:34:5
+   |
+LL |     assert_eq!(<() as Tr>::B, 0);    // causes the error above
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/src/test/ui/borrowck/issue-81899.stderr b/src/test/ui/borrowck/issue-81899.stderr
index 92ebd5a220d90..e7345ff3f9a64 100644
--- a/src/test/ui/borrowck/issue-81899.stderr
+++ b/src/test/ui/borrowck/issue-81899.stderr
@@ -27,3 +27,16 @@ LL | const _CONST: &[u8] = &f(&[], |_| {});
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/issue-81899.rs:4:23
+   |
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+   | ----------------------^^^^^^^^^^^^^^^-
+   |                       |
+   |                       referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.stderr b/src/test/ui/borrowck/issue-88434-minimal-example.stderr
index d46cd862e34aa..47d83c6535583 100644
--- a/src/test/ui/borrowck/issue-88434-minimal-example.stderr
+++ b/src/test/ui/borrowck/issue-88434-minimal-example.stderr
@@ -27,3 +27,16 @@ LL | const _CONST: &() = &f(&|_| {});
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/issue-88434-minimal-example.rs:3:21
+   |
+LL | const _CONST: &() = &f(&|_| {});
+   | --------------------^^^^^^^^^^^-
+   |                     |
+   |                     referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
index e6b07aba74d42..b08a7cfc7fe1a 100644
--- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
+++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
@@ -27,3 +27,16 @@ LL | const _CONST: &[u8] = &f(&[], |_| {});
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/issue-88434-removal-index-should-be-less.rs:3:23
+   |
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+   | ----------------------^^^^^^^^^^^^^^^-
+   |                       |
+   |                       referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/assert-type-intrinsics.stderr b/src/test/ui/consts/assert-type-intrinsics.stderr
index bb57ee82cc16f..89f8f2ffc55cb 100644
--- a/src/test/ui/consts/assert-type-intrinsics.stderr
+++ b/src/test/ui/consts/assert-type-intrinsics.stderr
@@ -37,3 +37,45 @@ LL | |     };
 
 error: aborting due to 3 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/assert-type-intrinsics.rs:14:9
+   |
+LL | /     const _BAD1: () = unsafe {
+LL | |         MaybeUninit::<!>::uninit().assume_init();
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
+LL | |     };
+   | |______-
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/assert-type-intrinsics.rs:17:9
+   |
+LL | /     const _BAD2: () = unsafe {
+LL | |         intrinsics::assert_uninit_valid::<bool>();
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid
+LL | |     };
+   | |______-
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/assert-type-intrinsics.rs:20:9
+   |
+LL | /     const _BAD3: () = unsafe {
+LL | |         intrinsics::assert_zero_valid::<&'static i32>();
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid
+LL | |     };
+   | |______-
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/assoc_const_generic_impl.stderr b/src/test/ui/consts/assoc_const_generic_impl.stderr
index 96cb904fa1b19..cccf62a8ff6d3 100644
--- a/src/test/ui/consts/assoc_const_generic_impl.stderr
+++ b/src/test/ui/consts/assoc_const_generic_impl.stderr
@@ -22,3 +22,20 @@ LL |         let () = Self::I_AM_ZERO_SIZED;
 
 error: aborting due to previous error; 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/assoc_const_generic_impl.rs:11:34
+   |
+LL |     const I_AM_ZERO_SIZED: ()  = [()][std::mem::size_of::<Self>()];
+   |     -----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                  |
+   |                                  index out of bounds: the length is 1 but the index is 4
+   |
+note: the lint level is defined here
+  --> $DIR/assoc_const_generic_impl.rs:3:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-err-early.stderr b/src/test/ui/consts/const-err-early.stderr
index 2b3d881738762..385e770eb4f01 100644
--- a/src/test/ui/consts/const-err-early.stderr
+++ b/src/test/ui/consts/const-err-early.stderr
@@ -60,3 +60,88 @@ LL | pub const E: u8 = [5u8][1];
 
 error: aborting due to 5 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-err-early.rs:3:19
+   |
+LL | pub const A: i8 = -i8::MIN;
+   | ------------------^^^^^^^^-
+   |                   |
+   |                   attempt to negate `i8::MIN`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/const-err-early.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-err-early.rs:5:19
+   |
+LL | pub const B: u8 = 200u8 + 200u8;
+   | ------------------^^^^^^^^^^^^^-
+   |                   |
+   |                   attempt to compute `200_u8 + 200_u8`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/const-err-early.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-err-early.rs:7:19
+   |
+LL | pub const C: u8 = 200u8 * 4;
+   | ------------------^^^^^^^^^-
+   |                   |
+   |                   attempt to compute `200_u8 * 4_u8`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/const-err-early.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-err-early.rs:9:19
+   |
+LL | pub const D: u8 = 42u8 - (42u8 + 1);
+   | ------------------^^^^^^^^^^^^^^^^^-
+   |                   |
+   |                   attempt to compute `42_u8 - 43_u8`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/const-err-early.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-err-early.rs:11:19
+   |
+LL | pub const E: u8 = [5u8][1];
+   | ------------------^^^^^^^^-
+   |                   |
+   |                   index out of bounds: the length is 1 but the index is 1
+   |
+note: the lint level is defined here
+  --> $DIR/const-err-early.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-err-multi.stderr b/src/test/ui/consts/const-err-multi.stderr
index c8172e83d10e2..a195459ff0884 100644
--- a/src/test/ui/consts/const-err-multi.stderr
+++ b/src/test/ui/consts/const-err-multi.stderr
@@ -49,3 +49,71 @@ LL | pub const D: i8 = 50 - A;
 
 error: aborting due to 4 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-err-multi.rs:3:19
+   |
+LL | pub const A: i8 = -i8::MIN;
+   | ------------------^^^^^^^^-
+   |                   |
+   |                   attempt to negate `i8::MIN`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/const-err-multi.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-err-multi.rs:6:19
+   |
+LL | pub const B: i8 = A;
+   | ------------------^-
+   |                   |
+   |                   referenced constant has errors
+   |
+note: the lint level is defined here
+  --> $DIR/const-err-multi.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-err-multi.rs:9:19
+   |
+LL | pub const C: u8 = A as u8;
+   | ------------------^-------
+   |                   |
+   |                   referenced constant has errors
+   |
+note: the lint level is defined here
+  --> $DIR/const-err-multi.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-err-multi.rs:12:24
+   |
+LL | pub const D: i8 = 50 - A;
+   | -----------------------^-
+   |                        |
+   |                        referenced constant has errors
+   |
+note: the lint level is defined here
+  --> $DIR/const-err-multi.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-err.stderr b/src/test/ui/consts/const-err.stderr
index 0c963874a8496..3b03e702dc4ae 100644
--- a/src/test/ui/consts/const-err.stderr
+++ b/src/test/ui/consts/const-err.stderr
@@ -29,3 +29,20 @@ LL |     black_box((FOO, FOO));
 error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const-err.rs:11:17
+   |
+LL | const FOO: u8 = [5u8][1];
+   | ----------------^^^^^^^^-
+   |                 |
+   |                 index out of bounds: the length is 1 but the index is 1
+   |
+note: the lint level is defined here
+  --> $DIR/const-err.rs:5:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.stderr b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
index 9dc40030a6ff8..f88bf4454260b 100644
--- a/src/test/ui/consts/const-eval/conditional_array_execution.stderr
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
@@ -33,3 +33,36 @@ LL |     println!("{}", FOO);
 error: aborting due to previous error; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/conditional_array_execution.rs:7:19
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   | ------------------^^^^^---------------------------
+   |                   |
+   |                   attempt to compute `5_u32 - 6_u32`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/conditional_array_execution.rs:3:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: erroneous constant used
+  --> $DIR/conditional_array_execution.rs:12:20
+   |
+LL |     println!("{}", FOO);
+   |                    ^^^ referenced constant has errors
+   |
+note: the lint level is defined here
+  --> $DIR/conditional_array_execution.rs:3:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
index 26728cf541582..1c74b978827c6 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
@@ -12,3 +12,20 @@ LL |         NEG_NEG_128 => println!("A"),
 
 error: aborting due to 2 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const-eval-overflow-2.rs:11:25
+   |
+LL | const NEG_NEG_128: i8 = -NEG_128;
+   | ------------------------^^^^^^^^-
+   |                         |
+   |                         attempt to negate `i8::MIN`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow-2.rs:4:36
+   |
+LL | #![allow(unused_imports, warnings, const_err)]
+   |                                    ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2.stderr
index 66e86c352d154..948ead521ea34 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2.stderr
@@ -107,3 +107,153 @@ LL | |      );
 
 error: aborting due to 8 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:14:6
+   |
+LL | / const VALS_I8: (i8,) =
+LL | |     (
+LL | |      i8::MIN - 1,
+   | |      ^^^^^^^^^^^ attempt to compute `i8::MIN - 1_i8`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:21:6
+   |
+LL | / const VALS_I16: (i16,) =
+LL | |     (
+LL | |      i16::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `i16::MIN - 1_i16`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:28:6
+   |
+LL | / const VALS_I32: (i32,) =
+LL | |     (
+LL | |      i32::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `i32::MIN - 1_i32`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:35:6
+   |
+LL | / const VALS_I64: (i64,) =
+LL | |     (
+LL | |      i64::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `i64::MIN - 1_i64`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:42:6
+   |
+LL | / const VALS_U8: (u8,) =
+LL | |     (
+LL | |      u8::MIN - 1,
+   | |      ^^^^^^^^^^^ attempt to compute `0_u8 - 1_u8`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:48:6
+   |
+LL | / const VALS_U16: (u16,) = (
+LL | |      u16::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `0_u16 - 1_u16`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:54:6
+   |
+LL | / const VALS_U32: (u32,) = (
+LL | |      u32::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:61:6
+   |
+LL | / const VALS_U64: (u64,) =
+LL | |     (
+LL | |      u64::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `0_u64 - 1_u64`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr
index 3401ba4776500..5db6a49a98b0c 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr
@@ -107,3 +107,153 @@ LL | |      );
 
 error: aborting due to 8 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:14:6
+   |
+LL | / const VALS_I8: (i8,) =
+LL | |     (
+LL | |      i8::MAX + 1,
+   | |      ^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2b.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:21:6
+   |
+LL | / const VALS_I16: (i16,) =
+LL | |     (
+LL | |      i16::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `i16::MAX + 1_i16`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2b.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:28:6
+   |
+LL | / const VALS_I32: (i32,) =
+LL | |     (
+LL | |      i32::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2b.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:35:6
+   |
+LL | / const VALS_I64: (i64,) =
+LL | |     (
+LL | |      i64::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `i64::MAX + 1_i64`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2b.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:42:6
+   |
+LL | / const VALS_U8: (u8,) =
+LL | |     (
+LL | |      u8::MAX + 1,
+   | |      ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2b.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:48:6
+   |
+LL | / const VALS_U16: (u16,) = (
+LL | |      u16::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `u16::MAX + 1_u16`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2b.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:54:6
+   |
+LL | / const VALS_U32: (u32,) = (
+LL | |      u32::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `u32::MAX + 1_u32`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2b.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:61:6
+   |
+LL | / const VALS_U64: (u64,) =
+LL | |     (
+LL | |      u64::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to compute `u64::MAX + 1_u64`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2b.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr
index 93c64090f0eeb..ec3f3c110596b 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr
@@ -107,3 +107,153 @@ LL | |      );
 
 error: aborting due to 8 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:14:6
+   |
+LL | / const VALS_I8: (i8,) =
+LL | |     (
+LL | |      i8::MIN * 2,
+   | |      ^^^^^^^^^^^ attempt to compute `i8::MIN * 2_i8`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2c.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:21:6
+   |
+LL | / const VALS_I16: (i16,) =
+LL | |     (
+LL | |      i16::MIN * 2,
+   | |      ^^^^^^^^^^^^ attempt to compute `i16::MIN * 2_i16`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2c.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:28:6
+   |
+LL | / const VALS_I32: (i32,) =
+LL | |     (
+LL | |      i32::MIN * 2,
+   | |      ^^^^^^^^^^^^ attempt to compute `i32::MIN * 2_i32`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2c.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:35:6
+   |
+LL | / const VALS_I64: (i64,) =
+LL | |     (
+LL | |      i64::MIN * 2,
+   | |      ^^^^^^^^^^^^ attempt to compute `i64::MIN * 2_i64`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2c.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:42:6
+   |
+LL | / const VALS_U8: (u8,) =
+LL | |     (
+LL | |      u8::MAX * 2,
+   | |      ^^^^^^^^^^^ attempt to compute `u8::MAX * 2_u8`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2c.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:48:6
+   |
+LL | / const VALS_U16: (u16,) = (
+LL | |      u16::MAX * 2,
+   | |      ^^^^^^^^^^^^ attempt to compute `u16::MAX * 2_u16`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2c.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:54:6
+   |
+LL | / const VALS_U32: (u32,) = (
+LL | |      u32::MAX * 2,
+   | |      ^^^^^^^^^^^^ attempt to compute `u32::MAX * 2_u32`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2c.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:61:6
+   |
+LL | / const VALS_U64: (u64,) =
+LL | |     (
+LL | |      u64::MAX * 2,
+   | |      ^^^^^^^^^^^^ attempt to compute `u64::MAX * 2_u64`, which would overflow
+LL | |      );
+   | |_______-
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-overflow2c.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
index b74d5a2722bd8..bbec2a830e64b 100644
--- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
@@ -35,3 +35,31 @@ query stack during panic:
 #1 [optimized_mir] optimizing MIR for `main`
 #2 [collect_and_partition_mono_items] collect_and_partition_mono_items
 end of query stack
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const-eval-query-stack.rs:19:16
+   |
+LL | const X: i32 = 1 / 0;
+   | ---------------^^^^^-
+   |                |
+   |                attempt to divide `1_i32` by zero
+   |
+note: the lint level is defined here
+  --> $DIR/const-eval-query-stack.rs:18:8
+   |
+LL | #[warn(const_err)]
+   |        ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: erroneous constant used
+  --> $DIR/const-eval-query-stack.rs:23:27
+   |
+LL |     let x: &'static i32 = &X;
+   |                           ^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr
index c19f6342b5ba6..b004637fd8300 100644
--- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr
+++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr
@@ -321,3 +321,354 @@ LL |     const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.charact
 error: aborting due to 29 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:26:49
+   |
+LL |     const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
+   |     --------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                                 |
+   |                                                 unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:30:43
+   |
+LL |     const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:34:45
+   |
+LL |     const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:38:45
+   |
+LL |     const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:42:45
+   |
+LL |     const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:49:43
+   |
+LL |     const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:53:45
+   |
+LL |     const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:57:45
+   |
+LL |     const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:61:45
+   |
+LL |     const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:68:45
+   |
+LL |     const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:72:45
+   |
+LL |     const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:76:47
+   |
+LL |     const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
+   |     ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                               |
+   |                                               unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:80:47
+   |
+LL |     const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
+   |     ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                               |
+   |                                               unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:84:39
+   |
+LL |     const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
+   |     ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                       |
+   |                                       unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:88:41
+   |
+LL |     const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:92:41
+   |
+LL |     const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:96:41
+   |
+LL |     const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:100:43
+   |
+LL |     const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:104:39
+   |
+LL |     const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
+   |     ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                       |
+   |                                       unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:108:41
+   |
+LL |     const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:112:41
+   |
+LL |     const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:116:41
+   |
+LL |     const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:120:43
+   |
+LL |     const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:124:41
+   |
+LL |     const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:128:41
+   |
+LL |     const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:132:43
+   |
+LL |     const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:136:43
+   |
+LL |     const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
index c17166263ba09..daf3d8927c19a 100644
--- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
+++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
@@ -21,3 +21,79 @@ LL |     x(y)
 error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const_fn_ptr_fail2.rs:12:5
+   |
+LL |     x(y)
+   |     ^^^^
+   |     |
+   |     calling non-const function `double`
+   |     inside `bar` at $DIR/const_fn_ptr_fail2.rs:12:5
+   |     inside `Y` at $DIR/const_fn_ptr_fail2.rs:15:18
+...
+LL | const Y: usize = bar(X, 2); // FIXME: should fail to typeck someday
+   | ---------------------------
+   |
+note: the lint level is defined here
+  --> $DIR/const_fn_ptr_fail2.rs:4:10
+   |
+LL | #![allow(const_err)]
+   |          ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const_fn_ptr_fail2.rs:12:5
+   |
+LL |     x(y)
+   |     ^^^^
+   |     |
+   |     calling non-const function `double`
+   |     inside `bar` at $DIR/const_fn_ptr_fail2.rs:12:5
+   |     inside `Z` at $DIR/const_fn_ptr_fail2.rs:16:18
+...
+LL | const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday
+   | --------------------------------
+   |
+note: the lint level is defined here
+  --> $DIR/const_fn_ptr_fail2.rs:4:10
+   |
+LL | #![allow(const_err)]
+   |          ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: erroneous constant used
+  --> $DIR/const_fn_ptr_fail2.rs:19:5
+   |
+LL |     assert_eq!(Y, 4);
+   |     ^^^^^^^^^^^^^^^^ referenced constant has errors
+   |
+note: the lint level is defined here
+  --> $DIR/const_fn_ptr_fail2.rs:4:10
+   |
+LL | #![allow(const_err)]
+   |          ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+warning: erroneous constant used
+  --> $DIR/const_fn_ptr_fail2.rs:21:5
+   |
+LL |     assert_eq!(Z, 4);
+   |     ^^^^^^^^^^^^^^^^ referenced constant has errors
+   |
+note: the lint level is defined here
+  --> $DIR/const_fn_ptr_fail2.rs:4:10
+   |
+LL | #![allow(const_err)]
+   |          ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/src/test/ui/consts/const-eval/erroneous-const.stderr b/src/test/ui/consts/const-eval/erroneous-const.stderr
index 7e2a60929c73d..9057b58ded9da 100644
--- a/src/test/ui/consts/const-eval/erroneous-const.stderr
+++ b/src/test/ui/consts/const-eval/erroneous-const.stderr
@@ -41,3 +41,20 @@ LL | pub static FOO: () = no_codegen::<i32>();
 error: aborting due to previous error; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/erroneous-const.rs:6:22
+   |
+LL |     const VOID: () = [()][2];
+   |     -----------------^^^^^^^-
+   |                      |
+   |                      index out of bounds: the length is 1 but the index is 2
+   |
+note: the lint level is defined here
+  --> $DIR/erroneous-const.rs:2:9
+   |
+LL | #![warn(const_err, unconditional_panic)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/erroneous-const2.stderr b/src/test/ui/consts/const-eval/erroneous-const2.stderr
index 813d3ee249fb2..bf6cc8410a7ee 100644
--- a/src/test/ui/consts/const-eval/erroneous-const2.stderr
+++ b/src/test/ui/consts/const-eval/erroneous-const2.stderr
@@ -35,3 +35,20 @@ LL |         let _ = PrintName::<i32>::VOID;
 error: aborting due to previous error; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/erroneous-const2.rs:6:22
+   |
+LL |     const VOID: () = [()][2];
+   |     -----------------^^^^^^^-
+   |                      |
+   |                      index out of bounds: the length is 1 but the index is 2
+   |
+note: the lint level is defined here
+  --> $DIR/erroneous-const2.rs:2:9
+   |
+LL | #![warn(const_err, unconditional_panic)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/format.stderr b/src/test/ui/consts/const-eval/format.stderr
index 44f436ae4e3a9..b00cadcea991f 100644
--- a/src/test/ui/consts/const-eval/format.stderr
+++ b/src/test/ui/consts/const-eval/format.stderr
@@ -76,3 +76,49 @@ LL |     println!("{:?}", 0);
 error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0015`.
+Future incompatibility report: Future breakage diagnostic:
+error: erroneous constant used
+  --> $DIR/format.rs:2:12
+   |
+LL |     panic!("{:?}", 0);
+   |            ^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: erroneous constant used
+  --> $DIR/format.rs:2:20
+   |
+LL |     panic!("{:?}", 0);
+   |                    ^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this error originates in the macro `$crate::const_format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+error: erroneous constant used
+  --> $DIR/format.rs:11:14
+   |
+LL |     println!("{:?}", 0);
+   |              ^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: erroneous constant used
+  --> $DIR/format.rs:11:22
+   |
+LL |     println!("{:?}", 0);
+   |                      ^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
index 73664fa49d189..7b3e46fccca7b 100644
--- a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
+++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
@@ -22,3 +22,20 @@ LL |     let _ = PrintName::<T>::VOID;
 
 error: aborting due to previous error; 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/index-out-of-bounds-never-type.rs:10:61
+   |
+LL |     const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
+   |     --------------------------------------------------------^^^^^---
+   |                                                             |
+   |                                                             index out of bounds: the length is 0 but the index is 0
+   |
+note: the lint level is defined here
+  --> $DIR/index-out-of-bounds-never-type.rs:4:9
+   |
+LL | #![warn(const_err, unconditional_panic)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr
index 32ab7c74b891f..53ed32638ced2 100644
--- a/src/test/ui/consts/const-eval/issue-43197.stderr
+++ b/src/test/ui/consts/const-eval/issue-43197.stderr
@@ -60,3 +60,69 @@ LL |     println!("{} {}", X, Y);
 error: aborting due to 2 previous errors; 4 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/issue-43197.rs:10:20
+   |
+LL |     const X: u32 = 0 - 1;
+   |     ---------------^^^^^-
+   |                    |
+   |                    attempt to compute `0_u32 - 1_u32`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/issue-43197.rs:3:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/issue-43197.rs:13:24
+   |
+LL |     const Y: u32 = foo(0 - 1);
+   |     -------------------^^^^^--
+   |                        |
+   |                        attempt to compute `0_u32 - 1_u32`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/issue-43197.rs:3:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: erroneous constant used
+  --> $DIR/issue-43197.rs:16:23
+   |
+LL |     println!("{} {}", X, Y);
+   |                       ^ referenced constant has errors
+   |
+note: the lint level is defined here
+  --> $DIR/issue-43197.rs:3:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+warning: erroneous constant used
+  --> $DIR/issue-43197.rs:16:26
+   |
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
+   |
+note: the lint level is defined here
+  --> $DIR/issue-43197.rs:3:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/src/test/ui/consts/const-eval/issue-44578.stderr b/src/test/ui/consts/const-eval/issue-44578.stderr
index bff9f40f82b35..5ecdb7ef5568b 100644
--- a/src/test/ui/consts/const-eval/issue-44578.stderr
+++ b/src/test/ui/consts/const-eval/issue-44578.stderr
@@ -7,3 +7,36 @@ LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/issue-44578.rs:15:24
+   |
+LL |     const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+   |     -------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                        |
+   |                        index out of bounds: the length is 1 but the index is 1
+   |
+note: the lint level is defined here
+  --> $DIR/issue-44578.rs:3:10
+   |
+LL | #![allow(const_err)]
+   |          ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: erroneous constant used
+  --> $DIR/issue-44578.rs:27:20
+   |
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+   |
+note: the lint level is defined here
+  --> $DIR/issue-44578.rs:3:10
+   |
+LL | #![allow(const_err)]
+   |          ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/src/test/ui/consts/const-eval/issue-50814-2.stderr b/src/test/ui/consts/const-eval/issue-50814-2.stderr
index 298f0a4a446dd..67af3b2b1d3ae 100644
--- a/src/test/ui/consts/const-eval/issue-50814-2.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814-2.stderr
@@ -25,3 +25,16 @@ LL |     println!("{:x}", foo::<()>() as *const usize as usize);
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/issue-50814-2.rs:14:24
+   |
+LL |     const BAR: usize = [5, 6, 7][T::BOO];
+   |     -------------------^^^^^^^^^^^^^^^^^-
+   |                        |
+   |                        index out of bounds: the length is 3 but the index is 42
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr
index 87bea28e76325..b82bc9ca2f81a 100644
--- a/src/test/ui/consts/const-eval/issue-50814.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814.stderr
@@ -25,3 +25,16 @@ LL |     foo(0);
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/issue-50814.rs:15:21
+   |
+LL |     const MAX: u8 = A::MAX + B::MAX;
+   |     ----------------^^^^^^^^^^^^^^^-
+   |                     |
+   |                     attempt to compute `u8::MAX + u8::MAX`, which would overflow
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr b/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr
index a18c7e78d95af..1a7d386142097 100644
--- a/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr
+++ b/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr
@@ -18,3 +18,22 @@ LL | | };
 
 error: aborting due to previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/partial_ptr_overwrite.rs:8:9
+   |
+LL | / const PARTIAL_OVERWRITE: () = {
+LL | |     let mut p = &42;
+LL | |     unsafe {
+LL | |         let ptr: *mut _ = &mut p;
+LL | |         *(ptr as *mut u8) = 123;
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at alloc4
+...  |
+LL | |     let x = *p;
+LL | | };
+   | |__-
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr
index 5bfd4ef92a975..be845339dfe67 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr
@@ -85,3 +85,53 @@ LL | | };
 
 warning: 7 warnings emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/promoted_errors.rs:15:5
+   |
+LL |       0 - 1
+   |       ^^^^^
+   |       |
+   |       attempt to compute `0_u32 - 1_u32`, which would overflow
+   |       inside `overflow` at $DIR/promoted_errors.rs:15:5
+   |       inside `X` at $DIR/promoted_errors.rs:43:29
+...
+LL | / const X: () = {
+LL | |     let _x: &'static u32 = &overflow();
+LL | |
+LL | |
+...  |
+LL | |     let _x: &'static i32 = &oob();
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:11:9
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/promoted_errors.rs:43:28
+   |
+LL | / const X: () = {
+LL | |     let _x: &'static u32 = &overflow();
+   | |                            ^^^^^^^^^^^ referenced constant has errors
+LL | |
+LL | |
+...  |
+LL | |     let _x: &'static i32 = &oob();
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:11:9
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr
index 0a8a8aef3cf8f..c91d52336c36d 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr
@@ -86,3 +86,54 @@ LL | | };
 
 warning: 7 warnings emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/promoted_errors.rs:21:5
+   |
+LL |       1 / 0
+   |       ^^^^^
+   |       |
+   |       attempt to divide `1_i32` by zero
+   |       inside `div_by_zero1` at $DIR/promoted_errors.rs:21:5
+   |       inside `X` at $DIR/promoted_errors.rs:46:29
+...
+LL | / const X: () = {
+LL | |     let _x: &'static u32 = &overflow();
+LL | |
+LL | |
+...  |
+LL | |     let _x: &'static i32 = &oob();
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:11:9
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/promoted_errors.rs:46:28
+   |
+LL | / const X: () = {
+LL | |     let _x: &'static u32 = &overflow();
+LL | |
+LL | |
+LL | |     let _x: &'static i32 = &div_by_zero1();
+   | |                            ^^^^^^^^^^^^^^^ referenced constant has errors
+...  |
+LL | |     let _x: &'static i32 = &oob();
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:11:9
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
index 5bfd4ef92a975..be845339dfe67 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
@@ -85,3 +85,53 @@ LL | | };
 
 warning: 7 warnings emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/promoted_errors.rs:15:5
+   |
+LL |       0 - 1
+   |       ^^^^^
+   |       |
+   |       attempt to compute `0_u32 - 1_u32`, which would overflow
+   |       inside `overflow` at $DIR/promoted_errors.rs:15:5
+   |       inside `X` at $DIR/promoted_errors.rs:43:29
+...
+LL | / const X: () = {
+LL | |     let _x: &'static u32 = &overflow();
+LL | |
+LL | |
+...  |
+LL | |     let _x: &'static i32 = &oob();
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:11:9
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/promoted_errors.rs:43:28
+   |
+LL | / const X: () = {
+LL | |     let _x: &'static u32 = &overflow();
+   | |                            ^^^^^^^^^^^ referenced constant has errors
+LL | |
+LL | |
+...  |
+LL | |     let _x: &'static i32 = &oob();
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:11:9
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/pub_const_err.stderr b/src/test/ui/consts/const-eval/pub_const_err.stderr
index dd47dca2b2e40..56d66827626b9 100644
--- a/src/test/ui/consts/const-eval/pub_const_err.stderr
+++ b/src/test/ui/consts/const-eval/pub_const_err.stderr
@@ -16,3 +16,20 @@ LL | #![warn(const_err)]
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/pub_const_err.rs:6:20
+   |
+LL | pub const Z: u32 = 0 - 1;
+   | -------------------^^^^^-
+   |                    |
+   |                    attempt to compute `0_u32 - 1_u32`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/pub_const_err.rs:2:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/pub_const_err_bin.stderr b/src/test/ui/consts/const-eval/pub_const_err_bin.stderr
index 9f413fb8fd770..202ea781e975d 100644
--- a/src/test/ui/consts/const-eval/pub_const_err_bin.stderr
+++ b/src/test/ui/consts/const-eval/pub_const_err_bin.stderr
@@ -16,3 +16,20 @@ LL | #![warn(const_err)]
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/pub_const_err_bin.rs:4:20
+   |
+LL | pub const Z: u32 = 0 - 1;
+   | -------------------^^^^^-
+   |                    |
+   |                    attempt to compute `0_u32 - 1_u32`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/pub_const_err_bin.rs:2:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr
index 83ac6c90a43a8..a55fd8c156e07 100644
--- a/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr
@@ -24,3 +24,16 @@ LL |         10..=BAR => {},
 
 error: aborting due to 3 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ref_to_int_match.rs:25:27
+   |
+LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
+   | --------------------------^^^^^^^^^^^^^^^^---
+   |                           |
+   |                           unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr
index 83ac6c90a43a8..a55fd8c156e07 100644
--- a/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr
@@ -24,3 +24,16 @@ LL |         10..=BAR => {},
 
 error: aborting due to 3 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ref_to_int_match.rs:25:27
+   |
+LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
+   | --------------------------^^^^^^^^^^^^^^^^---
+   |                           |
+   |                           unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/ub-enum.32bit.stderr b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr
index c6fa14d0534f4..2440cd2272c6c 100644
--- a/src/test/ui/consts/const-eval/ub-enum.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr
@@ -125,3 +125,58 @@ LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe {
 error: aborting due to 13 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-enum.rs:26:1
+   |
+LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-enum.rs:30:1
+   |
+LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-enum.rs:45:1
+   |
+LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-enum.rs:49:1
+   |
+LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-enum.rs:63:1
+   |
+LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr
index 25be593ab83b0..e9b4023068e94 100644
--- a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr
@@ -125,3 +125,58 @@ LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe {
 error: aborting due to 13 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-enum.rs:26:1
+   |
+LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-enum.rs:30:1
+   |
+LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-enum.rs:45:1
+   |
+LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-enum.rs:49:1
+   |
+LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-enum.rs:63:1
+   |
+LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
index 8a4f23c033e89..10a0ccd552b6d 100644
--- a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
@@ -176,3 +176,66 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
 error: aborting due to 16 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-ref-ptr.rs:31:1
+   |
+LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-ref-ptr.rs:35:39
+   |
+LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
+   | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                       |
+   |                                       unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-ref-ptr.rs:35:38
+   |
+LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
+   | -------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                      |
+   |                                      referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-ref-ptr.rs:41:86
+   |
+LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
+   | -------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^----
+   |                                                                                      |
+   |                                                                                      unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-ref-ptr.rs:41:85
+   |
+LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
+   | ------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^----
+   |                                                                                     |
+   |                                                                                     referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
index da1c6d1a07f84..e9fcefe12c7d9 100644
--- a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
@@ -176,3 +176,66 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
 error: aborting due to 16 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-ref-ptr.rs:31:1
+   |
+LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-ref-ptr.rs:35:39
+   |
+LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
+   | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                       |
+   |                                       unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-ref-ptr.rs:35:38
+   |
+LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
+   | -------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                      |
+   |                                      referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-ref-ptr.rs:41:86
+   |
+LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
+   | -------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^----
+   |                                                                                      |
+   |                                                                                      unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-ref-ptr.rs:41:85
+   |
+LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
+   | ------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^----
+   |                                                                                     |
+   |                                                                                     referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
index a78cff11589fd..0c398f5bfd45e 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
@@ -344,3 +344,86 @@ LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
 error: aborting due to 32 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:42:1
+   |
+LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:46:1
+   |
+LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:75:1
+   |
+LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:82:1
+   |
+LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:87:40
+   |
+LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
+   | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                        |
+   |                                        referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:95:42
+   |
+LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                          |
+   |                                          referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:100:42
+   |
+LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                          |
+   |                                          referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
index 69a61d9caede6..bf53995d956c5 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
@@ -344,3 +344,86 @@ LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
 error: aborting due to 32 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:42:1
+   |
+LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:46:1
+   |
+LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:75:1
+   |
+LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:82:1
+   |
+LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:87:40
+   |
+LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
+   | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                        |
+   |                                        referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:95:42
+   |
+LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                          |
+   |                                          referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:100:42
+   |
+LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                          |
+   |                                          referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-eval/unused-broken-const.stderr b/src/test/ui/consts/const-eval/unused-broken-const.stderr
index 2ce60ec16a33f..bfc076aa5e64f 100644
--- a/src/test/ui/consts/const-eval/unused-broken-const.stderr
+++ b/src/test/ui/consts/const-eval/unused-broken-const.stderr
@@ -12,3 +12,16 @@ LL | const FOO: i32 = [][0];
 
 error: aborting due to previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/unused-broken-const.rs:5:18
+   |
+LL | const FOO: i32 = [][0];
+   | -----------------^^^^^-
+   |                  |
+   |                  index out of bounds: the length is 0 but the index is 0
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-external-macro-const-err.stderr b/src/test/ui/consts/const-external-macro-const-err.stderr
index a66d79a16160c..205ee92dfd7cf 100644
--- a/src/test/ui/consts/const-external-macro-const-err.stderr
+++ b/src/test/ui/consts/const-external-macro-const-err.stderr
@@ -11,3 +11,15 @@ LL |     static_assert!(2 + 2 == 5);
 
 error: aborting due to previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-external-macro-const-err.rs:12:5
+   |
+LL |     static_assert!(2 + 2 == 5);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this error originates in the macro `static_assert` (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/src/test/ui/consts/const-float-bits-reject-conv.stderr b/src/test/ui/consts/const-float-bits-reject-conv.stderr
index f3fd098e848a2..d822171df7234 100644
--- a/src/test/ui/consts/const-float-bits-reject-conv.stderr
+++ b/src/test/ui/consts/const-float-bits-reject-conv.stderr
@@ -214,3 +214,115 @@ LL |         const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
 error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:30:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:33:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:41:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:44:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:57:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:60:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:66:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:69:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-len-underflow-separate-spans.stderr b/src/test/ui/consts/const-len-underflow-separate-spans.stderr
index 70f645a6c40e8..0c10783476abc 100644
--- a/src/test/ui/consts/const-len-underflow-separate-spans.stderr
+++ b/src/test/ui/consts/const-len-underflow-separate-spans.stderr
@@ -19,3 +19,16 @@ LL |     let a: [i8; LEN] = unimplemented!();
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-len-underflow-separate-spans.rs:7:20
+   |
+LL | const LEN: usize = ONE - TWO;
+   | -------------------^^^^^^^^^-
+   |                    |
+   |                    attempt to compute `1_usize - 2_usize`, which would overflow
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-prop-read-static-in-const.stderr b/src/test/ui/consts/const-prop-read-static-in-const.stderr
index 94d3f1c614544..a60cd16f05a18 100644
--- a/src/test/ui/consts/const-prop-read-static-in-const.stderr
+++ b/src/test/ui/consts/const-prop-read-static-in-const.stderr
@@ -20,3 +20,16 @@ LL | const TEST: u8 = MY_STATIC;
 
 error: aborting due to previous error; 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-prop-read-static-in-const.rs:5:18
+   |
+LL | const TEST: u8 = MY_STATIC;
+   | -----------------^^^^^^^^^-
+   |                  |
+   |                  constant accesses static
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr
index a9211c17a6bc0..c6e0b321124b1 100644
--- a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr
+++ b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr
@@ -23,3 +23,29 @@ LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const
 
 error: aborting due to 2 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31
+   |
+LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               `extern type` does not have known layout
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-size_of_val-align_of_val-extern-type.rs:13:32
+   |
+LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) };
+   | -------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                |
+   |                                `extern type` does not have known layout
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const-slice-oob.stderr b/src/test/ui/consts/const-slice-oob.stderr
index 6d2c79034d391..c9f949727bc63 100644
--- a/src/test/ui/consts/const-slice-oob.stderr
+++ b/src/test/ui/consts/const-slice-oob.stderr
@@ -12,3 +12,16 @@ LL | const BAR: u32 = FOO[5];
 
 error: aborting due to previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const-slice-oob.rs:4:18
+   |
+LL | const BAR: u32 = FOO[5];
+   | -----------------^^^^^^-
+   |                  |
+   |                  index out of bounds: the length is 3 but the index is 5
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
index 5e706a4466ea1..ee95b0d518050 100644
--- a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
+++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
@@ -17,3 +17,21 @@ LL | | };
 
 error: aborting due to previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/const_eval_limit_reached.rs:6:11
+   |
+LL | / const X: usize = {
+LL | |     let mut x = 0;
+LL | |     while x != 1000 {
+   | |           ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+LL | |
+...  |
+LL | |     x
+LL | | };
+   | |__-
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/invalid-union.32bit.stderr b/src/test/ui/consts/invalid-union.32bit.stderr
index 38c38d1ae6732..bd7c95342f7f9 100644
--- a/src/test/ui/consts/invalid-union.32bit.stderr
+++ b/src/test/ui/consts/invalid-union.32bit.stderr
@@ -22,3 +22,14 @@ LL |     let _: &'static _ = &C;
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: erroneous constant used
+  --> $DIR/invalid-union.rs:41:25
+   |
+LL |     let _: &'static _ = &C;
+   |                         ^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr
index 6bfa97a2fded7..0d8b8ffcc161b 100644
--- a/src/test/ui/consts/invalid-union.64bit.stderr
+++ b/src/test/ui/consts/invalid-union.64bit.stderr
@@ -22,3 +22,14 @@ LL |     let _: &'static _ = &C;
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: erroneous constant used
+  --> $DIR/invalid-union.rs:41:25
+   |
+LL |     let _: &'static _ = &C;
+   |                         ^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/issue-56164.stderr b/src/test/ui/consts/issue-56164.stderr
index 3b80b3486a822..73a0f8ec0d04f 100644
--- a/src/test/ui/consts/issue-56164.stderr
+++ b/src/test/ui/consts/issue-56164.stderr
@@ -26,3 +26,14 @@ LL | const fn foo() { (||{})() }
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0015`.
+Future incompatibility report: Future breakage diagnostic:
+error: erroneous constant used
+  --> $DIR/issue-56164.rs:1:18
+   |
+LL | const fn foo() { (||{})() }
+   |                  ^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/issue-66693.stderr b/src/test/ui/consts/issue-66693.stderr
index b825768498386..929f905ae918b 100644
--- a/src/test/ui/consts/issue-66693.stderr
+++ b/src/test/ui/consts/issue-66693.stderr
@@ -34,3 +34,14 @@ LL |     panic!(&1);
 
 error: aborting due to 4 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: erroneous constant used
+  --> $DIR/issue-66693.rs:11:12
+   |
+LL |     panic!(&1);
+   |            ^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/issue-miri-1910.stderr b/src/test/ui/consts/issue-miri-1910.stderr
index 87882449c7342..e76a1f96b46a5 100644
--- a/src/test/ui/consts/issue-miri-1910.stderr
+++ b/src/test/ui/consts/issue-miri-1910.stderr
@@ -24,3 +24,28 @@ LL | | };
 
 error: aborting due to previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+LL |           copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |           |
+   |           unable to turn pointer into raw bytes
+   |           inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |           inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |           inside `C` at $DIR/issue-miri-1910.rs:7:5
+   |
+  ::: $DIR/issue-miri-1910.rs:4:1
+   |
+LL | / const C: () = unsafe {
+LL | |     let foo = Some(&42 as *const i32);
+LL | |     let one_and_a_half_pointers = std::mem::size_of::<*const i32>()/2*3;
+LL | |     (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read();
+LL | | };
+   | |__-
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const.stderr b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
index 193a49bb2666f..1765c9ed10a30 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const.stderr
+++ b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
@@ -15,3 +15,28 @@ LL |     const F: u32 = (U::X, 42).1;
 error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | calling non-const function `<Vec<u32> as Drop>::drop`
+   | inside `std::ptr::drop_in_place::<Vec<u32>> - shim(Some(Vec<u32>))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   | inside `std::ptr::drop_in_place::<(Vec<u32>, u32)> - shim(Some((Vec<u32>, u32)))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   | inside `<String as Bar<Vec<u32>, String>>::F` at $DIR/assoc_const.rs:14:31
+   |
+  ::: $DIR/assoc_const.rs:14:5
+   |
+LL |     const F: u32 = (U::X, 42).1;
+   |     ----------------------------
+   |
+note: the lint level is defined here
+  --> $DIR/assoc_const.rs:4:10
+   |
+LL | #![allow(const_err)]
+   |          ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr b/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr
index e15717979c5cb..f7be42de03fd6 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr
+++ b/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr
@@ -7,3 +7,20 @@ LL |     let y = <String as Bar<String>>::F;
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/assoc_const_2.rs:12:20
+   |
+LL |     const F: u32 = 100 / U::X;
+   |     ---------------^^^^^^^^^^-
+   |                    |
+   |                    attempt to divide `100_u32` by zero
+   |
+note: the lint level is defined here
+  --> $DIR/assoc_const_2.rs:3:10
+   |
+LL | #![allow(const_err)]
+   |          ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
index c48f59fe84890..98d4dff648a5f 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
@@ -47,3 +47,58 @@ LL | const READ_MUT: u32 = unsafe { MUTABLE };
 error: aborting due to 3 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const_refers_to_static.rs:13:5
+   |
+LL | / const MUTATE_INTERIOR_MUT: usize = {
+LL | |     static FOO: AtomicUsize = AtomicUsize::new(0);
+LL | |     FOO.fetch_add(1, Ordering::Relaxed)
+   | |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `AtomicUsize::fetch_add`
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/const_refers_to_static.rs:3:10
+   |
+LL | #![allow(const_err)]
+   |          ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const_refers_to_static.rs:18:14
+   |
+LL | / const READ_INTERIOR_MUT: usize = {
+LL | |     static FOO: AtomicUsize = AtomicUsize::new(0);
+LL | |     unsafe { *(&FOO as *const _ as *const usize) }
+   | |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/const_refers_to_static.rs:3:10
+   |
+LL | #![allow(const_err)]
+   |          ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const_refers_to_static.rs:22:32
+   |
+LL | const READ_MUT: u32 = unsafe { MUTABLE };
+   | -------------------------------^^^^^^^---
+   |                                |
+   |                                constant accesses static
+   |
+note: the lint level is defined here
+  --> $DIR/const_refers_to_static.rs:3:10
+   |
+LL | #![allow(const_err)]
+   |          ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
index 186c5b1856baa..2a0766294d3e0 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
@@ -170,3 +170,45 @@ LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None =>
 error: aborting due to 10 previous errors; 3 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const_refers_to_static_cross_crate.rs:25:15
+   |
+LL | / const U8_MUT2: &u8 = {
+LL | |     unsafe { &(*static_cross_crate::ZERO_REF)[0] }
+   | |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+LL | |
+LL | |
+LL | |
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/const_refers_to_static_cross_crate.rs:23:8
+   |
+LL | #[warn(const_err)]
+   |        ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+   |
+LL | / const U8_MUT3: &u8 = {
+LL | |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
+   | |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+LL | |
+LL | |
+LL | |
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/const_refers_to_static_cross_crate.rs:30:8
+   |
+LL | #[warn(const_err)]
+   |        ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
index 7a64abd7b9cb8..2d4f038d91490 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
@@ -170,3 +170,45 @@ LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None =>
 error: aborting due to 10 previous errors; 3 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const_refers_to_static_cross_crate.rs:25:15
+   |
+LL | / const U8_MUT2: &u8 = {
+LL | |     unsafe { &(*static_cross_crate::ZERO_REF)[0] }
+   | |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+LL | |
+LL | |
+LL | |
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/const_refers_to_static_cross_crate.rs:23:8
+   |
+LL | #[warn(const_err)]
+   |        ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+   |
+LL | / const U8_MUT3: &u8 = {
+LL | |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
+   | |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+LL | |
+LL | |
+LL | |
+LL | | };
+   | |__-
+   |
+note: the lint level is defined here
+  --> $DIR/const_refers_to_static_cross_crate.rs:30:8
+   |
+LL | #[warn(const_err)]
+   |        ^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr
index 12f6ca0b51a53..594576fe2cf3d 100644
--- a/src/test/ui/consts/ptr_comparisons.stderr
+++ b/src/test/ui/consts/ptr_comparisons.stderr
@@ -44,3 +44,29 @@ LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4
 error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ptr_comparisons.rs:65:27
+   |
+LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
+   | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                           |
+   |                           unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/ptr_comparisons.rs:70:27
+   |
+LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
+   | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------
+   |                           |
+   |                           unable to turn pointer into raw bytes
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/recursive.stderr b/src/test/ui/consts/recursive.stderr
index 31ac1fff4e84e..8d1e10d4176ff 100644
--- a/src/test/ui/consts/recursive.stderr
+++ b/src/test/ui/consts/recursive.stderr
@@ -29,3 +29,22 @@ LL | const X: () = f(1);
 
 error: aborting due to previous error; 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/recursive.rs:4:5
+   |
+LL |     f(x);
+   |     ^^^^
+   |     |
+   |     reached the configured maximum number of stack frames
+   |     inside `f::<i32>` at $DIR/recursive.rs:4:5
+   |     [... 126 additional calls inside `f::<i32>` at $DIR/recursive.rs:4:5 ...]
+   |     inside `X` at $DIR/recursive.rs:9:15
+...
+LL | const X: () = f(1);
+   | -------------------
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.stderr b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
index e98eefc11c3c8..17dd6131436c3 100644
--- a/src/test/ui/consts/uninhabited-const-issue-61744.stderr
+++ b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
@@ -150,3 +150,147 @@ LL |     dbg!(i32::CONSTANT);
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: any use of this value will cause an error
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+   |     |
+   |     reached the configured maximum number of stack frames
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
+   |     inside `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside `<i32 as Const>::CONSTANT` at $DIR/uninhabited-const-issue-61744.rs:13:36
+...
+LL |     const CONSTANT: i32 = unsafe { fake_type() };
+   |     ---------------------------------------------
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/intrinsics/auxiliary/cci_intrinsic.rs b/src/test/ui/intrinsics/auxiliary/cci_intrinsic.rs
index f65f359875bfd..f3b9d569ce3b1 100644
--- a/src/test/ui/intrinsics/auxiliary/cci_intrinsic.rs
+++ b/src/test/ui/intrinsics/auxiliary/cci_intrinsic.rs
@@ -2,13 +2,13 @@
 
 pub mod rusti {
     extern "rust-intrinsic" {
-        pub fn atomic_xchg<T>(dst: *mut T, src: T) -> T;
+        pub fn atomic_xchg_seqcst<T>(dst: *mut T, src: T) -> T;
     }
 }
 
 #[inline(always)]
-pub fn atomic_xchg(dst: *mut isize, src: isize) -> isize {
+pub fn atomic_xchg_seqcst(dst: *mut isize, src: isize) -> isize {
     unsafe {
-        rusti::atomic_xchg(dst, src)
+        rusti::atomic_xchg_seqcst(dst, src)
     }
 }
diff --git a/src/test/ui/intrinsics/intrinsic-atomics-cc.rs b/src/test/ui/intrinsics/intrinsic-atomics-cc.rs
index 52e891da9ba77..ce3fa7b0c05e6 100644
--- a/src/test/ui/intrinsics/intrinsic-atomics-cc.rs
+++ b/src/test/ui/intrinsics/intrinsic-atomics-cc.rs
@@ -3,10 +3,10 @@
 
 
 extern crate cci_intrinsic;
-use cci_intrinsic::atomic_xchg;
+use cci_intrinsic::atomic_xchg_seqcst;
 
 pub fn main() {
     let mut x = 1;
-    atomic_xchg(&mut x, 5);
+    atomic_xchg_seqcst(&mut x, 5);
     assert_eq!(x, 5);
 }
diff --git a/src/test/ui/intrinsics/intrinsic-atomics.rs b/src/test/ui/intrinsics/intrinsic-atomics.rs
index c6e48e8b5afba..b17f4347be31c 100644
--- a/src/test/ui/intrinsics/intrinsic-atomics.rs
+++ b/src/test/ui/intrinsics/intrinsic-atomics.rs
@@ -3,31 +3,31 @@
 
 mod rusti {
     extern "rust-intrinsic" {
-        pub fn atomic_cxchg<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-        pub fn atomic_cxchg_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-        pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+        pub fn atomic_cxchg_seqcst_seqcst<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+        pub fn atomic_cxchg_acquire_acquire<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+        pub fn atomic_cxchg_release_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
 
-        pub fn atomic_cxchgweak<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-        pub fn atomic_cxchgweak_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-        pub fn atomic_cxchgweak_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+        pub fn atomic_cxchgweak_seqcst_seqcst<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+        pub fn atomic_cxchgweak_acquire_acquire<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+        pub fn atomic_cxchgweak_release_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
 
-        pub fn atomic_load<T>(src: *const T) -> T;
-        pub fn atomic_load_acq<T>(src: *const T) -> T;
+        pub fn atomic_load_seqcst<T>(src: *const T) -> T;
+        pub fn atomic_load_acquire<T>(src: *const T) -> T;
 
-        pub fn atomic_store<T>(dst: *mut T, val: T);
-        pub fn atomic_store_rel<T>(dst: *mut T, val: T);
+        pub fn atomic_store_seqcst<T>(dst: *mut T, val: T);
+        pub fn atomic_store_release<T>(dst: *mut T, val: T);
 
-        pub fn atomic_xchg<T>(dst: *mut T, src: T) -> T;
-        pub fn atomic_xchg_acq<T>(dst: *mut T, src: T) -> T;
-        pub fn atomic_xchg_rel<T>(dst: *mut T, src: T) -> T;
+        pub fn atomic_xchg_seqcst<T>(dst: *mut T, src: T) -> T;
+        pub fn atomic_xchg_acquire<T>(dst: *mut T, src: T) -> T;
+        pub fn atomic_xchg_release<T>(dst: *mut T, src: T) -> T;
 
-        pub fn atomic_xadd<T>(dst: *mut T, src: T) -> T;
-        pub fn atomic_xadd_acq<T>(dst: *mut T, src: T) -> T;
-        pub fn atomic_xadd_rel<T>(dst: *mut T, src: T) -> T;
+        pub fn atomic_xadd_seqcst<T>(dst: *mut T, src: T) -> T;
+        pub fn atomic_xadd_acquire<T>(dst: *mut T, src: T) -> T;
+        pub fn atomic_xadd_release<T>(dst: *mut T, src: T) -> T;
 
-        pub fn atomic_xsub<T>(dst: *mut T, src: T) -> T;
-        pub fn atomic_xsub_acq<T>(dst: *mut T, src: T) -> T;
-        pub fn atomic_xsub_rel<T>(dst: *mut T, src: T) -> T;
+        pub fn atomic_xsub_seqcst<T>(dst: *mut T, src: T) -> T;
+        pub fn atomic_xsub_acquire<T>(dst: *mut T, src: T) -> T;
+        pub fn atomic_xsub_release<T>(dst: *mut T, src: T) -> T;
     }
 }
 
@@ -35,45 +35,45 @@ pub fn main() {
     unsafe {
         let mut x: Box<_> = Box::new(1);
 
-        assert_eq!(rusti::atomic_load(&*x), 1);
+        assert_eq!(rusti::atomic_load_seqcst(&*x), 1);
         *x = 5;
-        assert_eq!(rusti::atomic_load_acq(&*x), 5);
+        assert_eq!(rusti::atomic_load_acquire(&*x), 5);
 
-        rusti::atomic_store(&mut *x,3);
+        rusti::atomic_store_seqcst(&mut *x,3);
         assert_eq!(*x, 3);
-        rusti::atomic_store_rel(&mut *x,1);
+        rusti::atomic_store_release(&mut *x,1);
         assert_eq!(*x, 1);
 
-        assert_eq!(rusti::atomic_cxchg(&mut *x, 1, 2), (1, true));
+        assert_eq!(rusti::atomic_cxchg_seqcst_seqcst(&mut *x, 1, 2), (1, true));
         assert_eq!(*x, 2);
 
-        assert_eq!(rusti::atomic_cxchg_acq(&mut *x, 1, 3), (2, false));
+        assert_eq!(rusti::atomic_cxchg_acquire_acquire(&mut *x, 1, 3), (2, false));
         assert_eq!(*x, 2);
 
-        assert_eq!(rusti::atomic_cxchg_rel(&mut *x, 2, 1), (2, true));
+        assert_eq!(rusti::atomic_cxchg_release_relaxed(&mut *x, 2, 1), (2, true));
         assert_eq!(*x, 1);
 
-        assert_eq!(rusti::atomic_xchg(&mut *x, 0), 1);
+        assert_eq!(rusti::atomic_xchg_seqcst(&mut *x, 0), 1);
         assert_eq!(*x, 0);
 
-        assert_eq!(rusti::atomic_xchg_acq(&mut *x, 1), 0);
+        assert_eq!(rusti::atomic_xchg_acquire(&mut *x, 1), 0);
         assert_eq!(*x, 1);
 
-        assert_eq!(rusti::atomic_xchg_rel(&mut *x, 0), 1);
+        assert_eq!(rusti::atomic_xchg_release(&mut *x, 0), 1);
         assert_eq!(*x, 0);
 
-        assert_eq!(rusti::atomic_xadd(&mut *x, 1), 0);
-        assert_eq!(rusti::atomic_xadd_acq(&mut *x, 1), 1);
-        assert_eq!(rusti::atomic_xadd_rel(&mut *x, 1), 2);
+        assert_eq!(rusti::atomic_xadd_seqcst(&mut *x, 1), 0);
+        assert_eq!(rusti::atomic_xadd_acquire(&mut *x, 1), 1);
+        assert_eq!(rusti::atomic_xadd_release(&mut *x, 1), 2);
         assert_eq!(*x, 3);
 
-        assert_eq!(rusti::atomic_xsub(&mut *x, 1), 3);
-        assert_eq!(rusti::atomic_xsub_acq(&mut *x, 1), 2);
-        assert_eq!(rusti::atomic_xsub_rel(&mut *x, 1), 1);
+        assert_eq!(rusti::atomic_xsub_seqcst(&mut *x, 1), 3);
+        assert_eq!(rusti::atomic_xsub_acquire(&mut *x, 1), 2);
+        assert_eq!(rusti::atomic_xsub_release(&mut *x, 1), 1);
         assert_eq!(*x, 0);
 
         loop {
-            let res = rusti::atomic_cxchgweak(&mut *x, 0, 1);
+            let res = rusti::atomic_cxchgweak_seqcst_seqcst(&mut *x, 0, 1);
             assert_eq!(res.0, 0);
             if res.1 {
                 break;
@@ -82,7 +82,7 @@ pub fn main() {
         assert_eq!(*x, 1);
 
         loop {
-            let res = rusti::atomic_cxchgweak_acq(&mut *x, 1, 2);
+            let res = rusti::atomic_cxchgweak_acquire_acquire(&mut *x, 1, 2);
             assert_eq!(res.0, 1);
             if res.1 {
                 break;
@@ -91,7 +91,7 @@ pub fn main() {
         assert_eq!(*x, 2);
 
         loop {
-            let res = rusti::atomic_cxchgweak_rel(&mut *x, 2, 3);
+            let res = rusti::atomic_cxchgweak_release_relaxed(&mut *x, 2, 3);
             assert_eq!(res.0, 2);
             if res.1 {
                 break;
diff --git a/src/test/ui/intrinsics/non-integer-atomic.rs b/src/test/ui/intrinsics/non-integer-atomic.rs
index 00a7f368a0fa8..85ea81ba67961 100644
--- a/src/test/ui/intrinsics/non-integer-atomic.rs
+++ b/src/test/ui/intrinsics/non-integer-atomic.rs
@@ -12,81 +12,81 @@ pub type Bar = &'static Fn();
 pub type Quux = [u8; 100];
 
 pub unsafe fn test_bool_load(p: &mut bool, v: bool) {
-    intrinsics::atomic_load(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
+    intrinsics::atomic_load_seqcst(p);
+    //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `bool`
 }
 
 pub unsafe fn test_bool_store(p: &mut bool, v: bool) {
-    intrinsics::atomic_store(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
+    intrinsics::atomic_store_seqcst(p, v);
+    //~^ ERROR `atomic_store_seqcst` intrinsic: expected basic integer type, found `bool`
 }
 
 pub unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
-    intrinsics::atomic_xchg(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+    intrinsics::atomic_xchg_seqcst(p, v);
+    //~^ ERROR `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `bool`
 }
 
 pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
-    intrinsics::atomic_cxchg(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+    intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+    //~^ ERROR `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `bool`
 }
 
 pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
-    intrinsics::atomic_load(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
+    intrinsics::atomic_load_seqcst(p);
+    //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `Foo`
 }
 
 pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
-    intrinsics::atomic_store(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
+    intrinsics::atomic_store_seqcst(p, v);
+    //~^ ERROR `atomic_store_seqcst` intrinsic: expected basic integer type, found `Foo`
 }
 
 pub unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
-    intrinsics::atomic_xchg(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+    intrinsics::atomic_xchg_seqcst(p, v);
+    //~^ ERROR `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `Foo`
 }
 
 pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
-    intrinsics::atomic_cxchg(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+    intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+    //~^ ERROR `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `Foo`
 }
 
 pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
-    intrinsics::atomic_load(p);
+    intrinsics::atomic_load_seqcst(p);
     //~^ ERROR expected basic integer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
-    intrinsics::atomic_store(p, v);
+    intrinsics::atomic_store_seqcst(p, v);
     //~^ ERROR expected basic integer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
-    intrinsics::atomic_xchg(p, v);
+    intrinsics::atomic_xchg_seqcst(p, v);
     //~^ ERROR expected basic integer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
-    intrinsics::atomic_cxchg(p, v, v);
+    intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
     //~^ ERROR expected basic integer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
-    intrinsics::atomic_load(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+    intrinsics::atomic_load_seqcst(p);
+    //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
 }
 
 pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
-    intrinsics::atomic_store(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+    intrinsics::atomic_store_seqcst(p, v);
+    //~^ ERROR `atomic_store_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
 }
 
 pub unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
-    intrinsics::atomic_xchg(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+    intrinsics::atomic_xchg_seqcst(p, v);
+    //~^ ERROR `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
 }
 
 pub unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
-    intrinsics::atomic_cxchg(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+    intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+    //~^ ERROR `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
 }
diff --git a/src/test/ui/intrinsics/non-integer-atomic.stderr b/src/test/ui/intrinsics/non-integer-atomic.stderr
index ee485c21cd696..32791a8e8b7f1 100644
--- a/src/test/ui/intrinsics/non-integer-atomic.stderr
+++ b/src/test/ui/intrinsics/non-integer-atomic.stderr
@@ -1,98 +1,98 @@
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `bool`
   --> $DIR/non-integer-atomic.rs:15:5
    |
-LL |     intrinsics::atomic_load(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_load_seqcst(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `bool`
   --> $DIR/non-integer-atomic.rs:20:5
    |
-LL |     intrinsics::atomic_store(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_store_seqcst(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `bool`
   --> $DIR/non-integer-atomic.rs:25:5
    |
-LL |     intrinsics::atomic_xchg(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_xchg_seqcst(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `bool`
   --> $DIR/non-integer-atomic.rs:30:5
    |
-LL |     intrinsics::atomic_cxchg(p, v, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:35:5
    |
-LL |     intrinsics::atomic_load(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_load_seqcst(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:40:5
    |
-LL |     intrinsics::atomic_store(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_store_seqcst(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:45:5
    |
-LL |     intrinsics::atomic_xchg(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_xchg_seqcst(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:50:5
    |
-LL |     intrinsics::atomic_cxchg(p, v, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:55:5
    |
-LL |     intrinsics::atomic_load(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_load_seqcst(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:60:5
    |
-LL |     intrinsics::atomic_store(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_store_seqcst(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:65:5
    |
-LL |     intrinsics::atomic_xchg(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_xchg_seqcst(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:70:5
    |
-LL |     intrinsics::atomic_cxchg(p, v, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:75:5
    |
-LL |     intrinsics::atomic_load(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_load_seqcst(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:80:5
    |
-LL |     intrinsics::atomic_store(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_store_seqcst(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:85:5
    |
-LL |     intrinsics::atomic_xchg(p, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_xchg_seqcst(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:90:5
    |
-LL |     intrinsics::atomic_cxchg(p, v, v);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 16 previous errors
 
diff --git a/src/test/ui/limits/issue-55878.stderr b/src/test/ui/limits/issue-55878.stderr
index 90411353f0825..1402d1387037e 100644
--- a/src/test/ui/limits/issue-55878.stderr
+++ b/src/test/ui/limits/issue-55878.stderr
@@ -23,3 +23,15 @@ LL |     println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: erroneous constant used
+  --> $DIR/issue-55878.rs:7:26
+   |
+LL |     println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr
index af6308f0d1b4f..c14529a7d090a 100644
--- a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr
+++ b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr
@@ -12,3 +12,16 @@ LL | const C: i32 = 1 / 0;
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/allowed-cli-deny-by-default-lint.rs:6:16
+   |
+LL | const C: i32 = 1 / 0;
+   | ---------------^^^^^-
+   |                |
+   |                attempt to divide `1_i32` by zero
+   |
+   = note: requested on the command line with `--force-warn const-err`
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr
index 05656afd22d88..dd71a168960ab 100644
--- a/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr
+++ b/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr
@@ -12,3 +12,16 @@ LL | const C: i32 = 1 / 0;
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/allowed-deny-by-default-lint.rs:7:16
+   |
+LL | const C: i32 = 1 / 0;
+   | ---------------^^^^^-
+   |                |
+   |                attempt to divide `1_i32` by zero
+   |
+   = note: requested on the command line with `--force-warn const-err`
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/lint/force-warn/deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/deny-by-default-lint.stderr
index ef295f99e649c..d4e80584669ae 100644
--- a/src/test/ui/lint/force-warn/deny-by-default-lint.stderr
+++ b/src/test/ui/lint/force-warn/deny-by-default-lint.stderr
@@ -12,3 +12,16 @@ LL | const C: i32 = 1 / 0;
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: any use of this value will cause an error
+  --> $DIR/deny-by-default-lint.rs:5:16
+   |
+LL | const C: i32 = 1 / 0;
+   | ---------------^^^^^-
+   |                |
+   |                attempt to divide `1_i32` by zero
+   |
+   = note: requested on the command line with `--force-warn const-err`
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
diff --git a/src/test/ui/mir/issue-92893.rs b/src/test/ui/mir/issue-92893.rs
index d2bbb4f110114..635050f376c8a 100644
--- a/src/test/ui/mir/issue-92893.rs
+++ b/src/test/ui/mir/issue-92893.rs
@@ -1,6 +1,7 @@
 struct Bug<A = [(); (let a = (), 1).1]> {
     //~^ `let` expressions are not supported here
-    //~^^ `let` expressions in this position are unstable [E0658]
+    //~| `let` expressions in this position are unstable [E0658]
+    //~| expected expression, found `let` statement
     a: A
 }
 
diff --git a/src/test/ui/mir/issue-92893.stderr b/src/test/ui/mir/issue-92893.stderr
index 063b5d66feb45..4a0fcce31d7c7 100644
--- a/src/test/ui/mir/issue-92893.stderr
+++ b/src/test/ui/mir/issue-92893.stderr
@@ -1,3 +1,9 @@
+error: expected expression, found `let` statement
+  --> $DIR/issue-92893.rs:1:22
+   |
+LL | struct Bug<A = [(); (let a = (), 1).1]> {
+   |                      ^^^
+
 error: `let` expressions are not supported here
   --> $DIR/issue-92893.rs:1:22
    |
@@ -15,6 +21,6 @@ LL | struct Bug<A = [(); (let a = (), 1).1]> {
    = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs
index 4a36515b99128..bb1aff70d8995 100644
--- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs
+++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs
@@ -58,8 +58,10 @@ fn _macros() {
     }
     use_expr!((let 0 = 1 && 0 == 0));
     //~^ ERROR `let` expressions in this position are unstable
+    //~| ERROR expected expression, found `let` statement
     use_expr!((let 0 = 1));
     //~^ ERROR `let` expressions in this position are unstable
+    //~| ERROR expected expression, found `let` statement
     match () {
         #[cfg(FALSE)]
         () if let 0 = 1 => {}
diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr
index 8d93fb87f7ad1..370a57318fdd0 100644
--- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr
+++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr
@@ -1,5 +1,17 @@
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:59:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:62:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^
+
 error: no rules expected the token `let`
-  --> $DIR/feature-gate.rs:69:15
+  --> $DIR/feature-gate.rs:71:15
    |
 LL |     macro_rules! use_expr {
    |     --------------------- when calling this macro
@@ -58,7 +70,7 @@ LL |         () if let Range { start: _, end: _ } = (true..true) && false => {}
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
 error[E0658]: `if let` guards are experimental
-  --> $DIR/feature-gate.rs:65:12
+  --> $DIR/feature-gate.rs:67:12
    |
 LL |         () if let 0 = 1 => {}
    |            ^^^^^^^^^^^^
@@ -203,7 +215,7 @@ LL |     use_expr!((let 0 = 1 && 0 == 0));
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:61:16
+  --> $DIR/feature-gate.rs:62:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
@@ -211,6 +223,6 @@ LL |     use_expr!((let 0 = 1));
    = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
-error: aborting due to 23 previous errors
+error: aborting due to 25 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
index 1bd8b74240eac..36b730505c29e 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
@@ -81,9 +81,11 @@ fn _macros() {
     use_expr!((let 0 = 1 && 0 == 0));
     //~^ ERROR `let` expressions are not supported here
     //~| ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
     use_expr!((let 0 = 1));
     //~^ ERROR `let` expressions are not supported here
     //~| ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 }
 
 fn nested_within_if_expr() {
@@ -147,7 +149,8 @@ fn nested_within_if_expr() {
     //~| ERROR mismatched types
     //~| ERROR mismatched types
 
-    if let true = let true = true {} //~ ERROR `let` expressions are not supported here
+    if let true = let true = true {}
+    //~^ ERROR `let` expressions are not supported here
 }
 
 fn nested_within_while_expr() {
@@ -211,7 +214,8 @@ fn nested_within_while_expr() {
     //~| ERROR mismatched types
     //~| ERROR mismatched types
 
-    while let true = let true = true {} //~ ERROR `let` expressions are not supported here
+    while let true = let true = true {}
+    //~^ ERROR `let` expressions are not supported here
 }
 
 fn not_error_because_clarified_intent() {
@@ -225,45 +229,85 @@ fn not_error_because_clarified_intent() {
 }
 
 fn outside_if_and_while_expr() {
-    &let 0 = 0; //~ ERROR `let` expressions are not supported here
+    &let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 
-    !let 0 = 0; //~ ERROR `let` expressions are not supported here
-    *let 0 = 0; //~ ERROR `let` expressions are not supported here
-    //~^ ERROR type `bool` cannot be dereferenced
-    -let 0 = 0; //~ ERROR `let` expressions are not supported here
-    //~^ ERROR cannot apply unary operator `-` to type `bool`
+    !let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    *let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR type `bool` cannot be dereferenced
+    //~| ERROR expected expression, found `let` statement
+    -let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR cannot apply unary operator `-` to type `bool`
+    //~| ERROR expected expression, found `let` statement
 
     fn _check_try_binds_tighter() -> Result<(), ()> {
         let 0 = 0?;
         //~^ ERROR the `?` operator can only be applied to values that implement `Try`
         Ok(())
     }
-    (let 0 = 0)?; //~ ERROR `let` expressions are not supported here
-    //~^ ERROR the `?` operator can only be used in a function that returns `Result`
+    (let 0 = 0)?;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR the `?` operator can only be used in a function that returns `Result`
     //~| ERROR the `?` operator can only be applied to values that implement `Try`
+    //~| ERROR expected expression, found `let` statement
 
-    true || let 0 = 0; //~ ERROR `let` expressions are not supported here
-    (true || let 0 = 0); //~ ERROR `let` expressions are not supported here
-    true && (true || let 0 = 0); //~ ERROR `let` expressions are not supported here
+    true || let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    (true || let 0 = 0);
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    true && (true || let 0 = 0);
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 
     let mut x = true;
-    x = let 0 = 0; //~ ERROR `let` expressions are not supported here
+    x = let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 
-    true..(let 0 = 0); //~ ERROR `let` expressions are not supported here
-    ..(let 0 = 0); //~ ERROR `let` expressions are not supported here
-    (let 0 = 0)..; //~ ERROR `let` expressions are not supported here
+    true..(let 0 = 0);
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    ..(let 0 = 0);
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    (let 0 = 0)..;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 
     (let Range { start: _, end: _ } = true..true || false);
     //~^ ERROR `let` expressions are not supported here
     //~| ERROR mismatched types
+    //~| ERROR expected expression, found `let` statement
 
     (let true = let true = true);
     //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    //~| ERROR expected expression, found `let` statement
+
+    {
+        #[cfg(FALSE)]
+        let x = true && let y = 1;
+        //~^ ERROR expected expression, found `let` statement
+    }
+
+    #[cfg(FALSE)]
+    {
+        [1, 2, 3][let _ = ()]
+        //~^ ERROR expected expression, found `let` statement
+    }
 
     // Check function tail position.
     &let 0 = 0
     //~^ ERROR `let` expressions are not supported here
     //~| ERROR mismatched types
+    //~| ERROR expected expression, found `let` statement
 }
 
 // Let's make sure that `let` inside const generic arguments are considered.
@@ -335,4 +379,14 @@ fn with_parenthesis() {
     let fun = || true;
     if let true = (true && fun()) && (true) {
     }
+
+    #[cfg(FALSE)]
+    let x = (true && let y = 1);
+    //~^ ERROR expected expression, found `let` statement
+
+    #[cfg(FALSE)]
+    {
+        ([1, 2, 3][let _ = ()])
+        //~^ ERROR expected expression, found `let` statement
+    }
 }
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index f7f39bd0b9a07..5cf06cf4b27cd 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -1,5 +1,113 @@
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:232:6
+   |
+LL |     &let 0 = 0;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:236:6
+   |
+LL |     !let 0 = 0;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:239:6
+   |
+LL |     *let 0 = 0;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:243:6
+   |
+LL |     -let 0 = 0;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:253:6
+   |
+LL |     (let 0 = 0)?;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:259:13
+   |
+LL |     true || let 0 = 0;
+   |             ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:262:14
+   |
+LL |     (true || let 0 = 0);
+   |              ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:265:22
+   |
+LL |     true && (true || let 0 = 0);
+   |                      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:270:9
+   |
+LL |     x = let 0 = 0;
+   |         ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:274:12
+   |
+LL |     true..(let 0 = 0);
+   |            ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:277:8
+   |
+LL |     ..(let 0 = 0);
+   |        ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:280:6
+   |
+LL |     (let 0 = 0)..;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:284:6
+   |
+LL |     (let Range { start: _, end: _ } = true..true || false);
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:289:6
+   |
+LL |     (let true = let true = true);
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:289:17
+   |
+LL |     (let true = let true = true);
+   |                 ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:296:25
+   |
+LL |         let x = true && let y = 1;
+   |                         ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:302:19
+   |
+LL |         [1, 2, 3][let _ = ()]
+   |                   ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:307:6
+   |
+LL |     &let 0 = 0
+   |      ^^^
+
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/disallowed-positions.rs:293:9
+  --> $DIR/disallowed-positions.rs:337:9
    |
 LL |         true && let 1 = 1
    |         ^^^^^^^^^^^^^^^^^
@@ -9,6 +117,30 @@ help: enclose the `const` expression in braces
 LL |         { true && let 1 = 1 }
    |         +                   +
 
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:384:22
+   |
+LL |     let x = (true && let y = 1);
+   |                      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:389:20
+   |
+LL |         ([1, 2, 3][let _ = ()])
+   |                    ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:81:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:85:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^
+
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:29:9
    |
@@ -270,33 +402,33 @@ LL |     use_expr!((let 0 = 1 && 0 == 0));
    |                ^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:84:16
+  --> $DIR/disallowed-positions.rs:85:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:84:16
+  --> $DIR/disallowed-positions.rs:85:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:84:16
+  --> $DIR/disallowed-positions.rs:85:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:84:16
+  --> $DIR/disallowed-positions.rs:85:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:90:9
+  --> $DIR/disallowed-positions.rs:92:9
    |
 LL |     if &let 0 = 0 {}
    |         ^^^^^^^^^
@@ -304,7 +436,7 @@ LL |     if &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:93:9
+  --> $DIR/disallowed-positions.rs:95:9
    |
 LL |     if !let 0 = 0 {}
    |         ^^^^^^^^^
@@ -312,7 +444,7 @@ LL |     if !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:94:9
+  --> $DIR/disallowed-positions.rs:96:9
    |
 LL |     if *let 0 = 0 {}
    |         ^^^^^^^^^
@@ -320,7 +452,7 @@ LL |     if *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:96:9
+  --> $DIR/disallowed-positions.rs:98:9
    |
 LL |     if -let 0 = 0 {}
    |         ^^^^^^^^^
@@ -328,72 +460,72 @@ LL |     if -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:104:9
+  --> $DIR/disallowed-positions.rs:106:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:104:9
+  --> $DIR/disallowed-positions.rs:106:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:108:16
+  --> $DIR/disallowed-positions.rs:110:16
    |
 LL |     if true || let 0 = 0 {}
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:108:13
+  --> $DIR/disallowed-positions.rs:110:13
    |
 LL |     if true || let 0 = 0 {}
    |             ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:109:17
+  --> $DIR/disallowed-positions.rs:111:17
    |
 LL |     if (true || let 0 = 0) {}
    |                 ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:109:14
+  --> $DIR/disallowed-positions.rs:111:14
    |
 LL |     if (true || let 0 = 0) {}
    |              ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:110:25
+  --> $DIR/disallowed-positions.rs:112:25
    |
 LL |     if true && (true || let 0 = 0) {}
    |                         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:110:22
+  --> $DIR/disallowed-positions.rs:112:22
    |
 LL |     if true && (true || let 0 = 0) {}
    |                      ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:111:25
+  --> $DIR/disallowed-positions.rs:113:25
    |
 LL |     if true || (true && let 0 = 0) {}
    |                         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:111:17
+  --> $DIR/disallowed-positions.rs:113:17
    |
 LL |     if true || (true && let 0 = 0) {}
    |                 ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:114:12
+  --> $DIR/disallowed-positions.rs:116:12
    |
 LL |     if x = let 0 = 0 {}
    |            ^^^^^^^^^
@@ -401,46 +533,46 @@ LL |     if x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:117:15
+  --> $DIR/disallowed-positions.rs:119:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:117:15
+  --> $DIR/disallowed-positions.rs:119:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:119:11
+  --> $DIR/disallowed-positions.rs:121:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:119:11
+  --> $DIR/disallowed-positions.rs:121:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:121:9
+  --> $DIR/disallowed-positions.rs:123:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:121:9
+  --> $DIR/disallowed-positions.rs:123:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:125:8
+  --> $DIR/disallowed-positions.rs:127:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -448,7 +580,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:129:8
+  --> $DIR/disallowed-positions.rs:131:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -456,7 +588,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:136:8
+  --> $DIR/disallowed-positions.rs:138:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -464,7 +596,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:144:8
+  --> $DIR/disallowed-positions.rs:146:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -472,7 +604,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:150:19
+  --> $DIR/disallowed-positions.rs:152:19
    |
 LL |     if let true = let true = true {}
    |                   ^^^^^^^^^^^^^^^
@@ -480,7 +612,7 @@ LL |     if let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:154:12
+  --> $DIR/disallowed-positions.rs:157:12
    |
 LL |     while &let 0 = 0 {}
    |            ^^^^^^^^^
@@ -488,7 +620,7 @@ LL |     while &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:157:12
+  --> $DIR/disallowed-positions.rs:160:12
    |
 LL |     while !let 0 = 0 {}
    |            ^^^^^^^^^
@@ -496,7 +628,7 @@ LL |     while !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:158:12
+  --> $DIR/disallowed-positions.rs:161:12
    |
 LL |     while *let 0 = 0 {}
    |            ^^^^^^^^^
@@ -504,7 +636,7 @@ LL |     while *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:160:12
+  --> $DIR/disallowed-positions.rs:163:12
    |
 LL |     while -let 0 = 0 {}
    |            ^^^^^^^^^
@@ -512,72 +644,72 @@ LL |     while -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:168:12
+  --> $DIR/disallowed-positions.rs:171:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:168:12
+  --> $DIR/disallowed-positions.rs:171:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:172:19
+  --> $DIR/disallowed-positions.rs:175:19
    |
 LL |     while true || let 0 = 0 {}
    |                   ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:172:16
+  --> $DIR/disallowed-positions.rs:175:16
    |
 LL |     while true || let 0 = 0 {}
    |                ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:173:20
+  --> $DIR/disallowed-positions.rs:176:20
    |
 LL |     while (true || let 0 = 0) {}
    |                    ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:173:17
+  --> $DIR/disallowed-positions.rs:176:17
    |
 LL |     while (true || let 0 = 0) {}
    |                 ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:174:28
+  --> $DIR/disallowed-positions.rs:177:28
    |
 LL |     while true && (true || let 0 = 0) {}
    |                            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:174:25
+  --> $DIR/disallowed-positions.rs:177:25
    |
 LL |     while true && (true || let 0 = 0) {}
    |                         ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:175:28
+  --> $DIR/disallowed-positions.rs:178:28
    |
 LL |     while true || (true && let 0 = 0) {}
    |                            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:175:20
+  --> $DIR/disallowed-positions.rs:178:20
    |
 LL |     while true || (true && let 0 = 0) {}
    |                    ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:178:15
+  --> $DIR/disallowed-positions.rs:181:15
    |
 LL |     while x = let 0 = 0 {}
    |               ^^^^^^^^^
@@ -585,46 +717,46 @@ LL |     while x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:181:18
+  --> $DIR/disallowed-positions.rs:184:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:181:18
+  --> $DIR/disallowed-positions.rs:184:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:183:14
+  --> $DIR/disallowed-positions.rs:186:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:183:14
+  --> $DIR/disallowed-positions.rs:186:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:185:12
+  --> $DIR/disallowed-positions.rs:188:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:185:12
+  --> $DIR/disallowed-positions.rs:188:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:189:11
+  --> $DIR/disallowed-positions.rs:192:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -632,7 +764,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:193:11
+  --> $DIR/disallowed-positions.rs:196:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -640,7 +772,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:200:11
+  --> $DIR/disallowed-positions.rs:203:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -648,7 +780,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:208:11
+  --> $DIR/disallowed-positions.rs:211:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -656,7 +788,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:214:22
+  --> $DIR/disallowed-positions.rs:217:22
    |
 LL |     while let true = let true = true {}
    |                      ^^^^^^^^^^^^^^^
@@ -664,7 +796,7 @@ LL |     while let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:228:6
+  --> $DIR/disallowed-positions.rs:232:6
    |
 LL |     &let 0 = 0;
    |      ^^^^^^^^^
@@ -672,7 +804,7 @@ LL |     &let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:230:6
+  --> $DIR/disallowed-positions.rs:236:6
    |
 LL |     !let 0 = 0;
    |      ^^^^^^^^^
@@ -680,7 +812,7 @@ LL |     !let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:231:6
+  --> $DIR/disallowed-positions.rs:239:6
    |
 LL |     *let 0 = 0;
    |      ^^^^^^^^^
@@ -688,7 +820,7 @@ LL |     *let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:233:6
+  --> $DIR/disallowed-positions.rs:243:6
    |
 LL |     -let 0 = 0;
    |      ^^^^^^^^^
@@ -696,59 +828,59 @@ LL |     -let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:241:6
+  --> $DIR/disallowed-positions.rs:253:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:241:6
+  --> $DIR/disallowed-positions.rs:253:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:245:13
+  --> $DIR/disallowed-positions.rs:259:13
    |
 LL |     true || let 0 = 0;
    |             ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:245:10
+  --> $DIR/disallowed-positions.rs:259:10
    |
 LL |     true || let 0 = 0;
    |          ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:246:14
+  --> $DIR/disallowed-positions.rs:262:14
    |
 LL |     (true || let 0 = 0);
    |              ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:246:11
+  --> $DIR/disallowed-positions.rs:262:11
    |
 LL |     (true || let 0 = 0);
    |           ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:247:22
+  --> $DIR/disallowed-positions.rs:265:22
    |
 LL |     true && (true || let 0 = 0);
    |                      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:247:19
+  --> $DIR/disallowed-positions.rs:265:19
    |
 LL |     true && (true || let 0 = 0);
    |                   ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:250:9
+  --> $DIR/disallowed-positions.rs:270:9
    |
 LL |     x = let 0 = 0;
    |         ^^^^^^^^^
@@ -756,46 +888,46 @@ LL |     x = let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:252:12
+  --> $DIR/disallowed-positions.rs:274:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:252:12
+  --> $DIR/disallowed-positions.rs:274:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:253:8
+  --> $DIR/disallowed-positions.rs:277:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:253:8
+  --> $DIR/disallowed-positions.rs:277:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:254:6
+  --> $DIR/disallowed-positions.rs:280:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:254:6
+  --> $DIR/disallowed-positions.rs:280:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:256:6
+  --> $DIR/disallowed-positions.rs:284:6
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -803,20 +935,20 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:260:6
+  --> $DIR/disallowed-positions.rs:289:6
    |
 LL |     (let true = let true = true);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:260:6
+  --> $DIR/disallowed-positions.rs:289:6
    |
 LL |     (let true = let true = true);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:264:6
+  --> $DIR/disallowed-positions.rs:307:6
    |
 LL |     &let 0 = 0
    |      ^^^^^^^^^
@@ -824,7 +956,7 @@ LL |     &let 0 = 0
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:275:17
+  --> $DIR/disallowed-positions.rs:319:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -832,7 +964,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:279:17
+  --> $DIR/disallowed-positions.rs:323:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -840,7 +972,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:283:17
+  --> $DIR/disallowed-positions.rs:327:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -848,7 +980,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:293:17
+  --> $DIR/disallowed-positions.rs:337:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -856,124 +988,124 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:302:9
+  --> $DIR/disallowed-positions.rs:346:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:302:9
+  --> $DIR/disallowed-positions.rs:346:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:306:9
+  --> $DIR/disallowed-positions.rs:350:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:306:9
+  --> $DIR/disallowed-positions.rs:350:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:309:9
+  --> $DIR/disallowed-positions.rs:353:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:309:9
+  --> $DIR/disallowed-positions.rs:353:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:309:32
+  --> $DIR/disallowed-positions.rs:353:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:309:32
+  --> $DIR/disallowed-positions.rs:353:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:316:9
+  --> $DIR/disallowed-positions.rs:360:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:316:9
+  --> $DIR/disallowed-positions.rs:360:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:316:31
+  --> $DIR/disallowed-positions.rs:360:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:316:31
+  --> $DIR/disallowed-positions.rs:360:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:320:9
+  --> $DIR/disallowed-positions.rs:364:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:320:9
+  --> $DIR/disallowed-positions.rs:364:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:320:31
+  --> $DIR/disallowed-positions.rs:364:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:320:31
+  --> $DIR/disallowed-positions.rs:364:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:324:9
+  --> $DIR/disallowed-positions.rs:368:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:324:9
+  --> $DIR/disallowed-positions.rs:368:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:90:8
+  --> $DIR/disallowed-positions.rs:92:8
    |
 LL |     if &let 0 = 0 {}
    |        ^^^^^^^^^^ expected `bool`, found `&bool`
@@ -985,19 +1117,19 @@ LL +     if let 0 = 0 {}
    |
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:94:8
+  --> $DIR/disallowed-positions.rs:96:8
    |
 LL |     if *let 0 = 0 {}
    |        ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:96:8
+  --> $DIR/disallowed-positions.rs:98:8
    |
 LL |     if -let 0 = 0 {}
    |        ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:104:8
+  --> $DIR/disallowed-positions.rs:106:8
    |
 LL |     if (let 0 = 0)? {}
    |        ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -1005,7 +1137,7 @@ LL |     if (let 0 = 0)? {}
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:104:19
+  --> $DIR/disallowed-positions.rs:106:19
    |
 LL | / fn nested_within_if_expr() {
 LL | |     if &let 0 = 0 {}
@@ -1015,14 +1147,14 @@ LL | |
 LL | |     if (let 0 = 0)? {}
    | |                   ^ cannot use the `?` operator in a function that returns `()`
 ...  |
-LL | |     if let true = let true = true {}
+LL | |
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:114:8
+  --> $DIR/disallowed-positions.rs:116:8
    |
 LL |     if x = let 0 = 0 {}
    |        ^^^^^^^^^^^^^ expected `bool`, found `()`
@@ -1033,7 +1165,7 @@ LL |     if x == let 0 = 0 {}
    |          ~~
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:117:8
+  --> $DIR/disallowed-positions.rs:119:8
    |
 LL |     if true..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1042,7 +1174,7 @@ LL |     if true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:119:8
+  --> $DIR/disallowed-positions.rs:121:8
    |
 LL |     if ..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
@@ -1051,7 +1183,7 @@ LL |     if ..(let 0 = 0) {}
             found struct `RangeTo<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:121:8
+  --> $DIR/disallowed-positions.rs:123:8
    |
 LL |     if (let 0 = 0).. {}
    |        ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
@@ -1060,7 +1192,7 @@ LL |     if (let 0 = 0).. {}
             found struct `RangeFrom<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:125:12
+  --> $DIR/disallowed-positions.rs:127:12
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1071,7 +1203,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:125:8
+  --> $DIR/disallowed-positions.rs:127:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1080,7 +1212,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:129:12
+  --> $DIR/disallowed-positions.rs:131:12
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1091,7 +1223,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:129:8
+  --> $DIR/disallowed-positions.rs:131:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1100,7 +1232,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:136:12
+  --> $DIR/disallowed-positions.rs:138:12
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -1111,20 +1243,20 @@ LL |     if let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:136:41
+  --> $DIR/disallowed-positions.rs:138:41
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |                                         ^^^^^^^ expected `bool`, found closure
    |
    = note: expected type `bool`
-           found closure `[closure@$DIR/disallowed-positions.rs:136:41: 136:48]`
+           found closure `[closure@$DIR/disallowed-positions.rs:138:41: 138:48]`
 help: use parentheses to call this closure
    |
 LL |     if let Range { start: F, end } = F..(|| true)() {}
    |                                         +       +++
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:136:8
+  --> $DIR/disallowed-positions.rs:138:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1133,7 +1265,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:144:12
+  --> $DIR/disallowed-positions.rs:146:12
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -1144,7 +1276,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:144:44
+  --> $DIR/disallowed-positions.rs:146:44
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |                                            ^^^^^^^ expected `bool`, found `&&bool`
@@ -1156,7 +1288,7 @@ LL +     if let Range { start: true, end } = t..false {}
    |
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:144:8
+  --> $DIR/disallowed-positions.rs:146:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1165,7 +1297,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<bool>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:100:20
+  --> $DIR/disallowed-positions.rs:102:20
    |
 LL |         if let 0 = 0? {}
    |                    ^^ the `?` operator cannot be applied to type `{integer}`
@@ -1173,7 +1305,7 @@ LL |         if let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:154:11
+  --> $DIR/disallowed-positions.rs:157:11
    |
 LL |     while &let 0 = 0 {}
    |           ^^^^^^^^^^ expected `bool`, found `&bool`
@@ -1185,19 +1317,19 @@ LL +     while let 0 = 0 {}
    |
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:158:11
+  --> $DIR/disallowed-positions.rs:161:11
    |
 LL |     while *let 0 = 0 {}
    |           ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:160:11
+  --> $DIR/disallowed-positions.rs:163:11
    |
 LL |     while -let 0 = 0 {}
    |           ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:168:11
+  --> $DIR/disallowed-positions.rs:171:11
    |
 LL |     while (let 0 = 0)? {}
    |           ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -1205,7 +1337,7 @@ LL |     while (let 0 = 0)? {}
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:168:22
+  --> $DIR/disallowed-positions.rs:171:22
    |
 LL | / fn nested_within_while_expr() {
 LL | |     while &let 0 = 0 {}
@@ -1215,14 +1347,14 @@ LL | |
 LL | |     while (let 0 = 0)? {}
    | |                      ^ cannot use the `?` operator in a function that returns `()`
 ...  |
-LL | |     while let true = let true = true {}
+LL | |
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:178:11
+  --> $DIR/disallowed-positions.rs:181:11
    |
 LL |     while x = let 0 = 0 {}
    |           ^^^^^^^^^^^^^ expected `bool`, found `()`
@@ -1233,7 +1365,7 @@ LL |     while x == let 0 = 0 {}
    |             ~~
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:181:11
+  --> $DIR/disallowed-positions.rs:184:11
    |
 LL |     while true..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1242,7 +1374,7 @@ LL |     while true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:183:11
+  --> $DIR/disallowed-positions.rs:186:11
    |
 LL |     while ..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
@@ -1251,7 +1383,7 @@ LL |     while ..(let 0 = 0) {}
             found struct `RangeTo<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:185:11
+  --> $DIR/disallowed-positions.rs:188:11
    |
 LL |     while (let 0 = 0).. {}
    |           ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
@@ -1260,7 +1392,7 @@ LL |     while (let 0 = 0).. {}
             found struct `RangeFrom<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:189:15
+  --> $DIR/disallowed-positions.rs:192:15
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1271,7 +1403,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:189:11
+  --> $DIR/disallowed-positions.rs:192:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1280,7 +1412,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:193:15
+  --> $DIR/disallowed-positions.rs:196:15
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1291,7 +1423,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:193:11
+  --> $DIR/disallowed-positions.rs:196:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1300,7 +1432,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:200:15
+  --> $DIR/disallowed-positions.rs:203:15
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -1311,20 +1443,20 @@ LL |     while let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:200:44
+  --> $DIR/disallowed-positions.rs:203:44
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |                                            ^^^^^^^ expected `bool`, found closure
    |
    = note: expected type `bool`
-           found closure `[closure@$DIR/disallowed-positions.rs:200:44: 200:51]`
+           found closure `[closure@$DIR/disallowed-positions.rs:203:44: 203:51]`
 help: use parentheses to call this closure
    |
 LL |     while let Range { start: F, end } = F..(|| true)() {}
    |                                            +       +++
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:200:11
+  --> $DIR/disallowed-positions.rs:203:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1333,7 +1465,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:208:15
+  --> $DIR/disallowed-positions.rs:211:15
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -1344,7 +1476,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:208:47
+  --> $DIR/disallowed-positions.rs:211:47
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |                                               ^^^^^^^ expected `bool`, found `&&bool`
@@ -1356,7 +1488,7 @@ LL +     while let Range { start: true, end } = t..false {}
    |
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:208:11
+  --> $DIR/disallowed-positions.rs:211:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1365,7 +1497,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<bool>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:164:23
+  --> $DIR/disallowed-positions.rs:167:23
    |
 LL |         while let 0 = 0? {}
    |                       ^^ the `?` operator cannot be applied to type `{integer}`
@@ -1373,19 +1505,19 @@ LL |         while let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:231:5
+  --> $DIR/disallowed-positions.rs:239:5
    |
 LL |     *let 0 = 0;
    |     ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:233:5
+  --> $DIR/disallowed-positions.rs:243:5
    |
 LL |     -let 0 = 0;
    |     ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:241:5
+  --> $DIR/disallowed-positions.rs:253:5
    |
 LL |     (let 0 = 0)?;
    |     ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -1393,12 +1525,12 @@ LL |     (let 0 = 0)?;
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:241:16
+  --> $DIR/disallowed-positions.rs:253:16
    |
 LL | / fn outside_if_and_while_expr() {
 LL | |     &let 0 = 0;
 LL | |
-LL | |     !let 0 = 0;
+LL | |
 ...  |
 LL | |     (let 0 = 0)?;
    | |                ^ cannot use the `?` operator in a function that returns `()`
@@ -1410,7 +1542,7 @@ LL | | }
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:256:10
+  --> $DIR/disallowed-positions.rs:284:10
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1421,7 +1553,7 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:264:5
+  --> $DIR/disallowed-positions.rs:307:5
    |
 LL | fn outside_if_and_while_expr() {
    |                                - help: try adding a return type: `-> &bool`
@@ -1430,14 +1562,14 @@ LL |     &let 0 = 0
    |     ^^^^^^^^^^ expected `()`, found `&bool`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:237:17
+  --> $DIR/disallowed-positions.rs:249:17
    |
 LL |         let 0 = 0?;
    |                 ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
 
-error: aborting due to 134 previous errors
+error: aborting due to 156 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0600, E0614.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
index e66caa19ec96b..12befc637c787 100644
--- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
@@ -17,6 +17,7 @@ fn main() {
     //~| ERROR `let` expressions are not supported here
     //~| ERROR mismatched types
     //~| ERROR mismatched types
+    //~| ERROR expected expression, found `let` statement
         return;
     };
 
diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
index eea8ed0c9633e..498a112fa9bb3 100644
--- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
@@ -9,6 +9,12 @@ help: wrap the expression in parentheses
 LL |     let Some(n) = (opt && n == 1) else {
    |                   +             +
 
+error: expected expression, found `let` statement
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:26
+   |
+LL |     let Some(n) = opt && let another = n else {
+   |                          ^^^
+
 error: a `&&` expression cannot be directly assigned in `let...else`
   --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19
    |
@@ -21,43 +27,43 @@ LL |     let Some(n) = (opt && let another = n) else {
    |                   +                      +
 
 error: this `if` expression is missing a block after the condition
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:5
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:24:5
    |
 LL |     if let Some(n) = opt else {
    |     ^^
    |
 help: add a block here
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:25
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:24:25
    |
 LL |     if let Some(n) = opt else {
    |                         ^
 
 error: this `if` expression is missing a block after the condition
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:5
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:28:5
    |
 LL |     if let Some(n) = opt && n == 1 else {
    |     ^^
    |
 help: add a block here
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:35
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:28:35
    |
 LL |     if let Some(n) = opt && n == 1 else {
    |                                   ^
 
 error: this `if` expression is missing a block after the condition
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:5
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:32:5
    |
 LL |     if let Some(n) = opt && let another = n else {
    |     ^^
    |
 help: add a block here
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:44
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:32:44
    |
 LL |     if let Some(n) = opt && let another = n else {
    |                                            ^
 
 error: expected `{`, found keyword `else`
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:37:33
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:38:33
    |
 LL |         while let Some(n) = opt else {
    |         ----- ----------------- ^^^^ expected `{`
@@ -66,7 +72,7 @@ LL |         while let Some(n) = opt else {
    |         while parsing the body of this `while` expression
 
 error: expected `{`, found keyword `else`
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:43:43
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:44:43
    |
 LL |         while let Some(n) = opt && n == 1 else {
    |         ----- --------------------------- ^^^^ expected `{`
@@ -75,7 +81,7 @@ LL |         while let Some(n) = opt && n == 1 else {
    |         while parsing the body of this `while` expression
 
 error: expected `{`, found keyword `else`
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:49:52
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:50:52
    |
 LL |         while let Some(n) = opt && let another = n else {
    |         ----- ------------------------------------ ^^^^ expected `{`
@@ -131,6 +137,6 @@ LL |     let Some(n) = opt && let another = n else {
    = note: expected type `bool`
               found enum `Option<_>`
 
-error: aborting due to 13 previous errors
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
index ac60bc7e57fd4..8771821130848 100644
--- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
@@ -39,6 +39,7 @@ fn _macros() {
 
     noop_expr!((let 0 = 1));
     //~^ ERROR `let` expressions in this position are unstable [E0658]
+    //~| ERROR expected expression, found `let` statement
 
     macro_rules! use_expr {
         ($e:expr) => {
@@ -48,9 +49,9 @@ fn _macros() {
     }
     #[cfg(FALSE)] (let 0 = 1);
     //~^ ERROR `let` expressions in this position are unstable [E0658]
+    //~| ERROR expected expression, found `let` statement
     use_expr!(let 0 = 1);
     //~^ ERROR no rules expected the token `let`
-    // ^--- FIXME(53667): Consider whether `Let` can be added to `ident_can_begin_expr`.
 }
 
 fn main() {}
diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
index 1eabee47c64ac..bcea8bbaa730b 100644
--- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
@@ -1,5 +1,17 @@
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:50:20
+   |
+LL |     #[cfg(FALSE)] (let 0 = 1);
+   |                    ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:40:17
+   |
+LL |     noop_expr!((let 0 = 1));
+   |                 ^^^
+
 error: no rules expected the token `let`
-  --> $DIR/feature-gate.rs:51:15
+  --> $DIR/feature-gate.rs:53:15
    |
 LL |     macro_rules! use_expr {
    |     --------------------- when calling this macro
@@ -62,7 +74,7 @@ LL |     while let Range { start: _, end: _ } = (true..true) && false {}
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:49:20
+  --> $DIR/feature-gate.rs:50:20
    |
 LL |     #[cfg(FALSE)] (let 0 = 1);
    |                    ^^^^^^^^^
@@ -79,6 +91,6 @@ LL |     noop_expr!((let 0 = 1));
    = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
-error: aborting due to 9 previous errors
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs
new file mode 100644
index 0000000000000..6cc53a1935b95
--- /dev/null
+++ b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs
@@ -0,0 +1,17 @@
+// check-pass
+// known-bug
+
+#![feature(let_chains)]
+
+fn main() {
+    let _opt = Some(1i32);
+
+    #[cfg(FALSE)]
+    {
+        if let Some(elem) = _opt && {
+            [1, 2, 3][let _ = ()];
+            true
+        } {
+        }
+    }
+}