about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/ast.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/format.rs18
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs181
-rw-r--r--compiler/rustc_parse/messages.ftl72
-rw-r--r--compiler/rustc_parse/src/errors.rs224
-rw-r--r--compiler/rustc_parse/src/lib.rs17
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs12
-rw-r--r--compiler/rustc_parse/src/parser/item.rs119
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs15
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs21
-rw-r--r--compiler/rustc_parse/src/parser/path.rs21
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs30
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs27
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--library/core/src/fmt/mod.rs246
-rw-r--r--library/core/src/fmt/rt.rs154
-rw-r--r--library/std/src/sys/windows/fs.rs41
-rw-r--r--src/etc/lldb_providers.py2
-rw-r--r--src/librustdoc/clean/mod.rs10
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.stderr54
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs6
-rw-r--r--tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff24
-rw-r--r--tests/rustdoc-ui/issue-110900.rs28
-rw-r--r--tests/ui/attributes/invalid_macro_export_argument.deny.stderr20
-rw-r--r--tests/ui/attributes/invalid_macro_export_argument.rs13
-rw-r--r--tests/ui/attributes/invalid_macro_export_argument.stderr16
-rw-r--r--tests/ui/fmt/ifmt-bad-arg.stderr4
-rw-r--r--tests/ui/fmt/ifmt-unimpl.stderr6
-rw-r--r--tests/ui/fmt/send-sync.stderr28
-rw-r--r--tests/ui/macros/missing-bang-in-decl.stderr14
-rw-r--r--tests/ui/parser/item-kw-case-mismatch.fixed28
-rw-r--r--tests/ui/parser/item-kw-case-mismatch.rs28
-rw-r--r--tests/ui/parser/item-kw-case-mismatch.stderr28
-rw-r--r--tests/ui/parser/recover-unticked-labels.stderr8
-rw-r--r--tests/ui/parser/use-colon-as-mod-sep.stderr6
37 files changed, 898 insertions, 638 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 1e4d3ba47f4..3ed342ce48b 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2976,7 +2976,7 @@ pub enum ItemKind {
 }
 
 impl ItemKind {
-    pub fn article(&self) -> &str {
+    pub fn article(&self) -> &'static str {
         use ItemKind::*;
         match self {
             Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
@@ -2985,7 +2985,7 @@ impl ItemKind {
         }
     }
 
-    pub fn descr(&self) -> &str {
+    pub fn descr(&self) -> &'static str {
         match self {
             ItemKind::ExternCrate(..) => "extern crate",
             ItemKind::Use(..) => "`use` import",
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
index ccf481cb9b3..c081162ea14 100644
--- a/compiler/rustc_ast_lowering/src/format.rs
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -186,7 +186,7 @@ enum ArgumentType {
 /// Generates:
 ///
 /// ```text
-///     <core::fmt::ArgumentV1>::new_…(arg)
+///     <core::fmt::Argument>::new_…(arg)
 /// ```
 fn make_argument<'hir>(
     ctx: &mut LoweringContext<'_, 'hir>,
@@ -327,7 +327,7 @@ fn make_format_spec<'hir>(
             None => sym::Unknown,
         },
     );
-    // This needs to match `FlagV1` in library/core/src/fmt/mod.rs.
+    // This needs to match `Flag` in library/core/src/fmt/rt.rs.
     let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
         | ((sign == Some(FormatSign::Minus)) as u32) << 1
         | (alternate as u32) << 2
@@ -438,7 +438,7 @@ fn expand_format_args<'hir>(
     // If the args array contains exactly all the original arguments once,
     // in order, we can use a simple array instead of a `match` construction.
     // However, if there's a yield point in any argument except the first one,
-    // we don't do this, because an ArgumentV1 cannot be kept across yield points.
+    // we don't do this, because an Argument cannot be kept across yield points.
     //
     // This is an optimization, speeding up compilation about 1-2% in some cases.
     // See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609
@@ -449,9 +449,9 @@ fn expand_format_args<'hir>(
     let args = if use_simple_array {
         // Generate:
         //     &[
-        //         <core::fmt::ArgumentV1>::new_display(&arg0),
-        //         <core::fmt::ArgumentV1>::new_lower_hex(&arg1),
-        //         <core::fmt::ArgumentV1>::new_debug(&arg2),
+        //         <core::fmt::Argument>::new_display(&arg0),
+        //         <core::fmt::Argument>::new_lower_hex(&arg1),
+        //         <core::fmt::Argument>::new_debug(&arg2),
         //         …
         //     ]
         let elements: Vec<_> = arguments
@@ -477,9 +477,9 @@ fn expand_format_args<'hir>(
         // Generate:
         //     &match (&arg0, &arg1, &…) {
         //         args => [
-        //             <core::fmt::ArgumentV1>::new_display(args.0),
-        //             <core::fmt::ArgumentV1>::new_lower_hex(args.1),
-        //             <core::fmt::ArgumentV1>::new_debug(args.0),
+        //             <core::fmt::Argument>::new_display(args.0),
+        //             <core::fmt::Argument>::new_lower_hex(args.1),
+        //             <core::fmt::Argument>::new_debug(args.0),
         //             …
         //         ]
         //     }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 6c11edb742c..4fb66854571 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -296,7 +296,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                 diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span)));
                 err
             }
-            _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => ccx
+            _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentMethods) => ccx
                 .tcx
                 .sess
                 .create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }),
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index b223b8c137a..a3d7bd3ef59 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3273,110 +3273,115 @@ declare_lint_pass! {
     /// Does nothing as a lint pass, but registers some `Lint`s
     /// that are used by other parts of the compiler.
     HardwiredLints => [
-        FORBIDDEN_LINT_GROUPS,
-        ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+        // tidy-alphabetical-start
+        ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
+        AMBIGUOUS_ASSOCIATED_ITEMS,
+        AMBIGUOUS_GLOB_REEXPORTS,
         ARITHMETIC_OVERFLOW,
-        UNCONDITIONAL_PANIC,
-        UNUSED_IMPORTS,
-        UNUSED_EXTERN_CRATES,
-        UNUSED_CRATE_DEPENDENCIES,
-        UNUSED_QUALIFICATIONS,
-        UNKNOWN_LINTS,
-        UNFULFILLED_LINT_EXPECTATIONS,
-        UNUSED_VARIABLES,
-        UNUSED_ASSIGNMENTS,
-        DEAD_CODE,
-        UNREACHABLE_CODE,
-        UNREACHABLE_PATTERNS,
-        OVERLAPPING_RANGE_ENDPOINTS,
+        ASM_SUB_REGISTER,
+        BAD_ASM_STYLE,
+        BARE_TRAIT_OBJECTS,
         BINDINGS_WITH_VARIANT_NAME,
-        UNUSED_MACROS,
-        UNUSED_MACRO_RULES,
-        WARNINGS,
-        UNUSED_FEATURES,
-        STABLE_FEATURES,
-        UNKNOWN_CRATE_TYPES,
-        TRIVIAL_CASTS,
-        TRIVIAL_NUMERIC_CASTS,
-        PRIVATE_IN_PUBLIC,
-        EXPORTED_PRIVATE_DEPENDENCIES,
-        PUB_USE_OF_PRIVATE_EXTERN_CRATE,
-        INVALID_TYPE_PARAM_DEFAULT,
-        RENAMED_AND_REMOVED_LINTS,
-        CONST_ITEM_MUTATION,
-        PATTERNS_IN_FNS_WITHOUT_BODY,
-        MISSING_FRAGMENT_SPECIFIER,
-        LATE_BOUND_LIFETIME_ARGUMENTS,
-        ORDER_DEPENDENT_TRAIT_OBJECTS,
+        BREAK_WITH_LABEL_AND_LOOP,
+        BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
+        CENUM_IMPL_DROP_CAST,
         COHERENCE_LEAK_CHECK,
+        CONFLICTING_REPR_HINTS,
+        CONST_EVALUATABLE_UNCHECKED,
+        CONST_ITEM_MUTATION,
+        DEAD_CODE,
         DEPRECATED,
-        UNUSED_UNSAFE,
-        UNUSED_MUT,
-        UNCONDITIONAL_RECURSION,
-        SINGLE_USE_LIFETIMES,
-        UNUSED_LIFETIMES,
-        UNUSED_LABELS,
-        TYVAR_BEHIND_RAW_POINTER,
+        DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
+        DEPRECATED_IN_FUTURE,
+        DEPRECATED_WHERE_CLAUSE_LOCATION,
+        DUPLICATE_MACRO_ATTRIBUTES,
         ELIDED_LIFETIMES_IN_PATHS,
-        BARE_TRAIT_OBJECTS,
-        ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
-        UNSTABLE_NAME_COLLISIONS,
-        IRREFUTABLE_LET_PATTERNS,
-        WHERE_CLAUSES_OBJECT_SAFETY,
-        PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
-        MACRO_USE_EXTERN_CRATE,
-        MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
+        EXPORTED_PRIVATE_DEPENDENCIES,
+        FFI_UNWIND_CALLS,
+        FORBIDDEN_LINT_GROUPS,
+        FUNCTION_ITEM_REFERENCES,
+        FUZZY_PROVENANCE_CASTS,
         ILL_FORMED_ATTRIBUTE_INPUT,
-        CONFLICTING_REPR_HINTS,
-        META_VARIABLE_MISUSE,
-        DEPRECATED_IN_FUTURE,
-        AMBIGUOUS_ASSOCIATED_ITEMS,
-        INDIRECT_STRUCTURAL_MATCH,
-        POINTER_STRUCTURAL_MATCH,
-        NONTRIVIAL_STRUCTURAL_MATCH,
-        SOFT_UNSTABLE,
-        UNSTABLE_SYNTAX_PRE_EXPANSION,
-        INLINE_NO_SANITIZE,
-        BAD_ASM_STYLE,
-        ASM_SUB_REGISTER,
-        UNSAFE_OP_IN_UNSAFE_FN,
+        ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+        IMPLIED_BOUNDS_ENTAILMENT,
         INCOMPLETE_INCLUDE,
-        CENUM_IMPL_DROP_CAST,
-        FUZZY_PROVENANCE_CASTS,
-        LOSSY_PROVENANCE_CASTS,
-        CONST_EVALUATABLE_UNCHECKED,
+        INDIRECT_STRUCTURAL_MATCH,
         INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
-        MUST_NOT_SUSPEND,
-        UNINHABITED_STATIC,
-        FUNCTION_ITEM_REFERENCES,
-        USELESS_DEPRECATED,
-        MISSING_ABI,
+        INLINE_NO_SANITIZE,
+        INVALID_ALIGNMENT,
         INVALID_DOC_ATTRIBUTES,
-        SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
-        RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
+        INVALID_MACRO_EXPORT_ARGUMENTS,
+        INVALID_TYPE_PARAM_DEFAULT,
+        IRREFUTABLE_LET_PATTERNS,
+        LARGE_ASSIGNMENTS,
+        LATE_BOUND_LIFETIME_ARGUMENTS,
         LEGACY_DERIVE_HELPERS,
+        LOSSY_PROVENANCE_CASTS,
+        MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
+        MACRO_USE_EXTERN_CRATE,
+        META_VARIABLE_MISUSE,
+        MISSING_ABI,
+        MISSING_FRAGMENT_SPECIFIER,
+        MUST_NOT_SUSPEND,
+        NAMED_ARGUMENTS_USED_POSITIONALLY,
+        NON_EXHAUSTIVE_OMITTED_PATTERNS,
+        NONTRIVIAL_STRUCTURAL_MATCH,
+        ORDER_DEPENDENT_TRAIT_OBJECTS,
+        OVERLAPPING_RANGE_ENDPOINTS,
+        PATTERNS_IN_FNS_WITHOUT_BODY,
+        POINTER_STRUCTURAL_MATCH,
+        PRIVATE_IN_PUBLIC,
         PROC_MACRO_BACK_COMPAT,
+        PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
+        PUB_USE_OF_PRIVATE_EXTERN_CRATE,
+        RENAMED_AND_REMOVED_LINTS,
+        REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
+        RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
         RUST_2021_INCOMPATIBLE_OR_PATTERNS,
-        LARGE_ASSIGNMENTS,
-        RUST_2021_PRELUDE_COLLISIONS,
         RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
+        RUST_2021_PRELUDE_COLLISIONS,
+        SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
+        SINGLE_USE_LIFETIMES,
+        SOFT_UNSTABLE,
+        STABLE_FEATURES,
+        SUSPICIOUS_AUTO_TRAIT_IMPLS,
+        TEST_UNSTABLE_LINT,
+        TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
+        TRIVIAL_CASTS,
+        TRIVIAL_NUMERIC_CASTS,
+        TYVAR_BEHIND_RAW_POINTER,
+        UNCONDITIONAL_PANIC,
+        UNCONDITIONAL_RECURSION,
+        UNDEFINED_NAKED_FUNCTION_ABI,
+        UNFULFILLED_LINT_EXPECTATIONS,
+        UNINHABITED_STATIC,
+        UNKNOWN_CRATE_TYPES,
+        UNKNOWN_LINTS,
+        UNREACHABLE_CODE,
+        UNREACHABLE_PATTERNS,
+        UNSAFE_OP_IN_UNSAFE_FN,
+        UNSTABLE_NAME_COLLISIONS,
+        UNSTABLE_SYNTAX_PRE_EXPANSION,
         UNSUPPORTED_CALLING_CONVENTIONS,
-        BREAK_WITH_LABEL_AND_LOOP,
+        UNUSED_ASSIGNMENTS,
         UNUSED_ATTRIBUTES,
+        UNUSED_CRATE_DEPENDENCIES,
+        UNUSED_EXTERN_CRATES,
+        UNUSED_FEATURES,
+        UNUSED_IMPORTS,
+        UNUSED_LABELS,
+        UNUSED_LIFETIMES,
+        UNUSED_MACRO_RULES,
+        UNUSED_MACROS,
+        UNUSED_MUT,
+        UNUSED_QUALIFICATIONS,
         UNUSED_TUPLE_STRUCT_FIELDS,
-        NON_EXHAUSTIVE_OMITTED_PATTERNS,
-        TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
-        DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
-        DUPLICATE_MACRO_ATTRIBUTES,
-        SUSPICIOUS_AUTO_TRAIT_IMPLS,
-        DEPRECATED_WHERE_CLAUSE_LOCATION,
-        TEST_UNSTABLE_LINT,
-        FFI_UNWIND_CALLS,
-        REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
-        NAMED_ARGUMENTS_USED_POSITIONALLY,
-        IMPLIED_BOUNDS_ENTAILMENT,
-        BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
-        AMBIGUOUS_GLOB_REEXPORTS,
+        UNUSED_UNSAFE,
+        UNUSED_VARIABLES,
+        USELESS_DEPRECATED,
+        WARNINGS,
+        WHERE_CLAUSES_OBJECT_SAFETY,
+        // tidy-alphabetical-end
     ]
 }
 
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index d45fa90a11b..9c4fac84fc2 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -772,3 +772,75 @@ parse_const_bounds_missing_tilde = const bounds must start with `~`
     .suggestion = add `~`
 
 parse_underscore_literal_suffix = underscore literal suffix is not allowed
+
+parse_expect_label_found_ident = expected a label, found an identifier
+    .suggestion = labels start with a tick
+
+parse_inappropriate_default = {$article} {$descr} cannot be `default`
+    .label = `default` because of this
+    .note = only associated `fn`, `const`, and `type` items can be `default`
+
+parse_recover_import_as_use = expected item, found {$token_name}
+    .suggestion = items are imported using the `use` keyword
+
+parse_single_colon_import_path = expected `::`, found `:`
+    .suggestion = use double colon
+    .note = import paths are delimited using `::`
+
+parse_bad_item_kind = {$descr} is not supported in {$ctx}
+    .help = consider moving the {$descr} out to a nearby module scope
+
+parse_single_colon_struct_type = found single colon in a struct field type path
+    .suggestion = write a path separator here
+
+parse_equals_struct_default = default values on `struct` fields aren't supported
+    .suggestion = remove this unsupported default value
+
+parse_macro_rules_missing_bang = expected `!` after `macro_rules`
+    .suggestion = add a `!`
+
+parse_macro_name_remove_bang = macro names aren't followed by a `!`
+    .suggestion = remove the `!`
+
+parse_macro_rules_visibility = can't qualify macro_rules invocation with `{$vis}`
+    .suggestion = try exporting the macro
+
+parse_macro_invocation_visibility = can't qualify macro invocation with `pub`
+    .suggestion = remove the visibility
+    .help = try adjusting the macro to put `{$vis}` inside the invocation
+
+parse_nested_adt = `{$kw_str}` definition cannot be nested inside `{$keyword}`
+    .suggestion = consider creating a new `{$kw_str}` definition instead of nesting
+
+parse_function_body_equals_expr = function body cannot be `= expression;`
+    .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
+
+parse_box_not_pat = expected pattern, found {$descr}
+    .note = `box` is a reserved keyword
+    .suggestion = escape `box` to use it as an identifier
+
+parse_unmatched_angle = unmatched angle {$plural ->
+    [true] brackets
+    *[false] bracket
+    }
+    .suggestion = remove extra angle {$plural ->
+    [true] brackets
+    *[false] bracket
+    }
+
+parse_missing_plus_in_bounds = expected `+` between lifetime and {$sym}
+    .suggestion = add `+`
+
+parse_incorrect_braces_trait_bounds = incorrect braces around trait bounds
+    .suggestion = remove the parentheses
+
+parse_kw_bad_case = keyword `{$kw}` is written in the wrong case
+    .suggestion = write it in the correct case
+
+parse_meta_bad_delim = wrong meta list delimiters
+parse_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
+parse_meta_bad_delim_suggestion = the delimiters should be `(` and `)`
+
+parse_malformed_cfg_attr = malformed `cfg_attr` attribute input
+    .suggestion = missing condition and attribute
+    .note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index b0e1189851a..f286707a9c0 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2421,3 +2421,227 @@ pub(crate) struct UnderscoreLiteralSuffix {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_expect_label_found_ident)]
+pub(crate) struct ExpectedLabelFoundIdent {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = "'", applicability = "machine-applicable", style = "short")]
+    pub start: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_inappropriate_default)]
+#[note]
+pub(crate) struct InappropriateDefault {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub article: &'static str,
+    pub descr: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_recover_import_as_use)]
+pub(crate) struct RecoverImportAsUse {
+    #[primary_span]
+    #[suggestion(code = "use", applicability = "machine-applicable", style = "short")]
+    pub span: Span,
+    pub token_name: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_single_colon_import_path)]
+#[note]
+pub(crate) struct SingleColonImportPath {
+    #[primary_span]
+    #[suggestion(code = "::", applicability = "machine-applicable", style = "short")]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_bad_item_kind)]
+#[help]
+pub(crate) struct BadItemKind {
+    #[primary_span]
+    pub span: Span,
+    pub descr: &'static str,
+    pub ctx: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_single_colon_struct_type)]
+pub(crate) struct SingleColonStructType {
+    #[primary_span]
+    #[suggestion(code = "::", applicability = "maybe-incorrect", style = "verbose")]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_equals_struct_default)]
+pub(crate) struct EqualsStructDefault {
+    #[primary_span]
+    #[suggestion(code = "", applicability = "machine-applicable")]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_macro_rules_missing_bang)]
+pub(crate) struct MacroRulesMissingBang {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = "!", applicability = "machine-applicable", style = "verbose")]
+    pub hi: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_macro_name_remove_bang)]
+pub(crate) struct MacroNameRemoveBang {
+    #[primary_span]
+    #[suggestion(code = "", applicability = "machine-applicable")]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_macro_rules_visibility)]
+pub(crate) struct MacroRulesVisibility<'a> {
+    #[primary_span]
+    #[suggestion(code = "#[macro_export]", applicability = "maybe-incorrect")]
+    pub span: Span,
+    pub vis: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_macro_invocation_visibility)]
+#[help]
+pub(crate) struct MacroInvocationVisibility<'a> {
+    #[primary_span]
+    #[suggestion(code = "", applicability = "machine-applicable")]
+    pub span: Span,
+    pub vis: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_nested_adt)]
+pub(crate) struct NestedAdt<'a> {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = "", applicability = "maybe-incorrect")]
+    pub item: Span,
+    pub keyword: &'a str,
+    pub kw_str: Cow<'a, str>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_function_body_equals_expr)]
+pub(crate) struct FunctionBodyEqualsExpr {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sugg: FunctionBodyEqualsExprSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
+pub(crate) struct FunctionBodyEqualsExprSugg {
+    #[suggestion_part(code = "{{")]
+    pub eq: Span,
+    #[suggestion_part(code = " }}")]
+    pub semi: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_box_not_pat)]
+pub(crate) struct BoxNotPat {
+    #[primary_span]
+    pub span: Span,
+    #[note]
+    pub kw: Span,
+    #[suggestion(code = "r#", applicability = "maybe-incorrect", style = "verbose")]
+    pub lo: Span,
+    pub descr: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unmatched_angle)]
+pub(crate) struct UnmatchedAngle {
+    #[primary_span]
+    #[suggestion(code = "", applicability = "machine-applicable")]
+    pub span: Span,
+    pub plural: bool,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_missing_plus_in_bounds)]
+pub(crate) struct MissingPlusBounds {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " +", applicability = "maybe-incorrect", style = "verbose")]
+    pub hi: Span,
+    pub sym: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_incorrect_braces_trait_bounds)]
+pub(crate) struct IncorrectBracesTraitBounds {
+    #[primary_span]
+    pub span: Vec<Span>,
+    #[subdiagnostic]
+    pub sugg: IncorrectBracesTraitBoundsSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
+pub(crate) struct IncorrectBracesTraitBoundsSugg {
+    #[suggestion_part(code = " ")]
+    pub l: Span,
+    #[suggestion_part(code = "")]
+    pub r: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_kw_bad_case)]
+pub(crate) struct KwBadCase<'a> {
+    #[primary_span]
+    #[suggestion(code = "{kw}", applicability = "machine-applicable")]
+    pub span: Span,
+    pub kw: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_meta_bad_delim)]
+pub(crate) struct MetaBadDelim {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sugg: MetaBadDelimSugg,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_cfg_attr_bad_delim)]
+pub(crate) struct CfgAttrBadDelim {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sugg: MetaBadDelimSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parse_meta_bad_delim_suggestion, applicability = "machine-applicable")]
+pub(crate) struct MetaBadDelimSugg {
+    #[suggestion_part(code = "(")]
+    pub open: Span,
+    #[suggestion_part(code = ")")]
+    pub close: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_malformed_cfg_attr)]
+#[note]
+pub(crate) struct MalformedCfgAttr {
+    #[primary_span]
+    #[suggestion(code = "{sugg}")]
+    pub span: Span,
+    pub sugg: &'static str,
+}
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 507f6e4182e..61a1cdeb540 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -18,7 +18,7 @@ use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{AttrItem, Attribute, MetaItem};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{Applicability, Diagnostic, FatalError, Level, PResult};
+use rustc_errors::{Diagnostic, FatalError, Level, PResult};
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
 use rustc_session::parse::ParseSess;
@@ -243,8 +243,7 @@ pub fn parse_cfg_attr(
         ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens })
             if !tokens.is_empty() =>
         {
-            let msg = "wrong `cfg_attr` delimiters";
-            crate::validate_attr::check_meta_bad_delim(parse_sess, dspan, delim, msg);
+            crate::validate_attr::check_cfg_attr_bad_delim(parse_sess, dspan, delim);
             match parse_in(parse_sess, tokens.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
                 Ok(r) => return Some(r),
                 Err(mut e) => {
@@ -265,15 +264,5 @@ const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
     #the-cfg_attr-attribute>";
 
 fn error_malformed_cfg_attr_missing(span: Span, parse_sess: &ParseSess) {
-    parse_sess
-        .span_diagnostic
-        .struct_span_err(span, "malformed `cfg_attr` attribute input")
-        .span_suggestion(
-            span,
-            "missing condition and attribute",
-            CFG_ATTR_GRAMMAR_HELP,
-            Applicability::HasPlaceholders,
-        )
-        .note(CFG_ATTR_NOTE_REF)
-        .emit();
+    parse_sess.emit_err(errors::MalformedCfgAttr { span, sugg: CFG_ATTR_GRAMMAR_HELP });
 }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 03c82fbd329..27de9bd7268 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -3151,14 +3151,10 @@ impl<'a> Parser<'a> {
         let label = format!("'{}", ident.name);
         let ident = Ident { name: Symbol::intern(&label), span: ident.span };
 
-        self.struct_span_err(ident.span, "expected a label, found an identifier")
-            .span_suggestion(
-                ident.span,
-                "labels start with a tick",
-                label,
-                Applicability::MachineApplicable,
-            )
-            .emit();
+        self.sess.emit_err(errors::ExpectedLabelFoundIdent {
+            span: ident.span,
+            start: ident.span.shrink_to_lo(),
+        });
 
         Label { ident }
     }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index f5fef6ad019..9e003bfc097 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -181,11 +181,11 @@ impl<'a> Parser<'a> {
     /// Error in-case `default` was parsed in an in-appropriate context.
     fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
         if let Defaultness::Default(span) = def {
-            let msg = format!("{} {} cannot be `default`", kind.article(), kind.descr());
-            self.struct_span_err(span, &msg)
-                .span_label(span, "`default` because of this")
-                .note("only associated `fn`, `const`, and `type` items can be `default`")
-                .emit();
+            self.sess.emit_err(errors::InappropriateDefault {
+                span,
+                article: kind.article(),
+                descr: kind.descr(),
+            });
         }
     }
 
@@ -310,14 +310,7 @@ impl<'a> Parser<'a> {
         self.bump();
         match self.parse_use_item() {
             Ok(u) => {
-                self.struct_span_err(span, format!("expected item, found {token_name}"))
-                    .span_suggestion_short(
-                        span,
-                        "items are imported using the `use` keyword",
-                        "use",
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
+                self.sess.emit_err(errors::RecoverImportAsUse { span, token_name });
                 Ok(Some(u))
             }
             Err(e) => {
@@ -963,15 +956,8 @@ impl<'a> Parser<'a> {
             } else {
                 // Recover from using a colon as path separator.
                 while self.eat_noexpect(&token::Colon) {
-                    self.struct_span_err(self.prev_token.span, "expected `::`, found `:`")
-                        .span_suggestion_short(
-                            self.prev_token.span,
-                            "use double colon",
-                            "::",
-                            Applicability::MachineApplicable,
-                        )
-                        .note_once("import paths are delimited using `::`")
-                        .emit();
+                    self.sess
+                        .emit_err(errors::SingleColonImportPath { span: self.prev_token.span });
 
                     // We parse the rest of the path and append it to the original prefix.
                     self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
@@ -1134,13 +1120,11 @@ impl<'a> Parser<'a> {
         ))
     }
 
-    fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option<T> {
+    fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
         // FIXME(#100717): needs variant for each `ItemKind` (instead of using `ItemKind::descr()`)
         let span = self.sess.source_map().guess_head_span(span);
         let descr = kind.descr();
-        self.struct_span_err(span, &format!("{descr} is not supported in {ctx}"))
-            .help(&format!("consider moving the {descr} out to a nearby module scope"))
-            .emit();
+        self.sess.emit_err(errors::BadItemKind { span, descr, ctx });
         None
     }
 
@@ -1713,27 +1697,13 @@ impl<'a> Parser<'a> {
         self.expect_field_ty_separator()?;
         let ty = self.parse_ty()?;
         if self.token.kind == token::Colon && self.look_ahead(1, |tok| tok.kind != token::Colon) {
-            self.struct_span_err(self.token.span, "found single colon in a struct field type path")
-                .span_suggestion_verbose(
-                    self.token.span,
-                    "write a path separator here",
-                    "::",
-                    Applicability::MaybeIncorrect,
-                )
-                .emit();
+            self.sess.emit_err(errors::SingleColonStructType { span: self.token.span });
         }
         if self.token.kind == token::Eq {
             self.bump();
             let const_expr = self.parse_expr_anon_const()?;
             let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
-            self.struct_span_err(sp, "default values on `struct` fields aren't supported")
-                .span_suggestion(
-                    sp,
-                    "remove this unsupported default value",
-                    "",
-                    Applicability::MachineApplicable,
-                )
-                .emit();
+            self.sess.emit_err(errors::EqualsStructDefault { span: sp });
         }
         Ok(FieldDef {
             span: lo.to(self.prev_token.span),
@@ -1871,14 +1841,10 @@ impl<'a> Parser<'a> {
                 return IsMacroRulesItem::Yes { has_bang: true };
             } else if self.look_ahead(1, |t| (t.is_ident())) {
                 // macro_rules foo
-                self.struct_span_err(macro_rules_span, "expected `!` after `macro_rules`")
-                    .span_suggestion(
-                        macro_rules_span,
-                        "add a `!`",
-                        "macro_rules!",
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
+                self.sess.emit_err(errors::MacroRulesMissingBang {
+                    span: macro_rules_span,
+                    hi: macro_rules_span.shrink_to_hi(),
+                });
 
                 return IsMacroRulesItem::Yes { has_bang: false };
             }
@@ -1903,9 +1869,7 @@ impl<'a> Parser<'a> {
         if self.eat(&token::Not) {
             // Handle macro_rules! foo!
             let span = self.prev_token.span;
-            self.struct_span_err(span, "macro names aren't followed by a `!`")
-                .span_suggestion(span, "remove the `!`", "", Applicability::MachineApplicable)
-                .emit();
+            self.sess.emit_err(errors::MacroNameRemoveBang { span });
         }
 
         let body = self.parse_delim_args()?;
@@ -1925,25 +1889,9 @@ impl<'a> Parser<'a> {
         let vstr = pprust::vis_to_string(vis);
         let vstr = vstr.trim_end();
         if macro_rules {
-            let msg = format!("can't qualify macro_rules invocation with `{vstr}`");
-            self.struct_span_err(vis.span, &msg)
-                .span_suggestion(
-                    vis.span,
-                    "try exporting the macro",
-                    "#[macro_export]",
-                    Applicability::MaybeIncorrect, // speculative
-                )
-                .emit();
+            self.sess.emit_err(errors::MacroRulesVisibility { span: vis.span, vis: vstr });
         } else {
-            self.struct_span_err(vis.span, "can't qualify macro invocation with `pub`")
-                .span_suggestion(
-                    vis.span,
-                    "remove the visibility",
-                    "",
-                    Applicability::MachineApplicable,
-                )
-                .help(&format!("try adjusting the macro to put `{vstr}` inside the invocation"))
-                .emit();
+            self.sess.emit_err(errors::MacroInvocationVisibility { span: vis.span, vis: vstr });
         }
     }
 
@@ -1989,18 +1937,12 @@ impl<'a> Parser<'a> {
             let kw_token = self.token.clone();
             let kw_str = pprust::token_to_string(&kw_token);
             let item = self.parse_item(ForceCollect::No)?;
-
-            self.struct_span_err(
-                kw_token.span,
-                &format!("`{kw_str}` definition cannot be nested inside `{keyword}`"),
-            )
-            .span_suggestion(
-                item.unwrap().span,
-                &format!("consider creating a new `{kw_str}` definition instead of nesting"),
-                "",
-                Applicability::MaybeIncorrect,
-            )
-            .emit();
+            self.sess.emit_err(errors::NestedAdt {
+                span: kw_token.span,
+                item: item.unwrap().span,
+                kw_str,
+                keyword: keyword.as_str(),
+            });
             // We successfully parsed the item but we must inform the caller about nested problem.
             return Ok(false);
         }
@@ -2139,13 +2081,10 @@ impl<'a> Parser<'a> {
             let _ = self.parse_expr()?;
             self.expect_semi()?; // `;`
             let span = eq_sp.to(self.prev_token.span);
-            self.struct_span_err(span, "function body cannot be `= expression;`")
-                .multipart_suggestion(
-                    "surround the expression with `{` and `}` instead of `=` and `;`",
-                    vec![(eq_sp, "{".to_string()), (self.prev_token.span, " }".to_string())],
-                    Applicability::MachineApplicable,
-                )
-                .emit();
+            self.sess.emit_err(errors::FunctionBodyEqualsExpr {
+                span,
+                sugg: errors::FunctionBodyEqualsExprSugg { eq: eq_sp, semi: self.prev_token.span },
+            });
             (AttrVec::new(), Some(self.mk_block_err(span)))
         } else {
             let expected = if req_body {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index aa57b804779..1c34e491f21 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -43,7 +43,7 @@ use thin_vec::ThinVec;
 use tracing::debug;
 
 use crate::errors::{
-    IncorrectVisibilityRestriction, MismatchedClosingDelimiter, NonStringAbiLiteral,
+    self, IncorrectVisibilityRestriction, MismatchedClosingDelimiter, NonStringAbiLiteral,
 };
 
 bitflags::bitflags! {
@@ -663,15 +663,10 @@ impl<'a> Parser<'a> {
         if case == Case::Insensitive
         && let Some((ident, /* is_raw */ false)) = self.token.ident()
         && ident.as_str().to_lowercase() == kw.as_str().to_lowercase() {
-            self
-                .struct_span_err(ident.span, format!("keyword `{kw}` is written in a wrong case"))
-                .span_suggestion(
-                    ident.span,
-                    "write it in the correct case",
-                    kw,
-                    Applicability::MachineApplicable
-                ).emit();
-
+            self.sess.emit_err(errors::KwBadCase {
+                span: ident.span,
+                kw: kw.as_str()
+            });
             self.bump();
             return true;
         }
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 2246002f5d3..f2422fe307c 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,6 +1,6 @@
 use super::{ForceCollect, Parser, PathStyle, TrailingToken};
 use crate::errors::{
-    AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed,
+    self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed,
     DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
     ExpectedCommaAfterPatternField, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow,
     InclusiveRangeNoEnd, InvalidMutInPattern, PatternOnWrongSideOfAt, RefMutOrderIncorrect,
@@ -908,18 +908,13 @@ impl<'a> Parser<'a> {
         let box_span = self.prev_token.span;
 
         if self.isnt_pattern_start() {
-            self.struct_span_err(
-                self.token.span,
-                format!("expected pattern, found {}", super::token_descr(&self.token)),
-            )
-            .span_note(box_span, "`box` is a reserved keyword")
-            .span_suggestion_verbose(
-                box_span.shrink_to_lo(),
-                "escape `box` to use it as an identifier",
-                "r#",
-                Applicability::MaybeIncorrect,
-            )
-            .emit();
+            let descr = super::token_descr(&self.token);
+            self.sess.emit_err(errors::BoxNotPat {
+                span: self.token.span,
+                kw: box_span,
+                lo: box_span.shrink_to_lo(),
+                descr,
+            });
 
             // We cannot use `parse_pat_ident()` since it will complain `box`
             // is not an identifier.
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 6cceb47ff83..ae73760bd8c 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -8,7 +8,7 @@ use rustc_ast::{
     AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
     Path, PathSegment, QSelf,
 };
-use rustc_errors::{pluralize, Applicability, PResult};
+use rustc_errors::{Applicability, PResult};
 use rustc_span::source_map::{BytePos, Span};
 use rustc_span::symbol::{kw, sym, Ident};
 use std::mem;
@@ -464,23 +464,10 @@ impl<'a> Parser<'a> {
                     // i.e. no multibyte characters, in this range.
                     let span =
                         lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count));
-                    self.struct_span_err(
+                    self.sess.emit_err(errors::UnmatchedAngle {
                         span,
-                        &format!(
-                            "unmatched angle bracket{}",
-                            pluralize!(snapshot.unmatched_angle_bracket_count)
-                        ),
-                    )
-                    .span_suggestion(
-                        span,
-                        &format!(
-                            "remove extra angle bracket{}",
-                            pluralize!(snapshot.unmatched_angle_bracket_count)
-                        ),
-                        "",
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
+                        plural: snapshot.unmatched_angle_bracket_count > 1,
+                    });
 
                     // Try again without unmatched angle bracket characters.
                     self.parse_angle_args(ty_generics)
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index f5f6788362b..3ceb3a2bef1 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -588,20 +588,14 @@ impl<'a> Parser<'a> {
         // Always parse bounds greedily for better error recovery.
         if self.token.is_lifetime() {
             self.look_ahead(1, |t| {
-                if let token::Ident(symname, _) = t.kind {
+                if let token::Ident(sym, _) = t.kind {
                     // parse pattern with "'a Sized" we're supposed to give suggestion like
                     // "'a + Sized"
-                    self.struct_span_err(
-                        self.token.span,
-                        &format!("expected `+` between lifetime and {}", symname),
-                    )
-                    .span_suggestion_verbose(
-                        self.token.span.shrink_to_hi(),
-                        "add `+`",
-                        " +",
-                        Applicability::MaybeIncorrect,
-                    )
-                    .emit();
+                    self.sess.emit_err(errors::MissingPlusBounds {
+                        span: self.token.span,
+                        hi: self.token.span.shrink_to_hi(),
+                        sym,
+                    });
                 }
             })
         }
@@ -926,14 +920,10 @@ impl<'a> Parser<'a> {
                 self.parse_remaining_bounds(bounds, true)?;
                 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
                 let sp = vec![lo, self.prev_token.span];
-                let sugg = vec![(lo, String::from(" ")), (self.prev_token.span, String::new())];
-                self.struct_span_err(sp, "incorrect braces around trait bounds")
-                    .multipart_suggestion(
-                        "remove the parentheses",
-                        sugg,
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
+                self.sess.emit_err(errors::IncorrectBracesTraitBounds {
+                    span: sp,
+                    sugg: errors::IncorrectBracesTraitBoundsSugg { l: lo, r: self.prev_token.span },
+                });
             } else {
                 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
             }
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 2f397e303e5..815b7c85679 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -1,6 +1,6 @@
 //! Meta-syntax validation logic of attributes for post-expansion.
 
-use crate::parse_in;
+use crate::{errors, parse_in};
 
 use rustc_ast::tokenstream::DelimSpan;
 use rustc_ast::MetaItemKind;
@@ -45,7 +45,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
         kind: match &item.args {
             AttrArgs::Empty => MetaItemKind::Word,
             AttrArgs::Delimited(DelimArgs { dspan, delim, tokens }) => {
-                check_meta_bad_delim(sess, *dspan, *delim, "wrong meta list delimiters");
+                check_meta_bad_delim(sess, *dspan, *delim);
                 let nmis = parse_in(sess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?;
                 MetaItemKind::List(nmis)
             }
@@ -84,19 +84,24 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
     })
 }
 
-pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) {
+pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter) {
     if let ast::MacDelimiter::Parenthesis = delim {
         return;
     }
+    sess.emit_err(errors::MetaBadDelim {
+        span: span.entire(),
+        sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close },
+    });
+}
 
-    sess.span_diagnostic
-        .struct_span_err(span.entire(), msg)
-        .multipart_suggestion(
-            "the delimiters should be `(` and `)`",
-            vec![(span.open, "(".to_string()), (span.close, ")".to_string())],
-            Applicability::MachineApplicable,
-        )
-        .emit();
+pub fn check_cfg_attr_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter) {
+    if let ast::MacDelimiter::Parenthesis = delim {
+        return;
+    }
+    sess.emit_err(errors::CfgAttrBadDelim {
+        span: span.entire(),
+        sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close },
+    });
 }
 
 /// Checks that the given meta-item is compatible with this `AttributeTemplate`.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index abf19c30e3d..c2619956219 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -129,8 +129,7 @@ symbols! {
         Any,
         Arc,
         Argument,
-        ArgumentV1,
-        ArgumentV1Methods,
+        ArgumentMethods,
         Arguments,
         AsMut,
         AsRef,
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index a901ae72669..f4f32232570 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -251,145 +251,48 @@ impl<'a> Formatter<'a> {
     }
 }
 
-// NB. Argument is essentially an optimized partially applied formatting function,
-// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`.
-
-extern "C" {
-    type Opaque;
-}
-
-/// This struct represents the generic "argument" which is taken by the Xprintf
-/// family of functions. It contains a function to format the given value. At
-/// compile time it is ensured that the function and the value have the correct
-/// types, and then this struct is used to canonicalize arguments to one type.
-#[lang = "format_argument"]
+/// This structure represents a safely precompiled version of a format string
+/// and its arguments. This cannot be generated at runtime because it cannot
+/// safely be done, so no constructors are given and the fields are private
+/// to prevent modification.
+///
+/// The [`format_args!`] macro will safely create an instance of this structure.
+/// The macro validates the format string at compile-time so usage of the
+/// [`write()`] and [`format()`] functions can be safely performed.
+///
+/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug`
+/// and `Display` contexts as seen below. The example also shows that `Debug`
+/// and `Display` format to the same thing: the interpolated format string
+/// in `format_args!`.
+///
+/// ```rust
+/// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
+/// let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
+/// assert_eq!("1 foo 2", display);
+/// assert_eq!(display, debug);
+/// ```
+///
+/// [`format()`]: ../../std/fmt/fn.format.html
+#[lang = "format_arguments"]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy, Clone)]
-#[allow(missing_debug_implementations)]
-#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-#[doc(hidden)]
-pub struct ArgumentV1<'a> {
-    value: &'a Opaque,
-    formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,
-}
-
-/// This struct represents the unsafety of constructing an `Arguments`.
-/// It exists, rather than an unsafe function, in order to simplify the expansion
-/// of `format_args!(..)` and reduce the scope of the `unsafe` block.
-#[lang = "format_unsafe_arg"]
-#[allow(missing_debug_implementations)]
-#[doc(hidden)]
-#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-pub struct UnsafeArg {
-    _private: (),
-}
-
-impl UnsafeArg {
-    /// See documentation where `UnsafeArg` is required to know when it is safe to
-    /// create and use `UnsafeArg`.
-    #[doc(hidden)]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-    #[inline(always)]
-    pub unsafe fn new() -> Self {
-        Self { _private: () }
-    }
-}
-
-// This guarantees a single stable value for the function pointer associated with
-// indices/counts in the formatting infrastructure.
-//
-// Note that a function defined as such would not be correct as functions are
-// always tagged unnamed_addr with the current lowering to LLVM IR, so their
-// address is not considered important to LLVM and as such the as_usize cast
-// could have been miscompiled. In practice, we never call as_usize on non-usize
-// containing data (as a matter of static generation of the formatting
-// arguments), so this is merely an additional check.
-//
-// We primarily want to ensure that the function pointer at `USIZE_MARKER` has
-// an address corresponding *only* to functions that also take `&usize` as their
-// first argument. The read_volatile here ensures that we can safely ready out a
-// usize from the passed reference and that this address does not point at a
-// non-usize taking function.
-#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| {
-    // SAFETY: ptr is a reference
-    let _v: usize = unsafe { crate::ptr::read_volatile(ptr) };
-    loop {}
-};
-
-macro_rules! arg_new {
-    ($f: ident, $t: ident) => {
-        #[doc(hidden)]
-        #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-        #[inline]
-        pub fn $f<'b, T: $t>(x: &'b T) -> ArgumentV1<'_> {
-            Self::new(x, $t::fmt)
-        }
-    };
-}
-
-#[rustc_diagnostic_item = "ArgumentV1Methods"]
-impl<'a> ArgumentV1<'a> {
-    #[doc(hidden)]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-    #[inline]
-    pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {
-        // SAFETY: `mem::transmute(x)` is safe because
-        //     1. `&'b T` keeps the lifetime it originated with `'b`
-        //              (so as to not have an unbounded lifetime)
-        //     2. `&'b T` and `&'b Opaque` have the same memory layout
-        //              (when `T` is `Sized`, as it is here)
-        // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
-        // and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI
-        // (as long as `T` is `Sized`)
-        unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } }
-    }
-
-    arg_new!(new_display, Display);
-    arg_new!(new_debug, Debug);
-    arg_new!(new_octal, Octal);
-    arg_new!(new_lower_hex, LowerHex);
-    arg_new!(new_upper_hex, UpperHex);
-    arg_new!(new_pointer, Pointer);
-    arg_new!(new_binary, Binary);
-    arg_new!(new_lower_exp, LowerExp);
-    arg_new!(new_upper_exp, UpperExp);
+pub struct Arguments<'a> {
+    // Format string pieces to print.
+    pieces: &'a [&'static str],
 
-    #[doc(hidden)]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-    pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
-        ArgumentV1::new(x, USIZE_MARKER)
-    }
-
-    fn as_usize(&self) -> Option<usize> {
-        // We are type punning a bit here: USIZE_MARKER only takes an &usize but
-        // formatter takes an &Opaque. Rust understandably doesn't think we should compare
-        // the function pointers if they don't have the same signature, so we cast to
-        // usizes to tell it that we just want to compare addresses.
-        if self.formatter as usize == USIZE_MARKER as usize {
-            // SAFETY: The `formatter` field is only set to USIZE_MARKER if
-            // the value is a usize, so this is safe
-            Some(unsafe { *(self.value as *const _ as *const usize) })
-        } else {
-            None
-        }
-    }
-}
+    // Placeholder specs, or `None` if all specs are default (as in "{}{}").
+    fmt: Option<&'a [rt::Placeholder]>,
 
-// flags available in the v1 format of format_args
-#[derive(Copy, Clone)]
-enum FlagV1 {
-    SignPlus,
-    SignMinus,
-    Alternate,
-    SignAwareZeroPad,
-    DebugLowerHex,
-    DebugUpperHex,
+    // Dynamic arguments for interpolation, to be interleaved with string
+    // pieces. (Every argument is preceded by a string piece.)
+    args: &'a [rt::Argument<'a>],
 }
 
+/// Used by the format_args!() macro to create a fmt::Arguments object.
+#[doc(hidden)]
+#[unstable(feature = "fmt_internals", issue = "none")]
 impl<'a> Arguments<'a> {
-    #[doc(hidden)]
     #[inline]
-    #[unstable(feature = "fmt_internals", issue = "none")]
     #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
     pub const fn new_const(pieces: &'a [&'static str]) -> Self {
         if pieces.len() > 1 {
@@ -401,10 +304,8 @@ impl<'a> Arguments<'a> {
     /// When using the format_args!() macro, this function is used to generate the
     /// Arguments structure.
     #[cfg(not(bootstrap))]
-    #[doc(hidden)]
     #[inline]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-    pub fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
+    pub fn new_v1(pieces: &'a [&'static str], args: &'a [rt::Argument<'a>]) -> Arguments<'a> {
         if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
             panic!("invalid args");
         }
@@ -412,11 +313,9 @@ impl<'a> Arguments<'a> {
     }
 
     #[cfg(bootstrap)]
-    #[doc(hidden)]
     #[inline]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
     #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
-    pub const fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
+    pub const fn new_v1(pieces: &'a [&'static str], args: &'a [rt::Argument<'a>]) -> Arguments<'a> {
         if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
             panic!("invalid args");
         }
@@ -425,19 +324,17 @@ impl<'a> Arguments<'a> {
 
     /// This function is used to specify nonstandard formatting parameters.
     ///
-    /// An `UnsafeArg` is required because the following invariants must be held
+    /// An `rt::UnsafeArg` is required because the following invariants must be held
     /// in order for this function to be safe:
     /// 1. The `pieces` slice must be at least as long as `fmt`.
     /// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`.
     /// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
-    #[doc(hidden)]
     #[inline]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
     pub fn new_v1_formatted(
         pieces: &'a [&'static str],
-        args: &'a [ArgumentV1<'a>],
+        args: &'a [rt::Argument<'a>],
         fmt: &'a [rt::Placeholder],
-        _unsafe_arg: UnsafeArg,
+        _unsafe_arg: rt::UnsafeArg,
     ) -> Arguments<'a> {
         Arguments { pieces, fmt: Some(fmt), args }
     }
@@ -446,9 +343,7 @@ impl<'a> Arguments<'a> {
     ///
     /// This is intended to be used for setting initial `String` capacity
     /// when using `format!`. Note: this is neither the lower nor upper bound.
-    #[doc(hidden)]
     #[inline]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
     pub fn estimated_capacity(&self) -> usize {
         let pieces_length: usize = self.pieces.iter().map(|x| x.len()).sum();
 
@@ -468,43 +363,6 @@ impl<'a> Arguments<'a> {
     }
 }
 
-/// This structure represents a safely precompiled version of a format string
-/// and its arguments. This cannot be generated at runtime because it cannot
-/// safely be done, so no constructors are given and the fields are private
-/// to prevent modification.
-///
-/// The [`format_args!`] macro will safely create an instance of this structure.
-/// The macro validates the format string at compile-time so usage of the
-/// [`write()`] and [`format()`] functions can be safely performed.
-///
-/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug`
-/// and `Display` contexts as seen below. The example also shows that `Debug`
-/// and `Display` format to the same thing: the interpolated format string
-/// in `format_args!`.
-///
-/// ```rust
-/// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
-/// let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
-/// assert_eq!("1 foo 2", display);
-/// assert_eq!(display, debug);
-/// ```
-///
-/// [`format()`]: ../../std/fmt/fn.format.html
-#[lang = "format_arguments"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Copy, Clone)]
-pub struct Arguments<'a> {
-    // Format string pieces to print.
-    pieces: &'a [&'static str],
-
-    // Placeholder specs, or `None` if all specs are default (as in "{}{}").
-    fmt: Option<&'a [rt::Placeholder]>,
-
-    // Dynamic arguments for interpolation, to be interleaved with string
-    // pieces. (Every argument is preceded by a string piece.)
-    args: &'a [ArgumentV1<'a>],
-}
-
 impl<'a> Arguments<'a> {
     /// Get the formatted string, if it has no arguments to be formatted at runtime.
     ///
@@ -1244,7 +1102,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
                 if !piece.is_empty() {
                     formatter.buf.write_str(*piece)?;
                 }
-                (arg.formatter)(arg.value, &mut formatter)?;
+                arg.fmt(&mut formatter)?;
                 idx += 1;
             }
         }
@@ -1274,7 +1132,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
     Ok(())
 }
 
-unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[ArgumentV1<'_>]) -> Result {
+unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argument<'_>]) -> Result {
     fmt.fill = arg.fill;
     fmt.align = arg.align;
     fmt.flags = arg.flags;
@@ -1292,10 +1150,10 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[ArgumentV1
     let value = unsafe { args.get_unchecked(arg.position) };
 
     // Then actually do some printing
-    (value.formatter)(value.value, fmt)
+    value.fmt(fmt)
 }
 
-unsafe fn getcount(args: &[ArgumentV1<'_>], cnt: &rt::Count) -> Option<usize> {
+unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize> {
     match *cnt {
         rt::Count::Is(n) => Some(n),
         rt::Count::Implied => None,
@@ -1878,7 +1736,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_plus(&self) -> bool {
-        self.flags & (1 << FlagV1::SignPlus as u32) != 0
+        self.flags & (1 << rt::Flag::SignPlus as u32) != 0
     }
 
     /// Determines if the `-` flag was specified.
@@ -1907,7 +1765,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_minus(&self) -> bool {
-        self.flags & (1 << FlagV1::SignMinus as u32) != 0
+        self.flags & (1 << rt::Flag::SignMinus as u32) != 0
     }
 
     /// Determines if the `#` flag was specified.
@@ -1935,7 +1793,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn alternate(&self) -> bool {
-        self.flags & (1 << FlagV1::Alternate as u32) != 0
+        self.flags & (1 << rt::Flag::Alternate as u32) != 0
     }
 
     /// Determines if the `0` flag was specified.
@@ -1961,17 +1819,17 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_aware_zero_pad(&self) -> bool {
-        self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0
+        self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0
     }
 
     // FIXME: Decide what public API we want for these two flags.
     // https://github.com/rust-lang/rust/issues/48584
     fn debug_lower_hex(&self) -> bool {
-        self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0
+        self.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0
     }
 
     fn debug_upper_hex(&self) -> bool {
-        self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0
+        self.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0
     }
 
     /// Creates a [`DebugStruct`] builder designed to assist with creation of
@@ -2531,13 +2389,13 @@ pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Resul
     // or not to zero extend, and then unconditionally set it to get the
     // prefix.
     if f.alternate() {
-        f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
+        f.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32);
 
         if f.width.is_none() {
             f.width = Some((usize::BITS / 4) as usize + 2);
         }
     }
-    f.flags |= 1 << (FlagV1::Alternate as u32);
+    f.flags |= 1 << (rt::Flag::Alternate as u32);
 
     let ret = LowerHex::fmt(&ptr_addr, f);
 
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index 2c1a767691b..0596f6c30ce 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -3,6 +3,8 @@
 
 //! These are the lang items used by format_args!().
 
+use super::*;
+
 #[lang = "format_placeholder"]
 #[derive(Copy, Clone)]
 pub struct Placeholder {
@@ -28,21 +30,17 @@ impl Placeholder {
     }
 }
 
-/// Possible alignments that can be requested as part of a formatting directive.
 #[lang = "format_alignment"]
 #[derive(Copy, Clone, PartialEq, Eq)]
 pub enum Alignment {
-    /// Indication that contents should be left-aligned.
     Left,
-    /// Indication that contents should be right-aligned.
     Right,
-    /// Indication that contents should be center-aligned.
     Center,
-    /// No alignment was requested.
     Unknown,
 }
 
-/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers.
+/// Used by [width](https://doc.rust-lang.org/std/fmt/#width)
+/// and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers.
 #[lang = "format_count"]
 #[derive(Copy, Clone)]
 pub enum Count {
@@ -53,3 +51,147 @@ pub enum Count {
     /// Not specified
     Implied,
 }
+
+// This needs to match the order of flags in compiler/rustc_ast_lowering/src/format.rs.
+#[derive(Copy, Clone)]
+pub(super) enum Flag {
+    SignPlus,
+    SignMinus,
+    Alternate,
+    SignAwareZeroPad,
+    DebugLowerHex,
+    DebugUpperHex,
+}
+
+/// This struct represents the generic "argument" which is taken by format_args!().
+/// It contains a function to format the given value. At compile time it is ensured that the
+/// function and the value have the correct types, and then this struct is used to canonicalize
+/// arguments to one type.
+///
+/// Argument is essentially an optimized partially applied formatting function,
+/// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`.
+#[lang = "format_argument"]
+#[derive(Copy, Clone)]
+pub struct Argument<'a> {
+    value: &'a Opaque,
+    formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,
+}
+
+#[rustc_diagnostic_item = "ArgumentMethods"]
+impl<'a> Argument<'a> {
+    #[inline(always)]
+    fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'b> {
+        // SAFETY: `mem::transmute(x)` is safe because
+        //     1. `&'b T` keeps the lifetime it originated with `'b`
+        //              (so as to not have an unbounded lifetime)
+        //     2. `&'b T` and `&'b Opaque` have the same memory layout
+        //              (when `T` is `Sized`, as it is here)
+        // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
+        // and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI
+        // (as long as `T` is `Sized`)
+        unsafe { Argument { formatter: mem::transmute(f), value: mem::transmute(x) } }
+    }
+
+    #[inline(always)]
+    pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'_> {
+        Self::new(x, Display::fmt)
+    }
+    #[inline(always)]
+    pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'_> {
+        Self::new(x, Debug::fmt)
+    }
+    #[inline(always)]
+    pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'_> {
+        Self::new(x, Octal::fmt)
+    }
+    #[inline(always)]
+    pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'_> {
+        Self::new(x, LowerHex::fmt)
+    }
+    #[inline(always)]
+    pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'_> {
+        Self::new(x, UpperHex::fmt)
+    }
+    #[inline(always)]
+    pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'_> {
+        Self::new(x, Pointer::fmt)
+    }
+    #[inline(always)]
+    pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'_> {
+        Self::new(x, Binary::fmt)
+    }
+    #[inline(always)]
+    pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'_> {
+        Self::new(x, LowerExp::fmt)
+    }
+    #[inline(always)]
+    pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'_> {
+        Self::new(x, UpperExp::fmt)
+    }
+    #[inline(always)]
+    pub fn from_usize(x: &usize) -> Argument<'_> {
+        Self::new(x, USIZE_MARKER)
+    }
+
+    #[inline(always)]
+    pub(super) fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+        (self.formatter)(self.value, f)
+    }
+
+    #[inline(always)]
+    pub(super) fn as_usize(&self) -> Option<usize> {
+        // We are type punning a bit here: USIZE_MARKER only takes an &usize but
+        // formatter takes an &Opaque. Rust understandably doesn't think we should compare
+        // the function pointers if they don't have the same signature, so we cast to
+        // usizes to tell it that we just want to compare addresses.
+        if self.formatter as usize == USIZE_MARKER as usize {
+            // SAFETY: The `formatter` field is only set to USIZE_MARKER if
+            // the value is a usize, so this is safe
+            Some(unsafe { *(self.value as *const _ as *const usize) })
+        } else {
+            None
+        }
+    }
+}
+
+/// This struct represents the unsafety of constructing an `Arguments`.
+/// It exists, rather than an unsafe function, in order to simplify the expansion
+/// of `format_args!(..)` and reduce the scope of the `unsafe` block.
+#[lang = "format_unsafe_arg"]
+pub struct UnsafeArg {
+    _private: (),
+}
+
+impl UnsafeArg {
+    /// See documentation where `UnsafeArg` is required to know when it is safe to
+    /// create and use `UnsafeArg`.
+    #[inline(always)]
+    pub unsafe fn new() -> Self {
+        Self { _private: () }
+    }
+}
+
+extern "C" {
+    type Opaque;
+}
+
+// This guarantees a single stable value for the function pointer associated with
+// indices/counts in the formatting infrastructure.
+//
+// Note that a function defined as such would not be correct as functions are
+// always tagged unnamed_addr with the current lowering to LLVM IR, so their
+// address is not considered important to LLVM and as such the as_usize cast
+// could have been miscompiled. In practice, we never call as_usize on non-usize
+// containing data (as a matter of static generation of the formatting
+// arguments), so this is merely an additional check.
+//
+// We primarily want to ensure that the function pointer at `USIZE_MARKER` has
+// an address corresponding *only* to functions that also take `&usize` as their
+// first argument. The read_volatile here ensures that we can safely ready out a
+// usize from the passed reference and that this address does not point at a
+// non-usize taking function.
+static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| {
+    // SAFETY: ptr is a reference
+    let _v: usize = unsafe { crate::ptr::read_volatile(ptr) };
+    loop {}
+};
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 956db577d53..8ed62cdddcd 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -1132,26 +1132,29 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io
                     &dir,
                     &name,
                     c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY,
-                )?;
-                dirlist.push(child_dir);
-            } else {
-                for i in 1..=MAX_RETRIES {
-                    let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE);
-                    match result {
-                        Ok(f) => delete(&f)?,
-                        // Already deleted, so skip.
-                        Err(e) if e.kind() == io::ErrorKind::NotFound => break,
-                        // Retry a few times if the file is locked or a delete is already in progress.
-                        Err(e)
-                            if i < MAX_RETRIES
-                                && (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _)
-                                    || e.raw_os_error()
-                                        == Some(c::ERROR_SHARING_VIOLATION as _)) => {}
-                        // Otherwise return the error.
-                        Err(e) => return Err(e),
-                    }
-                    thread::yield_now();
+                );
+                // On success, add the handle to the queue.
+                // If opening the directory fails we treat it the same as a file
+                if let Ok(child_dir) = child_dir {
+                    dirlist.push(child_dir);
+                    continue;
+                }
+            }
+            for i in 1..=MAX_RETRIES {
+                let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE);
+                match result {
+                    Ok(f) => delete(&f)?,
+                    // Already deleted, so skip.
+                    Err(e) if e.kind() == io::ErrorKind::NotFound => break,
+                    // Retry a few times if the file is locked or a delete is already in progress.
+                    Err(e)
+                        if i < MAX_RETRIES
+                            && (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _)
+                                || e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _)) => {}
+                    // Otherwise return the error.
+                    Err(e) => return Err(e),
                 }
+                thread::yield_now();
             }
         }
         // If there were no more files then delete the directory.
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
index 4f73746f817..c4381e202b9 100644
--- a/src/etc/lldb_providers.py
+++ b/src/etc/lldb_providers.py
@@ -31,7 +31,7 @@ from lldb import SBValue, SBData, SBError, eBasicTypeLong, eBasicTypeUnsignedLon
 #
 # You can find more information and examples here:
 #   1. https://lldb.llvm.org/varformats.html
-#   2. https://lldb.llvm.org/python-reference.html
+#   2. https://lldb.llvm.org/use/python-reference.html
 #   3. https://lldb.llvm.org/python_reference/lldb.formatters.cpp.libcxx-pysrc.html
 #   4. https://github.com/llvm-mirror/lldb/tree/master/examples/summaries/cocoa
 ####################################################################################################
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index c992a5388d1..8ccdb16b784 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -304,7 +304,7 @@ pub(crate) fn clean_predicate<'tcx>(
             clean_region_outlives_predicate(pred)
         }
         ty::PredicateKind::Clause(ty::Clause::TypeOutlives(pred)) => {
-            clean_type_outlives_predicate(pred, cx)
+            clean_type_outlives_predicate(bound_predicate.rebind(pred), cx)
         }
         ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
             Some(clean_projection_predicate(bound_predicate.rebind(pred), cx))
@@ -345,7 +345,7 @@ fn clean_poly_trait_predicate<'tcx>(
 }
 
 fn clean_region_outlives_predicate<'tcx>(
-    pred: ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>,
+    pred: ty::RegionOutlivesPredicate<'tcx>,
 ) -> Option<WherePredicate> {
     let ty::OutlivesPredicate(a, b) = pred;
 
@@ -358,13 +358,13 @@ fn clean_region_outlives_predicate<'tcx>(
 }
 
 fn clean_type_outlives_predicate<'tcx>(
-    pred: ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
+    pred: ty::Binder<'tcx, ty::TypeOutlivesPredicate<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> Option<WherePredicate> {
-    let ty::OutlivesPredicate(ty, lt) = pred;
+    let ty::OutlivesPredicate(ty, lt) = pred.skip_binder();
 
     Some(WherePredicate::BoundPredicate {
-        ty: clean_middle_ty(ty::Binder::dummy(ty), cx, None),
+        ty: clean_middle_ty(pred.rebind(ty), cx, None),
         bounds: vec![GenericBound::Outlives(
             clean_middle_region(lt).expect("failed to clean lifetimes"),
         )],
diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr
index 6bf13f21601..f04dfab36ca 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.stderr
+++ b/src/tools/miri/tests/fail/panic/double_panic.stderr
@@ -12,57 +12,59 @@ stack backtrace:
  at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
    4: <std::sys_common::backtrace::_print::DisplayBacktrace as std::fmt::Display>::fmt
  at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-   5: std::fmt::write
+   5: core::fmt::rt::Argument::fmt
+ at RUSTLIB/core/src/fmt/rt.rs:LL:CC
+   6: std::fmt::write
  at RUSTLIB/core/src/fmt/mod.rs:LL:CC
-   6: <std::sys::PLATFORM::stdio::Stderr as std::io::Write>::write_fmt
+   7: <std::sys::PLATFORM::stdio::Stderr as std::io::Write>::write_fmt
  at RUSTLIB/std/src/io/mod.rs:LL:CC
-   7: std::sys_common::backtrace::_print
+   8: std::sys_common::backtrace::_print
  at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-   8: std::sys_common::backtrace::print
+   9: std::sys_common::backtrace::print
  at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-   9: std::panicking::default_hook::{closure#1}
+  10: std::panicking::default_hook::{closure#1}
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  10: std::panicking::default_hook
+  11: std::panicking::default_hook
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  11: std::panicking::rust_panic_with_hook
+  12: std::panicking::rust_panic_with_hook
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  12: std::rt::begin_panic::{closure#0}
+  13: std::rt::begin_panic::{closure#0}
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  13: std::sys_common::backtrace::__rust_end_short_backtrace
+  14: std::sys_common::backtrace::__rust_end_short_backtrace
  at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-  14: std::rt::begin_panic
+  15: std::rt::begin_panic
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  15: <Foo as std::ops::Drop>::drop
+  16: <Foo as std::ops::Drop>::drop
  at $DIR/double_panic.rs:LL:CC
-  16: std::ptr::drop_in_place - shim(Some(Foo))
+  17: std::ptr::drop_in_place - shim(Some(Foo))
  at RUSTLIB/core/src/ptr/mod.rs:LL:CC
-  17: main
+  18: main
  at $DIR/double_panic.rs:LL:CC
-  18: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
+  19: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
  at RUSTLIB/core/src/ops/function.rs:LL:CC
-  19: std::sys_common::backtrace::__rust_begin_short_backtrace
+  20: std::sys_common::backtrace::__rust_begin_short_backtrace
  at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-  20: std::rt::lang_start::{closure#0}
+  21: std::rt::lang_start::{closure#0}
  at RUSTLIB/std/src/rt.rs:LL:CC
-  21: std::ops::function::impls::call_once
+  22: std::ops::function::impls::call_once
  at RUSTLIB/core/src/ops/function.rs:LL:CC
-  22: std::panicking::r#try::do_call
+  23: std::panicking::r#try::do_call
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  23: std::panicking::r#try
+  24: std::panicking::r#try
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  24: std::panic::catch_unwind
+  25: std::panic::catch_unwind
  at RUSTLIB/std/src/panic.rs:LL:CC
-  25: std::rt::lang_start_internal::{closure#2}
+  26: std::rt::lang_start_internal::{closure#2}
  at RUSTLIB/std/src/rt.rs:LL:CC
-  26: std::panicking::r#try::do_call
+  27: std::panicking::r#try::do_call
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  27: std::panicking::r#try
+  28: std::panicking::r#try
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  28: std::panic::catch_unwind
+  29: std::panic::catch_unwind
  at RUSTLIB/std/src/panic.rs:LL:CC
-  29: std::rt::lang_start_internal
+  30: std::rt::lang_start_internal
  at RUSTLIB/std/src/rt.rs:LL:CC
-  30: std::rt::lang_start
+  31: std::rt::lang_start
  at RUSTLIB/std/src/rt.rs:LL:CC
 thread panicked while panicking. aborting.
 error: abnormal termination: the program aborted execution
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index 0b72ca1eec1..5fbd1789b3a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -201,7 +201,7 @@ macro_rules! format_args {
 }
 
 fn main() {
-    $crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(arg1(a, b, c)), $crate::fmt::Display::fmt), $crate::fmt::ArgumentV1::new(&(arg2), $crate::fmt::Display::fmt), ]);
+    $crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::Argument::new(&(arg1(a, b, c)), $crate::fmt::Display::fmt), $crate::fmt::Argument::new(&(arg2), $crate::fmt::Display::fmt), ]);
 }
 "#]],
     );
@@ -229,7 +229,7 @@ macro_rules! format_args {
 }
 
 fn main() {
-    $crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(a::<A, B>()), $crate::fmt::Display::fmt), $crate::fmt::ArgumentV1::new(&(b), $crate::fmt::Display::fmt), ]);
+    $crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::Argument::new(&(a::<A, B>()), $crate::fmt::Display::fmt), $crate::fmt::Argument::new(&(b), $crate::fmt::Display::fmt), ]);
 }
 "#]],
     );
@@ -260,7 +260,7 @@ macro_rules! format_args {
 fn main() {
     let _ =
         /* parse error: expected field name or number */
-$crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(a.), $crate::fmt::Display::fmt), ]);
+$crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::Argument::new(&(a.), $crate::fmt::Display::fmt), ]);
 }
 "#]],
     );
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
index 44510f2b7ff..a9c5e1488aa 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
@@ -241,8 +241,8 @@ fn format_args_expand(
     // We expand `format_args!("", a1, a2)` to
     // ```
     // $crate::fmt::Arguments::new_v1(&[], &[
-    //   $crate::fmt::ArgumentV1::new(&arg1,$crate::fmt::Display::fmt),
-    //   $crate::fmt::ArgumentV1::new(&arg2,$crate::fmt::Display::fmt),
+    //   $crate::fmt::Argument::new(&arg1,$crate::fmt::Display::fmt),
+    //   $crate::fmt::Argument::new(&arg2,$crate::fmt::Display::fmt),
     // ])
     // ```,
     // which is still not really correct, but close enough for now
@@ -267,7 +267,7 @@ fn format_args_expand(
     }
     let _format_string = args.remove(0);
     let arg_tts = args.into_iter().flat_map(|arg| {
-        quote! { #DOLLAR_CRATE::fmt::ArgumentV1::new(&(#arg), #DOLLAR_CRATE::fmt::Display::fmt), }
+        quote! { #DOLLAR_CRATE::fmt::Argument::new(&(#arg), #DOLLAR_CRATE::fmt::Display::fmt), }
     }.token_trees);
     let expanded = quote! {
         #DOLLAR_CRATE::fmt::Arguments::new_v1(&[], &[##arg_tts])
diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
index 579587a430b..9bda5f575c9 100644
--- a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
@@ -15,14 +15,14 @@
       let mut _13: &[&str; 3];             // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
       let _14: &[&str; 3];                 // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
       let _15: [&str; 3];                  // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
-      let mut _16: &[core::fmt::ArgumentV1<'_>]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _17: &[core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _18: &[core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _19: [core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _20: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
+      let mut _16: &[core::fmt::rt::Argument<'_>]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _17: &[core::fmt::rt::Argument<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _18: &[core::fmt::rt::Argument<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _19: [core::fmt::rt::Argument<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _20: core::fmt::rt::Argument<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
       let mut _21: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
       let _22: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
-      let mut _23: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
+      let mut _23: core::fmt::rt::Argument<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
       let mut _24: &u32;                   // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
       let _25: &u32;                       // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
       let mut _27: bool;                   // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
@@ -113,11 +113,11 @@
           StorageLive(_22);                // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
           _22 = &_8;                       // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
           _21 = &(*_22);                   // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
-          _20 = core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _21) -> [return: bb3, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
+          _20 = core::fmt::rt::Argument::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _21) -> [return: bb3, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
                                            // mir::Constant
                                            // + span: $DIR/lifetimes.rs:27:20: 27:23
                                            // + user_ty: UserType(4)
-                                           // + literal: Const { ty: for<'b> fn(&'b Box<dyn std::fmt::Display>) -> core::fmt::ArgumentV1<'b> {core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>}, val: Value(<ZST>) }
+                                           // + literal: Const { ty: for<'b> fn(&'b Box<dyn std::fmt::Display>) -> core::fmt::rt::Argument<'b> {core::fmt::rt::Argument::<'_>::new_display::<Box<dyn std::fmt::Display>>}, val: Value(<ZST>) }
       }
   
       bb3: {
@@ -127,11 +127,11 @@
           StorageLive(_25);                // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
           _25 = &_6;                       // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
           _24 = &(*_25);                   // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
-          _23 = core::fmt::ArgumentV1::<'_>::new_display::<u32>(move _24) -> [return: bb4, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
+          _23 = core::fmt::rt::Argument::<'_>::new_display::<u32>(move _24) -> [return: bb4, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
                                            // mir::Constant
                                            // + span: $DIR/lifetimes.rs:27:24: 27:27
                                            // + user_ty: UserType(5)
-                                           // + literal: Const { ty: for<'b> fn(&'b u32) -> core::fmt::ArgumentV1<'b> {core::fmt::ArgumentV1::<'_>::new_display::<u32>}, val: Value(<ZST>) }
+                                           // + literal: Const { ty: for<'b> fn(&'b u32) -> core::fmt::rt::Argument<'b> {core::fmt::rt::Argument::<'_>::new_display::<u32>}, val: Value(<ZST>) }
       }
   
       bb4: {
@@ -141,13 +141,13 @@
           StorageDead(_20);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           _18 = &_19;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           _17 = &(*_18);                   // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _16 = move _17 as &[core::fmt::ArgumentV1<'_>] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _16 = move _17 as &[core::fmt::rt::Argument<'_>] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           StorageDead(_17);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           _11 = Arguments::<'_>::new_v1(move _12, move _16) -> [return: bb5, unwind unreachable]; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + user_ty: UserType(3)
-                                           // + literal: Const { ty: fn(&[&'static str], &[core::fmt::ArgumentV1<'_>]) -> Arguments<'_> {Arguments::<'_>::new_v1}, val: Value(<ZST>) }
+                                           // + literal: Const { ty: fn(&[&'static str], &[core::fmt::rt::Argument<'_>]) -> Arguments<'_> {Arguments::<'_>::new_v1}, val: Value(<ZST>) }
       }
   
       bb5: {
diff --git a/tests/rustdoc-ui/issue-110900.rs b/tests/rustdoc-ui/issue-110900.rs
new file mode 100644
index 00000000000..e3154baf860
--- /dev/null
+++ b/tests/rustdoc-ui/issue-110900.rs
@@ -0,0 +1,28 @@
+// check-pass
+
+#![crate_type="lib"]
+#![feature(associated_type_bounds)]
+
+trait A<'a> {}
+trait B<'b> {}
+
+trait C<'c>: for<'a> A<'a> + for<'b> B<'b> {
+    type As;
+}
+
+trait E<'e> {
+    type As;
+}
+trait F<'f>: for<'a> A<'a> + for<'e> E<'e> {}
+struct G<T>
+where
+    T: for<'l, 'i> H<'l, 'i, As: for<'a> A<'a> + 'i>
+{
+    t: std::marker::PhantomData<T>,
+}
+
+trait I<'a, 'b, 'c> {
+    type As;
+}
+
+trait H<'d, 'e>: for<'f> I<'d, 'f, 'e> + 'd {}
diff --git a/tests/ui/attributes/invalid_macro_export_argument.deny.stderr b/tests/ui/attributes/invalid_macro_export_argument.deny.stderr
new file mode 100644
index 00000000000..644acc27b58
--- /dev/null
+++ b/tests/ui/attributes/invalid_macro_export_argument.deny.stderr
@@ -0,0 +1,20 @@
+error: `#[macro_export]` can only take 1 or 0 arguments
+  --> $DIR/invalid_macro_export_argument.rs:7:1
+   |
+LL | #[macro_export(hello, world)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/invalid_macro_export_argument.rs:4:24
+   |
+LL | #![cfg_attr(deny, deny(invalid_macro_export_arguments))]
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `not_local_inner_macros` isn't a valid `#[macro_export]` argument
+  --> $DIR/invalid_macro_export_argument.rs:13:16
+   |
+LL | #[macro_export(not_local_inner_macros)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/attributes/invalid_macro_export_argument.rs b/tests/ui/attributes/invalid_macro_export_argument.rs
index 85d009f11a6..a0ed5fd1c8f 100644
--- a/tests/ui/attributes/invalid_macro_export_argument.rs
+++ b/tests/ui/attributes/invalid_macro_export_argument.rs
@@ -1,10 +1,17 @@
-// check-pass
-#[macro_export(hello, world)] //~ WARN `#[macro_export]` can only take 1 or 0 arguments
+// revisions: deny allow
+//[allow] check-pass
+
+#![cfg_attr(deny, deny(invalid_macro_export_arguments))]
+#![cfg_attr(allow, allow(invalid_macro_export_arguments))]
+
+#[macro_export(hello, world)]
+//[deny]~^ ERROR `#[macro_export]` can only take 1 or 0 arguments
 macro_rules! a {
     () => ()
 }
 
-#[macro_export(not_local_inner_macros)] //~ WARN `not_local_inner_macros` isn't a valid `#[macro_export]` argument
+#[macro_export(not_local_inner_macros)]
+//[deny]~^ ERROR `not_local_inner_macros` isn't a valid `#[macro_export]` argument
 macro_rules! b {
     () => ()
 }
diff --git a/tests/ui/attributes/invalid_macro_export_argument.stderr b/tests/ui/attributes/invalid_macro_export_argument.stderr
deleted file mode 100644
index a4e17642c2a..00000000000
--- a/tests/ui/attributes/invalid_macro_export_argument.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-warning: `#[macro_export]` can only take 1 or 0 arguments
-  --> $DIR/invalid_macro_export_argument.rs:2:1
-   |
-LL | #[macro_export(hello, world)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(invalid_macro_export_arguments)]` on by default
-
-warning: `not_local_inner_macros` isn't a valid `#[macro_export]` argument
-  --> $DIR/invalid_macro_export_argument.rs:7:16
-   |
-LL | #[macro_export(not_local_inner_macros)]
-   |                ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: 2 warnings emitted
-
diff --git a/tests/ui/fmt/ifmt-bad-arg.stderr b/tests/ui/fmt/ifmt-bad-arg.stderr
index bf18fb315c9..ed008c454a3 100644
--- a/tests/ui/fmt/ifmt-bad-arg.stderr
+++ b/tests/ui/fmt/ifmt-bad-arg.stderr
@@ -307,7 +307,7 @@ LL |     println!("{} {:.*} {}", 1, 3.2, 4);
    = note: expected reference `&usize`
               found reference `&{float}`
 note: associated function defined here
-  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+  --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
@@ -321,7 +321,7 @@ LL |     println!("{} {:07$.*} {}", 1, 3.2, 4);
    = note: expected reference `&usize`
               found reference `&{float}`
 note: associated function defined here
-  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+  --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 38 previous errors
diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr
index dc2dee3f341..cc316e55f5c 100644
--- a/tests/ui/fmt/ifmt-unimpl.stderr
+++ b/tests/ui/fmt/ifmt-unimpl.stderr
@@ -17,9 +17,9 @@ LL |     format!("{:X}", "3");
              NonZeroIsize
            and 21 others
    = note: required for `&str` to implement `UpperHex`
-note: required by a bound in `core::fmt::ArgumentV1::<'a>::new_upper_hex`
-  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `arg_new` (in Nightly builds, run with -Z macro-backtrace for more info)
+note: required by a bound in `core::fmt::rt::Argument::<'a>::new_upper_hex`
+  --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
+   = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/tests/ui/fmt/send-sync.stderr b/tests/ui/fmt/send-sync.stderr
index d43f4f0d957..b517a342e63 100644
--- a/tests/ui/fmt/send-sync.stderr
+++ b/tests/ui/fmt/send-sync.stderr
@@ -1,16 +1,16 @@
-error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely
+error[E0277]: `core::fmt::rt::Opaque` cannot be shared between threads safely
   --> $DIR/send-sync.rs:8:10
    |
 LL |     send(format_args!("{:?}", c));
-   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::Opaque` cannot be shared between threads safely
+   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::rt::Opaque` cannot be shared between threads safely
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `[core::fmt::ArgumentV1<'_>]`, the trait `Sync` is not implemented for `core::fmt::Opaque`
-   = note: required because it appears within the type `&core::fmt::Opaque`
-   = note: required because it appears within the type `ArgumentV1<'_>`
-   = note: required because it appears within the type `[ArgumentV1<'_>]`
-   = note: required for `&[core::fmt::ArgumentV1<'_>]` to implement `Send`
+   = help: within `[core::fmt::rt::Argument<'_>]`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`
+   = note: required because it appears within the type `&core::fmt::rt::Opaque`
+   = note: required because it appears within the type `Argument<'_>`
+   = note: required because it appears within the type `[Argument<'_>]`
+   = note: required for `&[core::fmt::rt::Argument<'_>]` to implement `Send`
    = note: required because it appears within the type `Arguments<'_>`
 note: required by a bound in `send`
   --> $DIR/send-sync.rs:1:12
@@ -18,19 +18,19 @@ note: required by a bound in `send`
 LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
 
-error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely
+error[E0277]: `core::fmt::rt::Opaque` cannot be shared between threads safely
   --> $DIR/send-sync.rs:9:10
    |
 LL |     sync(format_args!("{:?}", c));
-   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::Opaque` cannot be shared between threads safely
+   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::rt::Opaque` cannot be shared between threads safely
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::Opaque`
-   = note: required because it appears within the type `&core::fmt::Opaque`
-   = note: required because it appears within the type `ArgumentV1<'_>`
-   = note: required because it appears within the type `[ArgumentV1<'_>]`
-   = note: required because it appears within the type `&[ArgumentV1<'_>]`
+   = help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`
+   = note: required because it appears within the type `&core::fmt::rt::Opaque`
+   = note: required because it appears within the type `Argument<'_>`
+   = note: required because it appears within the type `[Argument<'_>]`
+   = note: required because it appears within the type `&[Argument<'_>]`
    = note: required because it appears within the type `Arguments<'_>`
 note: required by a bound in `sync`
   --> $DIR/send-sync.rs:2:12
diff --git a/tests/ui/macros/missing-bang-in-decl.stderr b/tests/ui/macros/missing-bang-in-decl.stderr
index dfabafb0a7a..aa78c9a6906 100644
--- a/tests/ui/macros/missing-bang-in-decl.stderr
+++ b/tests/ui/macros/missing-bang-in-decl.stderr
@@ -2,13 +2,23 @@ error: expected `!` after `macro_rules`
   --> $DIR/missing-bang-in-decl.rs:5:1
    |
 LL | macro_rules foo {
-   | ^^^^^^^^^^^ help: add a `!`: `macro_rules!`
+   | ^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | macro_rules! foo {
+   |            +
 
 error: expected `!` after `macro_rules`
   --> $DIR/missing-bang-in-decl.rs:10:1
    |
 LL | macro_rules bar! {
-   | ^^^^^^^^^^^ help: add a `!`: `macro_rules!`
+   | ^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | macro_rules! bar! {
+   |            +
 
 error: macro names aren't followed by a `!`
   --> $DIR/missing-bang-in-decl.rs:10:16
diff --git a/tests/ui/parser/item-kw-case-mismatch.fixed b/tests/ui/parser/item-kw-case-mismatch.fixed
index 1794268f260..4b99537fbf7 100644
--- a/tests/ui/parser/item-kw-case-mismatch.fixed
+++ b/tests/ui/parser/item-kw-case-mismatch.fixed
@@ -4,31 +4,31 @@
 
 fn main() {}
 
-use std::ptr::read;  //~ ERROR keyword `use` is written in a wrong case
-use std::ptr::write; //~ ERROR keyword `use` is written in a wrong case
+use std::ptr::read;  //~ ERROR keyword `use` is written in the wrong case
+use std::ptr::write; //~ ERROR keyword `use` is written in the wrong case
 
 async fn _a() {}
-//~^ ERROR keyword `fn` is written in a wrong case
+//~^ ERROR keyword `fn` is written in the wrong case
 
 fn _b() {}
-//~^ ERROR keyword `fn` is written in a wrong case
+//~^ ERROR keyword `fn` is written in the wrong case
 
 async fn _c() {}
-//~^ ERROR keyword `async` is written in a wrong case
-//~| ERROR keyword `fn` is written in a wrong case
+//~^ ERROR keyword `async` is written in the wrong case
+//~| ERROR keyword `fn` is written in the wrong case
 
 async fn _d() {}
-//~^ ERROR keyword `async` is written in a wrong case
+//~^ ERROR keyword `async` is written in the wrong case
 
 const unsafe fn _e() {}
-//~^ ERROR keyword `const` is written in a wrong case
-//~| ERROR keyword `unsafe` is written in a wrong case
-//~| ERROR keyword `fn` is written in a wrong case
+//~^ ERROR keyword `const` is written in the wrong case
+//~| ERROR keyword `unsafe` is written in the wrong case
+//~| ERROR keyword `fn` is written in the wrong case
 
 unsafe extern fn _f() {}
-//~^ ERROR keyword `unsafe` is written in a wrong case
-//~| ERROR keyword `extern` is written in a wrong case
+//~^ ERROR keyword `unsafe` is written in the wrong case
+//~| ERROR keyword `extern` is written in the wrong case
 
 extern "C" fn _g() {}
-//~^ ERROR keyword `extern` is written in a wrong case
-//~| ERROR keyword `fn` is written in a wrong case
+//~^ ERROR keyword `extern` is written in the wrong case
+//~| ERROR keyword `fn` is written in the wrong case
diff --git a/tests/ui/parser/item-kw-case-mismatch.rs b/tests/ui/parser/item-kw-case-mismatch.rs
index ac8390efdb9..b11ec93754f 100644
--- a/tests/ui/parser/item-kw-case-mismatch.rs
+++ b/tests/ui/parser/item-kw-case-mismatch.rs
@@ -4,31 +4,31 @@
 
 fn main() {}
 
-Use std::ptr::read;  //~ ERROR keyword `use` is written in a wrong case
-USE std::ptr::write; //~ ERROR keyword `use` is written in a wrong case
+Use std::ptr::read;  //~ ERROR keyword `use` is written in the wrong case
+USE std::ptr::write; //~ ERROR keyword `use` is written in the wrong case
 
 async Fn _a() {}
-//~^ ERROR keyword `fn` is written in a wrong case
+//~^ ERROR keyword `fn` is written in the wrong case
 
 Fn _b() {}
-//~^ ERROR keyword `fn` is written in a wrong case
+//~^ ERROR keyword `fn` is written in the wrong case
 
 aSYNC fN _c() {}
-//~^ ERROR keyword `async` is written in a wrong case
-//~| ERROR keyword `fn` is written in a wrong case
+//~^ ERROR keyword `async` is written in the wrong case
+//~| ERROR keyword `fn` is written in the wrong case
 
 Async fn _d() {}
-//~^ ERROR keyword `async` is written in a wrong case
+//~^ ERROR keyword `async` is written in the wrong case
 
 CONST UNSAFE FN _e() {}
-//~^ ERROR keyword `const` is written in a wrong case
-//~| ERROR keyword `unsafe` is written in a wrong case
-//~| ERROR keyword `fn` is written in a wrong case
+//~^ ERROR keyword `const` is written in the wrong case
+//~| ERROR keyword `unsafe` is written in the wrong case
+//~| ERROR keyword `fn` is written in the wrong case
 
 unSAFE EXTern fn _f() {}
-//~^ ERROR keyword `unsafe` is written in a wrong case
-//~| ERROR keyword `extern` is written in a wrong case
+//~^ ERROR keyword `unsafe` is written in the wrong case
+//~| ERROR keyword `extern` is written in the wrong case
 
 EXTERN "C" FN _g() {}
-//~^ ERROR keyword `extern` is written in a wrong case
-//~| ERROR keyword `fn` is written in a wrong case
+//~^ ERROR keyword `extern` is written in the wrong case
+//~| ERROR keyword `fn` is written in the wrong case
diff --git a/tests/ui/parser/item-kw-case-mismatch.stderr b/tests/ui/parser/item-kw-case-mismatch.stderr
index e66dae825f9..ba59ea85363 100644
--- a/tests/ui/parser/item-kw-case-mismatch.stderr
+++ b/tests/ui/parser/item-kw-case-mismatch.stderr
@@ -1,82 +1,82 @@
-error: keyword `use` is written in a wrong case
+error: keyword `use` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:7:1
    |
 LL | Use std::ptr::read;
    | ^^^ help: write it in the correct case (notice the capitalization): `use`
 
-error: keyword `use` is written in a wrong case
+error: keyword `use` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:8:1
    |
 LL | USE std::ptr::write;
    | ^^^ help: write it in the correct case: `use`
 
-error: keyword `fn` is written in a wrong case
+error: keyword `fn` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:10:7
    |
 LL | async Fn _a() {}
    |       ^^ help: write it in the correct case (notice the capitalization): `fn`
 
-error: keyword `fn` is written in a wrong case
+error: keyword `fn` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:13:1
    |
 LL | Fn _b() {}
    | ^^ help: write it in the correct case (notice the capitalization): `fn`
 
-error: keyword `async` is written in a wrong case
+error: keyword `async` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:16:1
    |
 LL | aSYNC fN _c() {}
    | ^^^^^ help: write it in the correct case: `async`
 
-error: keyword `fn` is written in a wrong case
+error: keyword `fn` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:16:7
    |
 LL | aSYNC fN _c() {}
    |       ^^ help: write it in the correct case: `fn`
 
-error: keyword `async` is written in a wrong case
+error: keyword `async` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:20:1
    |
 LL | Async fn _d() {}
    | ^^^^^ help: write it in the correct case: `async`
 
-error: keyword `const` is written in a wrong case
+error: keyword `const` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:23:1
    |
 LL | CONST UNSAFE FN _e() {}
    | ^^^^^ help: write it in the correct case: `const`
 
-error: keyword `unsafe` is written in a wrong case
+error: keyword `unsafe` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:23:7
    |
 LL | CONST UNSAFE FN _e() {}
    |       ^^^^^^ help: write it in the correct case: `unsafe`
 
-error: keyword `fn` is written in a wrong case
+error: keyword `fn` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:23:14
    |
 LL | CONST UNSAFE FN _e() {}
    |              ^^ help: write it in the correct case: `fn`
 
-error: keyword `unsafe` is written in a wrong case
+error: keyword `unsafe` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:28:1
    |
 LL | unSAFE EXTern fn _f() {}
    | ^^^^^^ help: write it in the correct case: `unsafe`
 
-error: keyword `extern` is written in a wrong case
+error: keyword `extern` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:28:8
    |
 LL | unSAFE EXTern fn _f() {}
    |        ^^^^^^ help: write it in the correct case: `extern`
 
-error: keyword `extern` is written in a wrong case
+error: keyword `extern` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:32:1
    |
 LL | EXTERN "C" FN _g() {}
    | ^^^^^^ help: write it in the correct case: `extern`
 
-error: keyword `fn` is written in a wrong case
+error: keyword `fn` is written in the wrong case
   --> $DIR/item-kw-case-mismatch.rs:32:12
    |
 LL | EXTERN "C" FN _g() {}
diff --git a/tests/ui/parser/recover-unticked-labels.stderr b/tests/ui/parser/recover-unticked-labels.stderr
index c115dffb10e..fbd108ca613 100644
--- a/tests/ui/parser/recover-unticked-labels.stderr
+++ b/tests/ui/parser/recover-unticked-labels.stderr
@@ -2,13 +2,17 @@ error: expected a label, found an identifier
   --> $DIR/recover-unticked-labels.rs:5:26
    |
 LL |     'label: loop { break label 0 };
-   |                          ^^^^^ help: labels start with a tick: `'label`
+   |                          -^^^^
+   |                          |
+   |                          help: labels start with a tick
 
 error: expected a label, found an identifier
   --> $DIR/recover-unticked-labels.rs:6:29
    |
 LL |     'label: loop { continue label };
-   |                             ^^^^^ help: labels start with a tick: `'label`
+   |                             -^^^^
+   |                             |
+   |                             help: labels start with a tick
 
 error[E0425]: cannot find value `label` in this scope
   --> $DIR/recover-unticked-labels.rs:4:26
diff --git a/tests/ui/parser/use-colon-as-mod-sep.stderr b/tests/ui/parser/use-colon-as-mod-sep.stderr
index e825dfed111..bfc5374ef9d 100644
--- a/tests/ui/parser/use-colon-as-mod-sep.stderr
+++ b/tests/ui/parser/use-colon-as-mod-sep.stderr
@@ -11,18 +11,24 @@ error: expected `::`, found `:`
    |
 LL | use std:fs::File;
    |        ^ help: use double colon
+   |
+   = note: import paths are delimited using `::`
 
 error: expected `::`, found `:`
   --> $DIR/use-colon-as-mod-sep.rs:7:8
    |
 LL | use std:collections:HashMap;
    |        ^ help: use double colon
+   |
+   = note: import paths are delimited using `::`
 
 error: expected `::`, found `:`
   --> $DIR/use-colon-as-mod-sep.rs:7:20
    |
 LL | use std:collections:HashMap;
    |                    ^ help: use double colon
+   |
+   = note: import paths are delimited using `::`
 
 error: aborting due to 4 previous errors