diff --git a/Cargo.lock b/Cargo.lock
index ef5811c6901d4..c5152a36e12e6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1259,7 +1259,6 @@ name = "error_index_generator"
 version = "0.0.0"
 dependencies = [
  "mdbook",
- "rustc_error_codes",
 ]
 
 [[package]]
@@ -3703,7 +3702,6 @@ dependencies = [
  "rustc_codegen_ssa",
  "rustc_const_eval",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_expand",
  "rustc_feature",
@@ -3776,9 +3774,11 @@ dependencies = [
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_data_structures",
+ "rustc_error_codes",
  "rustc_error_messages",
  "rustc_fluent_macro",
  "rustc_hir",
+ "rustc_index",
  "rustc_lint_defs",
  "rustc_macros",
  "rustc_serialize",
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 4843d36372dcc..51bb8a96fad26 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -1,9 +1,9 @@
-use rustc_errors::DiagnosticArgFromDisplay;
+use rustc_errors::{codes::*, DiagnosticArgFromDisplay};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_generic_type_with_parentheses, code = "E0214")]
+#[diag(ast_lowering_generic_type_with_parentheses, code = E0214)]
 pub struct GenericTypeWithParentheses {
     #[primary_span]
     #[label]
@@ -22,7 +22,7 @@ pub struct UseAngleBrackets {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_lowering_invalid_abi, code = "E0703")]
+#[diag(ast_lowering_invalid_abi, code = E0703)]
 #[note]
 pub struct InvalidAbi {
     #[primary_span]
@@ -89,7 +89,7 @@ pub enum AssocTyParenthesesSub {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_lowering_misplaced_impl_trait, code = "E0562")]
+#[diag(ast_lowering_misplaced_impl_trait, code = E0562)]
 #[note]
 pub struct MisplacedImplTrait<'a> {
     #[primary_span]
@@ -114,7 +114,7 @@ pub struct UnderscoreExprLhsAssign {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_base_expression_double_dot, code = "E0797")]
+#[diag(ast_lowering_base_expression_double_dot, code = E0797)]
 pub struct BaseExpressionDoubleDot {
     #[primary_span]
     #[suggestion(code = "/* expr */", applicability = "has-placeholders", style = "verbose")]
@@ -122,7 +122,7 @@ pub struct BaseExpressionDoubleDot {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = "E0728")]
+#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = E0728)]
 pub struct AwaitOnlyInAsyncFnAndBlocks {
     #[primary_span]
     #[label]
@@ -132,14 +132,14 @@ pub struct AwaitOnlyInAsyncFnAndBlocks {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_coroutine_too_many_parameters, code = "E0628")]
+#[diag(ast_lowering_coroutine_too_many_parameters, code = E0628)]
 pub struct CoroutineTooManyParameters {
     #[primary_span]
     pub fn_decl_span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_closure_cannot_be_static, code = "E0697")]
+#[diag(ast_lowering_closure_cannot_be_static, code = E0697)]
 pub struct ClosureCannotBeStatic {
     #[primary_span]
     pub fn_decl_span: Span,
@@ -154,14 +154,14 @@ pub struct FunctionalRecordUpdateDestructuringAssignment {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_async_coroutines_not_supported, code = "E0727")]
+#[diag(ast_lowering_async_coroutines_not_supported, code = E0727)]
 pub struct AsyncCoroutinesNotSupported {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_inline_asm_unsupported_target, code = "E0472")]
+#[diag(ast_lowering_inline_asm_unsupported_target, code = E0472)]
 pub struct InlineAsmUnsupportedTarget {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index e2b8e64b115e5..5f54a0ddf8c38 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -1,7 +1,7 @@
 //! Errors emitted by ast_passes.
 
 use rustc_ast::ParamKindOrd;
-use rustc_errors::{AddToDiagnostic, Applicability};
+use rustc_errors::{codes::*, AddToDiagnostic, Applicability};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
@@ -23,7 +23,7 @@ pub struct InvalidLabel {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_visibility_not_permitted, code = "E0449")]
+#[diag(ast_passes_visibility_not_permitted, code = E0449)]
 pub struct VisibilityNotPermitted {
     #[primary_span]
     pub span: Span,
@@ -44,7 +44,7 @@ pub enum VisibilityNotPermittedNote {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_trait_fn_const, code = "E0379")]
+#[diag(ast_passes_trait_fn_const, code = E0379)]
 pub struct TraitFnConst {
     #[primary_span]
     #[label]
@@ -302,14 +302,14 @@ pub struct ItemUnderscore<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_nomangle_ascii, code = "E0754")]
+#[diag(ast_passes_nomangle_ascii, code = E0754)]
 pub struct NoMangleAscii {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_module_nonascii, code = "E0754")]
+#[diag(ast_passes_module_nonascii, code = E0754)]
 #[help]
 pub struct ModuleNonAscii {
     #[primary_span]
@@ -318,7 +318,7 @@ pub struct ModuleNonAscii {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_auto_generic, code = "E0567")]
+#[diag(ast_passes_auto_generic, code = E0567)]
 pub struct AutoTraitGeneric {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
@@ -328,7 +328,7 @@ pub struct AutoTraitGeneric {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_auto_super_lifetime, code = "E0568")]
+#[diag(ast_passes_auto_super_lifetime, code = E0568)]
 pub struct AutoTraitBounds {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
@@ -338,7 +338,7 @@ pub struct AutoTraitBounds {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_auto_items, code = "E0380")]
+#[diag(ast_passes_auto_items, code = E0380)]
 pub struct AutoTraitItems {
     #[primary_span]
     pub spans: Vec<Span>,
@@ -384,28 +384,28 @@ impl AddToDiagnostic for EmptyLabelManySpans {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_pattern_in_fn_pointer, code = "E0561")]
+#[diag(ast_passes_pattern_in_fn_pointer, code = E0561)]
 pub struct PatternFnPointer {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_trait_object_single_bound, code = "E0226")]
+#[diag(ast_passes_trait_object_single_bound, code = E0226)]
 pub struct TraitObjectBound {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_impl_trait_path, code = "E0667")]
+#[diag(ast_passes_impl_trait_path, code = E0667)]
 pub struct ImplTraitPath {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_nested_impl_trait, code = "E0666")]
+#[diag(ast_passes_nested_impl_trait, code = E0666)]
 pub struct NestedImplTrait {
     #[primary_span]
     pub span: Span,
@@ -443,7 +443,7 @@ pub struct ObsoleteAuto {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_unsafe_negative_impl, code = "E0198")]
+#[diag(ast_passes_unsafe_negative_impl, code = E0198)]
 pub struct UnsafeNegativeImpl {
     #[primary_span]
     pub span: Span,
@@ -468,7 +468,7 @@ pub struct InherentImplCannot<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_inherent_cannot_be, code = "E0197")]
+#[diag(ast_passes_inherent_cannot_be, code = E0197)]
 pub struct InherentImplCannotUnsafe<'a> {
     #[primary_span]
     pub span: Span,
@@ -536,7 +536,7 @@ pub struct GenericDefaultTrailing {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_nested_lifetimes, code = "E0316")]
+#[diag(ast_passes_nested_lifetimes, code = E0316)]
 pub struct NestedLifetimes {
     #[primary_span]
     pub span: Span,
@@ -655,7 +655,7 @@ pub struct ConstAndCVariadic {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_pattern_in_foreign, code = "E0130")]
+#[diag(ast_passes_pattern_in_foreign, code = E0130)]
 pub struct PatternInForeign {
     #[primary_span]
     #[label]
@@ -663,7 +663,7 @@ pub struct PatternInForeign {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_pattern_in_bodiless, code = "E0642")]
+#[diag(ast_passes_pattern_in_bodiless, code = E0642)]
 pub struct PatternInBodiless {
     #[primary_span]
     #[label]
@@ -711,14 +711,14 @@ pub struct AssociatedSuggestion2 {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_stability_outside_std, code = "E0734")]
+#[diag(ast_passes_stability_outside_std, code = E0734)]
 pub struct StabilityOutsideStd {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_feature_on_non_nightly, code = "E0554")]
+#[diag(ast_passes_feature_on_non_nightly, code = E0554)]
 pub struct FeatureOnNonNightly {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 192e458775a93..82236d2e30678 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -398,7 +398,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     &self,
                     exclusive_range_pattern,
                     pattern.span,
-                    "exclusive range pattern syntax is experimental"
+                    "exclusive range pattern syntax is experimental",
+                    "use an inclusive range pattern, like N..=M"
                 );
             }
             _ => {}
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index 89606b81a9946..2ed5b8de9b8e0 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -2,8 +2,7 @@ use std::num::IntErrorKind;
 
 use rustc_ast as ast;
 use rustc_errors::{
-    error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
-    Level,
+    codes::*, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
 };
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
@@ -12,14 +11,14 @@ use crate::fluent_generated as fluent;
 use crate::UnsupportedLiteralReason;
 
 #[derive(Diagnostic)]
-#[diag(attr_expected_one_cfg_pattern, code = "E0536")]
+#[diag(attr_expected_one_cfg_pattern, code = E0536)]
 pub(crate) struct ExpectedOneCfgPattern {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_predicate, code = "E0537")]
+#[diag(attr_invalid_predicate, code = E0537)]
 pub(crate) struct InvalidPredicate {
     #[primary_span]
     pub span: Span,
@@ -28,7 +27,7 @@ pub(crate) struct InvalidPredicate {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_multiple_item, code = "E0538")]
+#[diag(attr_multiple_item, code = E0538)]
 pub(crate) struct MultipleItem {
     #[primary_span]
     pub span: Span,
@@ -37,7 +36,7 @@ pub(crate) struct MultipleItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_incorrect_meta_item, code = "E0539")]
+#[diag(attr_incorrect_meta_item, code = E0539)]
 pub(crate) struct IncorrectMetaItem {
     #[primary_span]
     pub span: Span,
@@ -56,7 +55,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> {
         let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
         DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item)
             .with_span(self.span)
-            .with_code(error_code!(E0541))
+            .with_code(E0541)
             .with_arg("item", self.item)
             .with_arg("expected", expected.join(", "))
             .with_span_label(self.span, fluent::attr_label)
@@ -64,28 +63,28 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_missing_since, code = "E0542")]
+#[diag(attr_missing_since, code = E0542)]
 pub(crate) struct MissingSince {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_missing_note, code = "E0543")]
+#[diag(attr_missing_note, code = E0543)]
 pub(crate) struct MissingNote {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_multiple_stability_levels, code = "E0544")]
+#[diag(attr_multiple_stability_levels, code = E0544)]
 pub(crate) struct MultipleStabilityLevels {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_issue_string, code = "E0545")]
+#[diag(attr_invalid_issue_string, code = E0545)]
 pub(crate) struct InvalidIssueString {
     #[primary_span]
     pub span: Span,
@@ -143,21 +142,21 @@ impl InvalidIssueStringCause {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_missing_feature, code = "E0546")]
+#[diag(attr_missing_feature, code = E0546)]
 pub(crate) struct MissingFeature {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_non_ident_feature, code = "E0546")]
+#[diag(attr_non_ident_feature, code = E0546)]
 pub(crate) struct NonIdentFeature {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_missing_issue, code = "E0547")]
+#[diag(attr_missing_issue, code = E0547)]
 pub(crate) struct MissingIssue {
     #[primary_span]
     pub span: Span,
@@ -166,14 +165,14 @@ pub(crate) struct MissingIssue {
 // FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
 // It is more similar to `IncorrectReprFormatGeneric`.
 #[derive(Diagnostic)]
-#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
+#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = E0552)]
 pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_repr_hint_no_paren, code = "E0552")]
+#[diag(attr_invalid_repr_hint_no_paren, code = E0552)]
 pub(crate) struct InvalidReprHintNoParen {
     #[primary_span]
     pub span: Span,
@@ -182,7 +181,7 @@ pub(crate) struct InvalidReprHintNoParen {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_repr_hint_no_value, code = "E0552")]
+#[diag(attr_invalid_repr_hint_no_value, code = E0552)]
 pub(crate) struct InvalidReprHintNoValue {
     #[primary_span]
     pub span: Span,
@@ -215,7 +214,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral {
             },
         );
         diag.span(self.span);
-        diag.code(error_code!(E0565));
+        diag.code(E0565);
         if self.is_bytestr {
             diag.span_suggestion(
                 self.start_point_span,
@@ -229,7 +228,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_repr_align_need_arg, code = "E0589")]
+#[diag(attr_invalid_repr_align_need_arg, code = E0589)]
 pub(crate) struct InvalidReprAlignNeedArg {
     #[primary_span]
     #[suggestion(code = "align(...)", applicability = "has-placeholders")]
@@ -237,7 +236,7 @@ pub(crate) struct InvalidReprAlignNeedArg {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_repr_generic, code = "E0589")]
+#[diag(attr_invalid_repr_generic, code = E0589)]
 pub(crate) struct InvalidReprGeneric<'a> {
     #[primary_span]
     pub span: Span,
@@ -247,14 +246,14 @@ pub(crate) struct InvalidReprGeneric<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_incorrect_repr_format_align_one_arg, code = "E0693")]
+#[diag(attr_incorrect_repr_format_align_one_arg, code = E0693)]
 pub(crate) struct IncorrectReprFormatAlignOneArg {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_incorrect_repr_format_generic, code = "E0693")]
+#[diag(attr_incorrect_repr_format_generic, code = E0693)]
 pub(crate) struct IncorrectReprFormatGeneric<'a> {
     #[primary_span]
     pub span: Span,
@@ -305,14 +304,14 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_rustc_promotable_pairing, code = "E0717")]
+#[diag(attr_rustc_promotable_pairing, code = E0717)]
 pub(crate) struct RustcPromotablePairing {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_rustc_allowed_unstable_pairing, code = "E0789")]
+#[diag(attr_rustc_allowed_unstable_pairing, code = E0789)]
 pub(crate) struct RustcAllowedUnstablePairing {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index 351976cdaea6b..8a275a8363010 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -1,4 +1,4 @@
-use rustc_errors::{struct_span_code_err, DiagCtxt, DiagnosticBuilder};
+use rustc_errors::{codes::*, struct_span_code_err, DiagCtxt, DiagnosticBuilder};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index da67862a48dc9..2e83072b8d132 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -3,7 +3,9 @@
 use either::Either;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
+use rustc_errors::{
+    codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan,
+};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index e321b92603d38..1685624f24772 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -1,4 +1,4 @@
-use rustc_errors::MultiSpan;
+use rustc_errors::{codes::*, MultiSpan};
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{GenericArg, Ty};
 use rustc_span::Span;
@@ -6,7 +6,7 @@ use rustc_span::Span;
 use crate::diagnostics::RegionName;
 
 #[derive(Diagnostic)]
-#[diag(borrowck_move_unsized, code = "E0161")]
+#[diag(borrowck_move_unsized, code = E0161)]
 pub(crate) struct MoveUnsized<'tcx> {
     pub ty: Ty<'tcx>,
     #[primary_span]
@@ -281,7 +281,7 @@ pub(crate) enum CaptureVarCause {
 }
 
 #[derive(Diagnostic)]
-#[diag(borrowck_cannot_move_when_borrowed, code = "E0505")]
+#[diag(borrowck_cannot_move_when_borrowed, code = E0505)]
 pub(crate) struct MoveBorrow<'a> {
     pub place: &'a str,
     pub borrow_place: &'a str,
@@ -294,7 +294,7 @@ pub(crate) struct MoveBorrow<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(borrowck_opaque_type_non_generic_param, code = "E0792")]
+#[diag(borrowck_opaque_type_non_generic_param, code = E0792)]
 pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
     pub ty: GenericArg<'tcx>,
     pub kind: &'a str,
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index d6dfd0efaf913..eadb48ddd36d8 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -1,6 +1,6 @@
 use rustc_errors::{
-    AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
-    MultiSpan, SingleLabelManySpans,
+    codes::*, AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
+    Level, MultiSpan, SingleLabelManySpans,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
@@ -269,7 +269,7 @@ pub(crate) struct ConcatIdentsIdentArgs {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_bad_derive_target, code = "E0774")]
+#[diag(builtin_macros_bad_derive_target, code = E0774)]
 pub(crate) struct BadDeriveTarget {
     #[primary_span]
     #[label]
@@ -283,7 +283,7 @@ pub(crate) struct BadDeriveTarget {
 pub(crate) struct TestsNotSupport {}
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_unexpected_lit, code = "E0777")]
+#[diag(builtin_macros_unexpected_lit, code = E0777)]
 pub(crate) struct BadDeriveLit {
     #[primary_span]
     #[label]
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 5d497d4a1883a..b13d566b40b3b 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -15,7 +15,7 @@ use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::Emitter;
 use rustc_errors::{translation::Translate, DiagCtxt, FatalError, Level};
-use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Style};
+use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, ErrCode, Style};
 use rustc_fs_util::link_or_copy;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_incremental::{
@@ -1000,7 +1000,7 @@ type DiagnosticArgName<'source> = Cow<'source, str>;
 struct Diagnostic {
     msgs: Vec<(DiagnosticMessage, Style)>,
     args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>,
-    code: Option<String>,
+    code: Option<ErrCode>,
     lvl: Level,
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 198b7ac417072..4014160dee321 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -1,6 +1,6 @@
 use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
 use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index f90e1906caf0a..ef291ead190cc 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -4,7 +4,7 @@ use crate::assert_module_sources::CguReuse;
 use crate::back::command::Command;
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
+    codes::*, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
     IntoDiagnosticArg, Level,
 };
 use rustc_macros::Diagnostic;
@@ -612,7 +612,7 @@ pub struct UnknownAtomicOperation;
 
 #[derive(Diagnostic)]
 pub enum InvalidMonomorphization<'tcx> {
-    #[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = E0511)]
     BasicIntegerType {
         #[primary_span]
         span: Span,
@@ -620,7 +620,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = E0511)]
     BasicFloatType {
         #[primary_span]
         span: Span,
@@ -628,14 +628,14 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = E0511)]
     FloatToIntUnchecked {
         #[primary_span]
         span: Span,
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = E0511)]
     FloatingPointVector {
         #[primary_span]
         span: Span,
@@ -644,7 +644,7 @@ pub enum InvalidMonomorphization<'tcx> {
         in_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = E0511)]
     FloatingPointType {
         #[primary_span]
         span: Span,
@@ -652,14 +652,14 @@ pub enum InvalidMonomorphization<'tcx> {
         in_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = E0511)]
     UnrecognizedIntrinsic {
         #[primary_span]
         span: Span,
         name: Symbol,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = E0511)]
     SimdArgument {
         #[primary_span]
         span: Span,
@@ -667,7 +667,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_input, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_input, code = E0511)]
     SimdInput {
         #[primary_span]
         span: Span,
@@ -675,7 +675,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_first, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_first, code = E0511)]
     SimdFirst {
         #[primary_span]
         span: Span,
@@ -683,7 +683,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_second, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_second, code = E0511)]
     SimdSecond {
         #[primary_span]
         span: Span,
@@ -691,7 +691,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_third, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_third, code = E0511)]
     SimdThird {
         #[primary_span]
         span: Span,
@@ -699,7 +699,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_return, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_return, code = E0511)]
     SimdReturn {
         #[primary_span]
         span: Span,
@@ -707,7 +707,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = E0511)]
     InvalidBitmask {
         #[primary_span]
         span: Span,
@@ -717,7 +717,7 @@ pub enum InvalidMonomorphization<'tcx> {
         expected_bytes: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = E0511)]
     ReturnLengthInputType {
         #[primary_span]
         span: Span,
@@ -728,7 +728,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_len: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = E0511)]
     SecondArgumentLength {
         #[primary_span]
         span: Span,
@@ -739,7 +739,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_len: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = E0511)]
     ThirdArgumentLength {
         #[primary_span]
         span: Span,
@@ -750,7 +750,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_len: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = E0511)]
     ReturnIntegerType {
         #[primary_span]
         span: Span,
@@ -759,7 +759,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = E0511)]
     SimdShuffle {
         #[primary_span]
         span: Span,
@@ -767,7 +767,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_return_length, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_return_length, code = E0511)]
     ReturnLength {
         #[primary_span]
         span: Span,
@@ -777,7 +777,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_len: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_return_element, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_return_element, code = E0511)]
     ReturnElement {
         #[primary_span]
         span: Span,
@@ -788,7 +788,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = E0511)]
     ShuffleIndexNotConstant {
         #[primary_span]
         span: Span,
@@ -796,7 +796,7 @@ pub enum InvalidMonomorphization<'tcx> {
         arg_idx: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = E0511)]
     ShuffleIndexOutOfBounds {
         #[primary_span]
         span: Span,
@@ -805,7 +805,7 @@ pub enum InvalidMonomorphization<'tcx> {
         total_len: u128,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = E0511)]
     InsertedType {
         #[primary_span]
         span: Span,
@@ -815,7 +815,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_return_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_return_type, code = E0511)]
     ReturnType {
         #[primary_span]
         span: Span,
@@ -825,7 +825,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ret_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = E0511)]
     ExpectedReturnType {
         #[primary_span]
         span: Span,
@@ -834,7 +834,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ret_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = E0511)]
     MismatchedLengths {
         #[primary_span]
         span: Span,
@@ -843,7 +843,7 @@ pub enum InvalidMonomorphization<'tcx> {
         v_len: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_mask_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_mask_type, code = E0511)]
     MaskType {
         #[primary_span]
         span: Span,
@@ -851,7 +851,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_vector_argument, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_vector_argument, code = E0511)]
     VectorArgument {
         #[primary_span]
         span: Span,
@@ -860,7 +860,7 @@ pub enum InvalidMonomorphization<'tcx> {
         in_elem: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = E0511)]
     CannotReturn {
         #[primary_span]
         span: Span,
@@ -870,7 +870,7 @@ pub enum InvalidMonomorphization<'tcx> {
         expected_bytes: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = E0511)]
     ExpectedElementType {
         #[primary_span]
         span: Span,
@@ -882,7 +882,7 @@ pub enum InvalidMonomorphization<'tcx> {
         mutability: ExpectedPointerMutability,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_third_arg_element_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_third_arg_element_type, code = E0511)]
     ThirdArgElementType {
         #[primary_span]
         span: Span,
@@ -891,7 +891,7 @@ pub enum InvalidMonomorphization<'tcx> {
         third_arg: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = E0511)]
     UnsupportedSymbolOfSize {
         #[primary_span]
         span: Span,
@@ -903,7 +903,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ret_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = E0511)]
     UnsupportedSymbol {
         #[primary_span]
         span: Span,
@@ -914,7 +914,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ret_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = E0511)]
     CastFatPointer {
         #[primary_span]
         span: Span,
@@ -922,7 +922,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = E0511)]
     ExpectedPointer {
         #[primary_span]
         span: Span,
@@ -930,7 +930,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = E0511)]
     ExpectedUsize {
         #[primary_span]
         span: Span,
@@ -938,7 +938,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = E0511)]
     UnsupportedCast {
         #[primary_span]
         span: Span,
@@ -949,7 +949,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_elem: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = E0511)]
     UnsupportedOperation {
         #[primary_span]
         span: Span,
@@ -958,7 +958,7 @@ pub enum InvalidMonomorphization<'tcx> {
         in_elem: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = E0511)]
     ExpectedVectorElementType {
         #[primary_span]
         span: Span,
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 171cc89d6adb8..83ef2e49ddb1b 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -1,6 +1,6 @@
 use rustc_errors::{
-    DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee,
-    IntoDiagnostic, Level,
+    codes::*, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage,
+    EmissionGuarantee, IntoDiagnostic, Level,
 };
 use rustc_hir::ConstContext;
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -41,14 +41,14 @@ pub(crate) struct UnstableInStable {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_thread_local_access, code = "E0625")]
+#[diag(const_eval_thread_local_access, code = E0625)]
 pub(crate) struct NonConstOpErr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_static_access, code = "E0013")]
+#[diag(const_eval_static_access, code = E0013)]
 #[help]
 pub(crate) struct StaticAccessErr {
     #[primary_span]
@@ -84,7 +84,7 @@ pub(crate) struct PanicNonStrErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_mut_deref, code = "E0658")]
+#[diag(const_eval_mut_deref, code = E0658)]
 pub(crate) struct MutDerefErr {
     #[primary_span]
     pub span: Span,
@@ -92,7 +92,7 @@ pub(crate) struct MutDerefErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_transient_mut_borrow, code = "E0658")]
+#[diag(const_eval_transient_mut_borrow, code = E0658)]
 pub(crate) struct TransientMutBorrowErr {
     #[primary_span]
     pub span: Span,
@@ -100,7 +100,7 @@ pub(crate) struct TransientMutBorrowErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_transient_mut_borrow_raw, code = "E0658")]
+#[diag(const_eval_transient_mut_borrow_raw, code = E0658)]
 pub(crate) struct TransientMutBorrowErrRaw {
     #[primary_span]
     pub span: Span,
@@ -132,7 +132,7 @@ pub(crate) struct UnstableConstFn {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_unallowed_mutable_refs, code = "E0764")]
+#[diag(const_eval_unallowed_mutable_refs, code = E0764)]
 pub(crate) struct UnallowedMutableRefs {
     #[primary_span]
     pub span: Span,
@@ -142,7 +142,7 @@ pub(crate) struct UnallowedMutableRefs {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_unallowed_mutable_refs_raw, code = "E0764")]
+#[diag(const_eval_unallowed_mutable_refs_raw, code = E0764)]
 pub(crate) struct UnallowedMutableRefsRaw {
     #[primary_span]
     pub span: Span,
@@ -151,7 +151,7 @@ pub(crate) struct UnallowedMutableRefsRaw {
     pub teach: Option<()>,
 }
 #[derive(Diagnostic)]
-#[diag(const_eval_non_const_fmt_macro_call, code = "E0015")]
+#[diag(const_eval_non_const_fmt_macro_call, code = E0015)]
 pub(crate) struct NonConstFmtMacroCall {
     #[primary_span]
     pub span: Span,
@@ -159,7 +159,7 @@ pub(crate) struct NonConstFmtMacroCall {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_non_const_fn_call, code = "E0015")]
+#[diag(const_eval_non_const_fn_call, code = E0015)]
 pub(crate) struct NonConstFnCall {
     #[primary_span]
     pub span: Span,
@@ -176,7 +176,7 @@ pub(crate) struct UnallowedOpInConstContext {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_unallowed_heap_allocations, code = "E0010")]
+#[diag(const_eval_unallowed_heap_allocations, code = E0010)]
 pub(crate) struct UnallowedHeapAllocations {
     #[primary_span]
     #[label]
@@ -187,7 +187,7 @@ pub(crate) struct UnallowedHeapAllocations {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_unallowed_inline_asm, code = "E0015")]
+#[diag(const_eval_unallowed_inline_asm, code = E0015)]
 pub(crate) struct UnallowedInlineAsm {
     #[primary_span]
     pub span: Span,
@@ -203,7 +203,7 @@ pub(crate) struct UnsupportedUntypedPointer {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_interior_mutable_data_refer, code = "E0492")]
+#[diag(const_eval_interior_mutable_data_refer, code = E0492)]
 pub(crate) struct InteriorMutableDataRefer {
     #[primary_span]
     #[label]
@@ -268,7 +268,7 @@ pub struct RawBytesNote {
 // FIXME(fee1-dead) do not use stringly typed `ConstContext`
 
 #[derive(Diagnostic)]
-#[diag(const_eval_match_eq_non_const, code = "E0015")]
+#[diag(const_eval_match_eq_non_const, code = E0015)]
 #[note]
 pub struct NonConstMatchEq<'tcx> {
     #[primary_span]
@@ -278,7 +278,7 @@ pub struct NonConstMatchEq<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_for_loop_into_iter_non_const, code = "E0015")]
+#[diag(const_eval_for_loop_into_iter_non_const, code = E0015)]
 pub struct NonConstForLoopIntoIter<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -287,7 +287,7 @@ pub struct NonConstForLoopIntoIter<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_question_branch_non_const, code = "E0015")]
+#[diag(const_eval_question_branch_non_const, code = E0015)]
 pub struct NonConstQuestionBranch<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -296,7 +296,7 @@ pub struct NonConstQuestionBranch<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_question_from_residual_non_const, code = "E0015")]
+#[diag(const_eval_question_from_residual_non_const, code = E0015)]
 pub struct NonConstQuestionFromResidual<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -305,7 +305,7 @@ pub struct NonConstQuestionFromResidual<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_try_block_from_output_non_const, code = "E0015")]
+#[diag(const_eval_try_block_from_output_non_const, code = E0015)]
 pub struct NonConstTryBlockFromOutput<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -314,7 +314,7 @@ pub struct NonConstTryBlockFromOutput<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_await_non_const, code = "E0015")]
+#[diag(const_eval_await_non_const, code = E0015)]
 pub struct NonConstAwait<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -323,7 +323,7 @@ pub struct NonConstAwait<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_closure_non_const, code = "E0015")]
+#[diag(const_eval_closure_non_const, code = E0015)]
 pub struct NonConstClosure {
     #[primary_span]
     pub span: Span,
@@ -356,7 +356,7 @@ pub struct ConsiderDereferencing {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_operator_non_const, code = "E0015")]
+#[diag(const_eval_operator_non_const, code = E0015)]
 pub struct NonConstOperator {
     #[primary_span]
     pub span: Span,
@@ -366,7 +366,7 @@ pub struct NonConstOperator {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_deref_coercion_non_const, code = "E0015")]
+#[diag(const_eval_deref_coercion_non_const, code = E0015)]
 #[note]
 pub struct NonConstDerefCoercion<'tcx> {
     #[primary_span]
@@ -379,7 +379,7 @@ pub struct NonConstDerefCoercion<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_live_drop, code = "E0493")]
+#[diag(const_eval_live_drop, code = E0493)]
 pub struct LiveDrop<'tcx> {
     #[primary_span]
     #[label]
@@ -391,7 +391,7 @@ pub struct LiveDrop<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_error, code = "E0080")]
+#[diag(const_eval_error, code = E0080)]
 pub struct ConstEvalError {
     #[primary_span]
     pub span: Span,
@@ -417,7 +417,7 @@ pub struct NullaryIntrinsicError {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_undefined_behavior, code = "E0080")]
+#[diag(const_eval_undefined_behavior, code = E0080)]
 pub struct UndefinedBehavior {
     #[primary_span]
     pub span: Span,
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 327c91731bf58..38eb19782621b 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -2,7 +2,7 @@
 
 use hir::def_id::LocalDefId;
 use hir::{ConstContext, LangItem};
-use rustc_errors::{error_code, DiagnosticBuilder};
+use rustc_errors::{codes::*, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
@@ -372,7 +372,7 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
         ccx.dcx().create_err(errors::UnallowedHeapAllocations {
             span,
             kind: ccx.const_kind(),
-            teach: ccx.tcx.sess.teach(&error_code!(E0010)).then_some(()),
+            teach: ccx.tcx.sess.teach(E0010).then_some(()),
         })
     }
 }
@@ -434,14 +434,14 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow {
                 span,
                 opt_help: Some(()),
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
+                teach: ccx.tcx.sess.teach(E0492).then_some(()),
             })
         } else {
             ccx.dcx().create_err(errors::InteriorMutableDataRefer {
                 span,
                 opt_help: None,
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
+                teach: ccx.tcx.sess.teach(E0492).then_some(()),
             })
         }
     }
@@ -469,12 +469,12 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow {
             hir::BorrowKind::Raw => ccx.dcx().create_err(errors::UnallowedMutableRefsRaw {
                 span,
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
+                teach: ccx.tcx.sess.teach(E0764).then_some(()),
             }),
             hir::BorrowKind::Ref => ccx.dcx().create_err(errors::UnallowedMutableRefs {
                 span,
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
+                teach: ccx.tcx.sess.teach(E0764).then_some(()),
             }),
         }
     }
@@ -588,7 +588,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
         ccx.dcx().create_err(errors::StaticAccessErr {
             span,
             kind: ccx.const_kind(),
-            teach: ccx.tcx.sess.teach(&error_code!(E0013)).then_some(()),
+            teach: ccx.tcx.sess.teach(E0013).then_some(()),
         })
     }
 }
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index 97a7dfef3b395..bfdd871455c94 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -15,7 +15,6 @@ rustc_builtin_macros = { path = "../rustc_builtin_macros" }
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 rustc_const_eval = { path = "../rustc_const_eval" }
 rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_error_codes = { path = "../rustc_error_codes" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_expand = { path = "../rustc_expand" }
 rustc_feature = { path = "../rustc_feature" }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 11dcf4108d4ec..383d5857a75ff 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -25,9 +25,8 @@ use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
 use rustc_data_structures::profiling::{
     get_resident_set_size, print_time_passes_entry, TimePassesFormat,
 };
-use rustc_errors::registry::{InvalidErrorCode, Registry};
-use rustc_errors::{markdown, ColorConfig};
-use rustc_errors::{DiagCtxt, ErrorGuaranteed, PResult};
+use rustc_errors::registry::Registry;
+use rustc_errors::{markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, PResult};
 use rustc_feature::find_gated_cfg;
 use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
 use rustc_interface::{interface, Queries};
@@ -209,7 +208,7 @@ impl Callbacks for TimePassesCallbacks {
 }
 
 pub fn diagnostics_registry() -> Registry {
-    Registry::new(rustc_error_codes::DIAGNOSTICS)
+    Registry::new(rustc_errors::codes::DIAGNOSTICS)
 }
 
 /// This is the primary entry point for rustc.
@@ -537,37 +536,36 @@ pub enum Compilation {
 }
 
 fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, color: ColorConfig) {
+    // Allow "E0123" or "0123" form.
     let upper_cased_code = code.to_ascii_uppercase();
-    let normalised =
-        if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
-    match registry.try_find_description(&normalised) {
-        Ok(description) => {
-            let mut is_in_code_block = false;
-            let mut text = String::new();
-            // Slice off the leading newline and print.
-            for line in description.lines() {
-                let indent_level =
-                    line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len());
-                let dedented_line = &line[indent_level..];
-                if dedented_line.starts_with("```") {
-                    is_in_code_block = !is_in_code_block;
-                    text.push_str(&line[..(indent_level + 3)]);
-                } else if is_in_code_block && dedented_line.starts_with("# ") {
-                    continue;
-                } else {
-                    text.push_str(line);
-                }
-                text.push('\n');
-            }
-            if io::stdout().is_terminal() {
-                show_md_content_with_pager(&text, color);
+    let start = if upper_cased_code.starts_with('E') { 1 } else { 0 };
+    if let Ok(code) = upper_cased_code[start..].parse::<u32>()
+        && let Ok(description) = registry.try_find_description(ErrCode::from_u32(code))
+    {
+        let mut is_in_code_block = false;
+        let mut text = String::new();
+        // Slice off the leading newline and print.
+        for line in description.lines() {
+            let indent_level =
+                line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len());
+            let dedented_line = &line[indent_level..];
+            if dedented_line.starts_with("```") {
+                is_in_code_block = !is_in_code_block;
+                text.push_str(&line[..(indent_level + 3)]);
+            } else if is_in_code_block && dedented_line.starts_with("# ") {
+                continue;
             } else {
-                safe_print!("{text}");
+                text.push_str(line);
             }
+            text.push('\n');
         }
-        Err(InvalidErrorCode) => {
-            early_dcx.early_fatal(format!("{code} is not a valid error code"));
+        if io::stdout().is_terminal() {
+            show_md_content_with_pager(&text, color);
+        } else {
+            safe_print!("{text}");
         }
+    } else {
+        early_dcx.early_fatal(format!("{code} is not a valid error code"));
     }
 }
 
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
deleted file mode 100644
index 9cd9ed54d4146..0000000000000
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ /dev/null
@@ -1,658 +0,0 @@
-// Error messages for EXXXX errors. Each message should start and end with a
-// new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and
-// use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
-//
-// /!\ IMPORTANT /!\
-//
-// Error messages' format must follow the RFC 1567 available here:
-// https://rust-lang.github.io/rfcs/1567-long-error-codes-explanation-normalization.html
-
-register_diagnostics! {
-E0001: include_str!("./error_codes/E0001.md"),
-E0002: include_str!("./error_codes/E0002.md"),
-E0004: include_str!("./error_codes/E0004.md"),
-E0005: include_str!("./error_codes/E0005.md"),
-E0007: include_str!("./error_codes/E0007.md"),
-E0009: include_str!("./error_codes/E0009.md"),
-E0010: include_str!("./error_codes/E0010.md"),
-E0013: include_str!("./error_codes/E0013.md"),
-E0014: include_str!("./error_codes/E0014.md"),
-E0015: include_str!("./error_codes/E0015.md"),
-E0023: include_str!("./error_codes/E0023.md"),
-E0025: include_str!("./error_codes/E0025.md"),
-E0026: include_str!("./error_codes/E0026.md"),
-E0027: include_str!("./error_codes/E0027.md"),
-E0029: include_str!("./error_codes/E0029.md"),
-E0030: include_str!("./error_codes/E0030.md"),
-E0033: include_str!("./error_codes/E0033.md"),
-E0034: include_str!("./error_codes/E0034.md"),
-E0038: include_str!("./error_codes/E0038.md"),
-E0040: include_str!("./error_codes/E0040.md"),
-E0044: include_str!("./error_codes/E0044.md"),
-E0045: include_str!("./error_codes/E0045.md"),
-E0046: include_str!("./error_codes/E0046.md"),
-E0049: include_str!("./error_codes/E0049.md"),
-E0050: include_str!("./error_codes/E0050.md"),
-E0053: include_str!("./error_codes/E0053.md"),
-E0054: include_str!("./error_codes/E0054.md"),
-E0055: include_str!("./error_codes/E0055.md"),
-E0057: include_str!("./error_codes/E0057.md"),
-E0059: include_str!("./error_codes/E0059.md"),
-E0060: include_str!("./error_codes/E0060.md"),
-E0061: include_str!("./error_codes/E0061.md"),
-E0062: include_str!("./error_codes/E0062.md"),
-E0063: include_str!("./error_codes/E0063.md"),
-E0067: include_str!("./error_codes/E0067.md"),
-E0069: include_str!("./error_codes/E0069.md"),
-E0070: include_str!("./error_codes/E0070.md"),
-E0071: include_str!("./error_codes/E0071.md"),
-E0072: include_str!("./error_codes/E0072.md"),
-E0073: include_str!("./error_codes/E0073.md"),
-E0074: include_str!("./error_codes/E0074.md"),
-E0075: include_str!("./error_codes/E0075.md"),
-E0076: include_str!("./error_codes/E0076.md"),
-E0077: include_str!("./error_codes/E0077.md"),
-E0080: include_str!("./error_codes/E0080.md"),
-E0081: include_str!("./error_codes/E0081.md"),
-E0084: include_str!("./error_codes/E0084.md"),
-E0087: include_str!("./error_codes/E0087.md"),
-E0088: include_str!("./error_codes/E0088.md"),
-E0089: include_str!("./error_codes/E0089.md"),
-E0090: include_str!("./error_codes/E0090.md"),
-E0091: include_str!("./error_codes/E0091.md"),
-E0092: include_str!("./error_codes/E0092.md"),
-E0093: include_str!("./error_codes/E0093.md"),
-E0094: include_str!("./error_codes/E0094.md"),
-E0106: include_str!("./error_codes/E0106.md"),
-E0107: include_str!("./error_codes/E0107.md"),
-E0109: include_str!("./error_codes/E0109.md"),
-E0110: include_str!("./error_codes/E0110.md"),
-E0116: include_str!("./error_codes/E0116.md"),
-E0117: include_str!("./error_codes/E0117.md"),
-E0118: include_str!("./error_codes/E0118.md"),
-E0119: include_str!("./error_codes/E0119.md"),
-E0120: include_str!("./error_codes/E0120.md"),
-E0121: include_str!("./error_codes/E0121.md"),
-E0124: include_str!("./error_codes/E0124.md"),
-E0128: include_str!("./error_codes/E0128.md"),
-E0130: include_str!("./error_codes/E0130.md"),
-E0131: include_str!("./error_codes/E0131.md"),
-E0132: include_str!("./error_codes/E0132.md"),
-E0133: include_str!("./error_codes/E0133.md"),
-E0136: include_str!("./error_codes/E0136.md"),
-E0137: include_str!("./error_codes/E0137.md"),
-E0138: include_str!("./error_codes/E0138.md"),
-E0139: include_str!("./error_codes/E0139.md"),
-E0152: include_str!("./error_codes/E0152.md"),
-E0154: include_str!("./error_codes/E0154.md"),
-E0158: include_str!("./error_codes/E0158.md"),
-E0161: include_str!("./error_codes/E0161.md"),
-E0162: include_str!("./error_codes/E0162.md"),
-E0164: include_str!("./error_codes/E0164.md"),
-E0165: include_str!("./error_codes/E0165.md"),
-E0170: include_str!("./error_codes/E0170.md"),
-E0178: include_str!("./error_codes/E0178.md"),
-E0183: include_str!("./error_codes/E0183.md"),
-E0184: include_str!("./error_codes/E0184.md"),
-E0185: include_str!("./error_codes/E0185.md"),
-E0186: include_str!("./error_codes/E0186.md"),
-E0191: include_str!("./error_codes/E0191.md"),
-E0192: include_str!("./error_codes/E0192.md"),
-E0193: include_str!("./error_codes/E0193.md"),
-E0195: include_str!("./error_codes/E0195.md"),
-E0197: include_str!("./error_codes/E0197.md"),
-E0198: include_str!("./error_codes/E0198.md"),
-E0199: include_str!("./error_codes/E0199.md"),
-E0200: include_str!("./error_codes/E0200.md"),
-E0201: include_str!("./error_codes/E0201.md"),
-E0203: include_str!("./error_codes/E0203.md"),
-E0204: include_str!("./error_codes/E0204.md"),
-E0205: include_str!("./error_codes/E0205.md"),
-E0206: include_str!("./error_codes/E0206.md"),
-E0207: include_str!("./error_codes/E0207.md"),
-E0208: include_str!("./error_codes/E0208.md"),
-E0210: include_str!("./error_codes/E0210.md"),
-E0211: include_str!("./error_codes/E0211.md"),
-E0212: include_str!("./error_codes/E0212.md"),
-E0214: include_str!("./error_codes/E0214.md"),
-E0220: include_str!("./error_codes/E0220.md"),
-E0221: include_str!("./error_codes/E0221.md"),
-E0222: include_str!("./error_codes/E0222.md"),
-E0223: include_str!("./error_codes/E0223.md"),
-E0224: include_str!("./error_codes/E0224.md"),
-E0225: include_str!("./error_codes/E0225.md"),
-E0226: include_str!("./error_codes/E0226.md"),
-E0227: include_str!("./error_codes/E0227.md"),
-E0228: include_str!("./error_codes/E0228.md"),
-E0229: include_str!("./error_codes/E0229.md"),
-E0230: include_str!("./error_codes/E0230.md"),
-E0231: include_str!("./error_codes/E0231.md"),
-E0232: include_str!("./error_codes/E0232.md"),
-E0243: include_str!("./error_codes/E0243.md"),
-E0244: include_str!("./error_codes/E0244.md"),
-E0251: include_str!("./error_codes/E0251.md"),
-E0252: include_str!("./error_codes/E0252.md"),
-E0253: include_str!("./error_codes/E0253.md"),
-E0254: include_str!("./error_codes/E0254.md"),
-E0255: include_str!("./error_codes/E0255.md"),
-E0256: include_str!("./error_codes/E0256.md"),
-E0259: include_str!("./error_codes/E0259.md"),
-E0260: include_str!("./error_codes/E0260.md"),
-E0261: include_str!("./error_codes/E0261.md"),
-E0262: include_str!("./error_codes/E0262.md"),
-E0263: include_str!("./error_codes/E0263.md"),
-E0264: include_str!("./error_codes/E0264.md"),
-E0267: include_str!("./error_codes/E0267.md"),
-E0268: include_str!("./error_codes/E0268.md"),
-E0271: include_str!("./error_codes/E0271.md"),
-E0275: include_str!("./error_codes/E0275.md"),
-E0276: include_str!("./error_codes/E0276.md"),
-E0277: include_str!("./error_codes/E0277.md"),
-E0281: include_str!("./error_codes/E0281.md"),
-E0282: include_str!("./error_codes/E0282.md"),
-E0283: include_str!("./error_codes/E0283.md"),
-E0284: include_str!("./error_codes/E0284.md"),
-E0297: include_str!("./error_codes/E0297.md"),
-E0301: include_str!("./error_codes/E0301.md"),
-E0302: include_str!("./error_codes/E0302.md"),
-E0303: include_str!("./error_codes/E0303.md"),
-E0307: include_str!("./error_codes/E0307.md"),
-E0308: include_str!("./error_codes/E0308.md"),
-E0309: include_str!("./error_codes/E0309.md"),
-E0310: include_str!("./error_codes/E0310.md"),
-E0311: include_str!("./error_codes/E0311.md"),
-E0312: include_str!("./error_codes/E0312.md"),
-E0316: include_str!("./error_codes/E0316.md"),
-E0317: include_str!("./error_codes/E0317.md"),
-E0320: include_str!("./error_codes/E0320.md"),
-E0321: include_str!("./error_codes/E0321.md"),
-E0322: include_str!("./error_codes/E0322.md"),
-E0323: include_str!("./error_codes/E0323.md"),
-E0324: include_str!("./error_codes/E0324.md"),
-E0325: include_str!("./error_codes/E0325.md"),
-E0326: include_str!("./error_codes/E0326.md"),
-E0328: include_str!("./error_codes/E0328.md"),
-E0329: include_str!("./error_codes/E0329.md"),
-E0364: include_str!("./error_codes/E0364.md"),
-E0365: include_str!("./error_codes/E0365.md"),
-E0366: include_str!("./error_codes/E0366.md"),
-E0367: include_str!("./error_codes/E0367.md"),
-E0368: include_str!("./error_codes/E0368.md"),
-E0369: include_str!("./error_codes/E0369.md"),
-E0370: include_str!("./error_codes/E0370.md"),
-E0371: include_str!("./error_codes/E0371.md"),
-E0373: include_str!("./error_codes/E0373.md"),
-E0374: include_str!("./error_codes/E0374.md"),
-E0375: include_str!("./error_codes/E0375.md"),
-E0376: include_str!("./error_codes/E0376.md"),
-E0377: include_str!("./error_codes/E0377.md"),
-E0378: include_str!("./error_codes/E0378.md"),
-E0379: include_str!("./error_codes/E0379.md"),
-E0380: include_str!("./error_codes/E0380.md"),
-E0381: include_str!("./error_codes/E0381.md"),
-E0382: include_str!("./error_codes/E0382.md"),
-E0383: include_str!("./error_codes/E0383.md"),
-E0384: include_str!("./error_codes/E0384.md"),
-E0386: include_str!("./error_codes/E0386.md"),
-E0387: include_str!("./error_codes/E0387.md"),
-E0388: include_str!("./error_codes/E0388.md"),
-E0389: include_str!("./error_codes/E0389.md"),
-E0390: include_str!("./error_codes/E0390.md"),
-E0391: include_str!("./error_codes/E0391.md"),
-E0392: include_str!("./error_codes/E0392.md"),
-E0393: include_str!("./error_codes/E0393.md"),
-E0398: include_str!("./error_codes/E0398.md"),
-E0399: include_str!("./error_codes/E0399.md"),
-E0401: include_str!("./error_codes/E0401.md"),
-E0403: include_str!("./error_codes/E0403.md"),
-E0404: include_str!("./error_codes/E0404.md"),
-E0405: include_str!("./error_codes/E0405.md"),
-E0407: include_str!("./error_codes/E0407.md"),
-E0408: include_str!("./error_codes/E0408.md"),
-E0409: include_str!("./error_codes/E0409.md"),
-E0411: include_str!("./error_codes/E0411.md"),
-E0412: include_str!("./error_codes/E0412.md"),
-E0415: include_str!("./error_codes/E0415.md"),
-E0416: include_str!("./error_codes/E0416.md"),
-E0422: include_str!("./error_codes/E0422.md"),
-E0423: include_str!("./error_codes/E0423.md"),
-E0424: include_str!("./error_codes/E0424.md"),
-E0425: include_str!("./error_codes/E0425.md"),
-E0426: include_str!("./error_codes/E0426.md"),
-E0428: include_str!("./error_codes/E0428.md"),
-E0429: include_str!("./error_codes/E0429.md"),
-E0430: include_str!("./error_codes/E0430.md"),
-E0431: include_str!("./error_codes/E0431.md"),
-E0432: include_str!("./error_codes/E0432.md"),
-E0433: include_str!("./error_codes/E0433.md"),
-E0434: include_str!("./error_codes/E0434.md"),
-E0435: include_str!("./error_codes/E0435.md"),
-E0436: include_str!("./error_codes/E0436.md"),
-E0437: include_str!("./error_codes/E0437.md"),
-E0438: include_str!("./error_codes/E0438.md"),
-E0439: include_str!("./error_codes/E0439.md"),
-E0445: include_str!("./error_codes/E0445.md"),
-E0446: include_str!("./error_codes/E0446.md"),
-E0447: include_str!("./error_codes/E0447.md"),
-E0448: include_str!("./error_codes/E0448.md"),
-E0449: include_str!("./error_codes/E0449.md"),
-E0451: include_str!("./error_codes/E0451.md"),
-E0452: include_str!("./error_codes/E0452.md"),
-E0453: include_str!("./error_codes/E0453.md"),
-E0454: include_str!("./error_codes/E0454.md"),
-E0455: include_str!("./error_codes/E0455.md"),
-E0457: include_str!("./error_codes/E0457.md"),
-E0458: include_str!("./error_codes/E0458.md"),
-E0459: include_str!("./error_codes/E0459.md"),
-E0460: include_str!("./error_codes/E0460.md"),
-E0461: include_str!("./error_codes/E0461.md"),
-E0462: include_str!("./error_codes/E0462.md"),
-E0463: include_str!("./error_codes/E0463.md"),
-E0464: include_str!("./error_codes/E0464.md"),
-E0466: include_str!("./error_codes/E0466.md"),
-E0468: include_str!("./error_codes/E0468.md"),
-E0469: include_str!("./error_codes/E0469.md"),
-E0472: include_str!("./error_codes/E0472.md"),
-E0476: include_str!("./error_codes/E0476.md"),
-E0477: include_str!("./error_codes/E0477.md"),
-E0478: include_str!("./error_codes/E0478.md"),
-E0482: include_str!("./error_codes/E0482.md"),
-E0491: include_str!("./error_codes/E0491.md"),
-E0492: include_str!("./error_codes/E0492.md"),
-E0493: include_str!("./error_codes/E0493.md"),
-E0495: include_str!("./error_codes/E0495.md"),
-E0496: include_str!("./error_codes/E0496.md"),
-E0497: include_str!("./error_codes/E0497.md"),
-E0498: include_str!("./error_codes/E0498.md"),
-E0499: include_str!("./error_codes/E0499.md"),
-E0500: include_str!("./error_codes/E0500.md"),
-E0501: include_str!("./error_codes/E0501.md"),
-E0502: include_str!("./error_codes/E0502.md"),
-E0503: include_str!("./error_codes/E0503.md"),
-E0504: include_str!("./error_codes/E0504.md"),
-E0505: include_str!("./error_codes/E0505.md"),
-E0506: include_str!("./error_codes/E0506.md"),
-E0507: include_str!("./error_codes/E0507.md"),
-E0508: include_str!("./error_codes/E0508.md"),
-E0509: include_str!("./error_codes/E0509.md"),
-E0510: include_str!("./error_codes/E0510.md"),
-E0511: include_str!("./error_codes/E0511.md"),
-E0512: include_str!("./error_codes/E0512.md"),
-E0514: include_str!("./error_codes/E0514.md"),
-E0515: include_str!("./error_codes/E0515.md"),
-E0516: include_str!("./error_codes/E0516.md"),
-E0517: include_str!("./error_codes/E0517.md"),
-E0518: include_str!("./error_codes/E0518.md"),
-E0519: include_str!("./error_codes/E0519.md"),
-E0520: include_str!("./error_codes/E0520.md"),
-E0521: include_str!("./error_codes/E0521.md"),
-E0522: include_str!("./error_codes/E0522.md"),
-E0523: include_str!("./error_codes/E0523.md"),
-E0524: include_str!("./error_codes/E0524.md"),
-E0525: include_str!("./error_codes/E0525.md"),
-E0527: include_str!("./error_codes/E0527.md"),
-E0528: include_str!("./error_codes/E0528.md"),
-E0529: include_str!("./error_codes/E0529.md"),
-E0530: include_str!("./error_codes/E0530.md"),
-E0531: include_str!("./error_codes/E0531.md"),
-E0532: include_str!("./error_codes/E0532.md"),
-E0533: include_str!("./error_codes/E0533.md"),
-E0534: include_str!("./error_codes/E0534.md"),
-E0535: include_str!("./error_codes/E0535.md"),
-E0536: include_str!("./error_codes/E0536.md"),
-E0537: include_str!("./error_codes/E0537.md"),
-E0538: include_str!("./error_codes/E0538.md"),
-E0539: include_str!("./error_codes/E0539.md"),
-E0541: include_str!("./error_codes/E0541.md"),
-E0542: include_str!("./error_codes/E0542.md"),
-E0543: include_str!("./error_codes/E0543.md"),
-E0544: include_str!("./error_codes/E0544.md"),
-E0545: include_str!("./error_codes/E0545.md"),
-E0546: include_str!("./error_codes/E0546.md"),
-E0547: include_str!("./error_codes/E0547.md"),
-E0549: include_str!("./error_codes/E0549.md"),
-E0550: include_str!("./error_codes/E0550.md"),
-E0551: include_str!("./error_codes/E0551.md"),
-E0552: include_str!("./error_codes/E0552.md"),
-E0554: include_str!("./error_codes/E0554.md"),
-E0556: include_str!("./error_codes/E0556.md"),
-E0557: include_str!("./error_codes/E0557.md"),
-E0559: include_str!("./error_codes/E0559.md"),
-E0560: include_str!("./error_codes/E0560.md"),
-E0561: include_str!("./error_codes/E0561.md"),
-E0562: include_str!("./error_codes/E0562.md"),
-E0565: include_str!("./error_codes/E0565.md"),
-E0566: include_str!("./error_codes/E0566.md"),
-E0567: include_str!("./error_codes/E0567.md"),
-E0568: include_str!("./error_codes/E0568.md"),
-E0569: include_str!("./error_codes/E0569.md"),
-E0570: include_str!("./error_codes/E0570.md"),
-E0571: include_str!("./error_codes/E0571.md"),
-E0572: include_str!("./error_codes/E0572.md"),
-E0573: include_str!("./error_codes/E0573.md"),
-E0574: include_str!("./error_codes/E0574.md"),
-E0575: include_str!("./error_codes/E0575.md"),
-E0576: include_str!("./error_codes/E0576.md"),
-E0577: include_str!("./error_codes/E0577.md"),
-E0578: include_str!("./error_codes/E0578.md"),
-E0579: include_str!("./error_codes/E0579.md"),
-E0580: include_str!("./error_codes/E0580.md"),
-E0581: include_str!("./error_codes/E0581.md"),
-E0582: include_str!("./error_codes/E0582.md"),
-E0583: include_str!("./error_codes/E0583.md"),
-E0584: include_str!("./error_codes/E0584.md"),
-E0585: include_str!("./error_codes/E0585.md"),
-E0586: include_str!("./error_codes/E0586.md"),
-E0587: include_str!("./error_codes/E0587.md"),
-E0588: include_str!("./error_codes/E0588.md"),
-E0589: include_str!("./error_codes/E0589.md"),
-E0590: include_str!("./error_codes/E0590.md"),
-E0591: include_str!("./error_codes/E0591.md"),
-E0592: include_str!("./error_codes/E0592.md"),
-E0593: include_str!("./error_codes/E0593.md"),
-E0594: include_str!("./error_codes/E0594.md"),
-E0595: include_str!("./error_codes/E0595.md"),
-E0596: include_str!("./error_codes/E0596.md"),
-E0597: include_str!("./error_codes/E0597.md"),
-E0599: include_str!("./error_codes/E0599.md"),
-E0600: include_str!("./error_codes/E0600.md"),
-E0601: include_str!("./error_codes/E0601.md"),
-E0602: include_str!("./error_codes/E0602.md"),
-E0603: include_str!("./error_codes/E0603.md"),
-E0604: include_str!("./error_codes/E0604.md"),
-E0605: include_str!("./error_codes/E0605.md"),
-E0606: include_str!("./error_codes/E0606.md"),
-E0607: include_str!("./error_codes/E0607.md"),
-E0608: include_str!("./error_codes/E0608.md"),
-E0609: include_str!("./error_codes/E0609.md"),
-E0610: include_str!("./error_codes/E0610.md"),
-E0614: include_str!("./error_codes/E0614.md"),
-E0615: include_str!("./error_codes/E0615.md"),
-E0616: include_str!("./error_codes/E0616.md"),
-E0617: include_str!("./error_codes/E0617.md"),
-E0618: include_str!("./error_codes/E0618.md"),
-E0619: include_str!("./error_codes/E0619.md"),
-E0620: include_str!("./error_codes/E0620.md"),
-E0621: include_str!("./error_codes/E0621.md"),
-E0622: include_str!("./error_codes/E0622.md"),
-E0623: include_str!("./error_codes/E0623.md"),
-E0624: include_str!("./error_codes/E0624.md"),
-E0625: include_str!("./error_codes/E0625.md"),
-E0626: include_str!("./error_codes/E0626.md"),
-E0627: include_str!("./error_codes/E0627.md"),
-E0628: include_str!("./error_codes/E0628.md"),
-E0631: include_str!("./error_codes/E0631.md"),
-E0632: include_str!("./error_codes/E0632.md"),
-E0633: include_str!("./error_codes/E0633.md"),
-E0634: include_str!("./error_codes/E0634.md"),
-E0635: include_str!("./error_codes/E0635.md"),
-E0636: include_str!("./error_codes/E0636.md"),
-E0637: include_str!("./error_codes/E0637.md"),
-E0638: include_str!("./error_codes/E0638.md"),
-E0639: include_str!("./error_codes/E0639.md"),
-E0640: include_str!("./error_codes/E0640.md"),
-E0641: include_str!("./error_codes/E0641.md"),
-E0642: include_str!("./error_codes/E0642.md"),
-E0643: include_str!("./error_codes/E0643.md"),
-E0644: include_str!("./error_codes/E0644.md"),
-E0646: include_str!("./error_codes/E0646.md"),
-E0647: include_str!("./error_codes/E0647.md"),
-E0648: include_str!("./error_codes/E0648.md"),
-E0657: include_str!("./error_codes/E0657.md"),
-E0658: include_str!("./error_codes/E0658.md"),
-E0659: include_str!("./error_codes/E0659.md"),
-E0660: include_str!("./error_codes/E0660.md"),
-E0661: include_str!("./error_codes/E0661.md"),
-E0662: include_str!("./error_codes/E0662.md"),
-E0663: include_str!("./error_codes/E0663.md"),
-E0664: include_str!("./error_codes/E0664.md"),
-E0665: include_str!("./error_codes/E0665.md"),
-E0666: include_str!("./error_codes/E0666.md"),
-E0667: include_str!("./error_codes/E0667.md"),
-E0668: include_str!("./error_codes/E0668.md"),
-E0669: include_str!("./error_codes/E0669.md"),
-E0670: include_str!("./error_codes/E0670.md"),
-E0671: include_str!("./error_codes/E0671.md"),
-E0687: include_str!("./error_codes/E0687.md"),
-E0688: include_str!("./error_codes/E0688.md"),
-E0689: include_str!("./error_codes/E0689.md"),
-E0690: include_str!("./error_codes/E0690.md"),
-E0691: include_str!("./error_codes/E0691.md"),
-E0692: include_str!("./error_codes/E0692.md"),
-E0693: include_str!("./error_codes/E0693.md"),
-E0695: include_str!("./error_codes/E0695.md"),
-E0696: include_str!("./error_codes/E0696.md"),
-E0697: include_str!("./error_codes/E0697.md"),
-E0698: include_str!("./error_codes/E0698.md"),
-E0699: include_str!("./error_codes/E0699.md"),
-E0700: include_str!("./error_codes/E0700.md"),
-E0701: include_str!("./error_codes/E0701.md"),
-E0703: include_str!("./error_codes/E0703.md"),
-E0704: include_str!("./error_codes/E0704.md"),
-E0705: include_str!("./error_codes/E0705.md"),
-E0706: include_str!("./error_codes/E0706.md"),
-E0708: include_str!("./error_codes/E0708.md"),
-E0710: include_str!("./error_codes/E0710.md"),
-E0712: include_str!("./error_codes/E0712.md"),
-E0713: include_str!("./error_codes/E0713.md"),
-E0714: include_str!("./error_codes/E0714.md"),
-E0715: include_str!("./error_codes/E0715.md"),
-E0716: include_str!("./error_codes/E0716.md"),
-E0711: include_str!("./error_codes/E0711.md"),
-E0717: include_str!("./error_codes/E0717.md"),
-E0718: include_str!("./error_codes/E0718.md"),
-E0719: include_str!("./error_codes/E0719.md"),
-E0720: include_str!("./error_codes/E0720.md"),
-E0722: include_str!("./error_codes/E0722.md"),
-E0724: include_str!("./error_codes/E0724.md"),
-E0725: include_str!("./error_codes/E0725.md"),
-E0726: include_str!("./error_codes/E0726.md"),
-E0727: include_str!("./error_codes/E0727.md"),
-E0728: include_str!("./error_codes/E0728.md"),
-E0729: include_str!("./error_codes/E0729.md"),
-E0730: include_str!("./error_codes/E0730.md"),
-E0731: include_str!("./error_codes/E0731.md"),
-E0732: include_str!("./error_codes/E0732.md"),
-E0733: include_str!("./error_codes/E0733.md"),
-E0734: include_str!("./error_codes/E0734.md"),
-E0735: include_str!("./error_codes/E0735.md"),
-E0736: include_str!("./error_codes/E0736.md"),
-E0737: include_str!("./error_codes/E0737.md"),
-E0739: include_str!("./error_codes/E0739.md"),
-E0740: include_str!("./error_codes/E0740.md"),
-E0741: include_str!("./error_codes/E0741.md"),
-E0742: include_str!("./error_codes/E0742.md"),
-E0743: include_str!("./error_codes/E0743.md"),
-E0744: include_str!("./error_codes/E0744.md"),
-E0745: include_str!("./error_codes/E0745.md"),
-E0746: include_str!("./error_codes/E0746.md"),
-E0747: include_str!("./error_codes/E0747.md"),
-E0748: include_str!("./error_codes/E0748.md"),
-E0749: include_str!("./error_codes/E0749.md"),
-E0750: include_str!("./error_codes/E0750.md"),
-E0751: include_str!("./error_codes/E0751.md"),
-E0752: include_str!("./error_codes/E0752.md"),
-E0753: include_str!("./error_codes/E0753.md"),
-E0754: include_str!("./error_codes/E0754.md"),
-E0755: include_str!("./error_codes/E0755.md"),
-E0756: include_str!("./error_codes/E0756.md"),
-E0757: include_str!("./error_codes/E0757.md"),
-E0758: include_str!("./error_codes/E0758.md"),
-E0759: include_str!("./error_codes/E0759.md"),
-E0760: include_str!("./error_codes/E0760.md"),
-E0761: include_str!("./error_codes/E0761.md"),
-E0762: include_str!("./error_codes/E0762.md"),
-E0763: include_str!("./error_codes/E0763.md"),
-E0764: include_str!("./error_codes/E0764.md"),
-E0765: include_str!("./error_codes/E0765.md"),
-E0766: include_str!("./error_codes/E0766.md"),
-E0767: include_str!("./error_codes/E0767.md"),
-E0768: include_str!("./error_codes/E0768.md"),
-E0769: include_str!("./error_codes/E0769.md"),
-E0770: include_str!("./error_codes/E0770.md"),
-E0771: include_str!("./error_codes/E0771.md"),
-E0772: include_str!("./error_codes/E0772.md"),
-E0773: include_str!("./error_codes/E0773.md"),
-E0774: include_str!("./error_codes/E0774.md"),
-E0775: include_str!("./error_codes/E0775.md"),
-E0776: include_str!("./error_codes/E0776.md"),
-E0777: include_str!("./error_codes/E0777.md"),
-E0778: include_str!("./error_codes/E0778.md"),
-E0779: include_str!("./error_codes/E0779.md"),
-E0780: include_str!("./error_codes/E0780.md"),
-E0781: include_str!("./error_codes/E0781.md"),
-E0782: include_str!("./error_codes/E0782.md"),
-E0783: include_str!("./error_codes/E0783.md"),
-E0784: include_str!("./error_codes/E0784.md"),
-E0785: include_str!("./error_codes/E0785.md"),
-E0786: include_str!("./error_codes/E0786.md"),
-E0787: include_str!("./error_codes/E0787.md"),
-E0788: include_str!("./error_codes/E0788.md"),
-E0789: include_str!("./error_codes/E0789.md"),
-E0790: include_str!("./error_codes/E0790.md"),
-E0791: include_str!("./error_codes/E0791.md"),
-E0792: include_str!("./error_codes/E0792.md"),
-E0793: include_str!("./error_codes/E0793.md"),
-E0794: include_str!("./error_codes/E0794.md"),
-E0795: include_str!("./error_codes/E0795.md"),
-E0796: include_str!("./error_codes/E0796.md"),
-E0797: include_str!("./error_codes/E0797.md"),
-}
-
-// Undocumented removed error codes. Note that many removed error codes are kept in the list above
-// and marked as no-longer emitted with a note in the markdown file (see E0001 for an example).
-//  E0006, // merged with E0005
-//  E0008, // cannot bind by-move into a pattern guard
-//  E0019, // merged into E0015
-//  E0035, // merged into E0087/E0089
-//  E0036, // merged into E0087/E0089
-//  E0068,
-//  E0085,
-//  E0086,
-//  E0101, // replaced with E0282
-//  E0102, // replaced with E0282
-//  E0103,
-//  E0104,
-//  E0122, // bounds in type aliases are ignored, turned into proper lint
-//  E0123,
-//  E0127,
-//  E0129,
-//  E0134,
-//  E0135,
-//  E0141,
-//  E0153, // unused error code
-//  E0157, // unused error code
-//  E0159, // use of trait `{}` as struct constructor
-//  E0163, // merged into E0071
-//  E0167,
-//  E0168,
-//  E0172, // non-trait found in a type sum, moved to resolve
-//  E0173, // manual implementations of unboxed closure traits are experimental
-//  E0174,
-//  E0182, // merged into E0229
-//  E0187, // cannot infer the kind of the closure
-//  E0188, // can not cast an immutable reference to a mutable pointer
-//  E0189, // deprecated: can only cast a boxed pointer to a boxed object
-//  E0190, // deprecated: can only cast a &-pointer to an &-object
-//  E0194, // merged into E0403
-//  E0196, // cannot determine a type for this closure
-//  E0209, // builtin traits can only be implemented on structs or enums
-//  E0213, // associated types are not accepted in this context
-//  E0215, // angle-bracket notation is not stable with `Fn`
-//  E0216, // parenthetical notation is only stable with `Fn`
-//  E0217, // ambiguous associated type, defined in multiple supertraits
-//  E0218, // no associated type defined
-//  E0219, // associated type defined in higher-ranked supertrait
-//  E0233,
-//  E0234,
-//  E0235, // structure constructor specifies a structure of type but
-//  E0236, // no lang item for range syntax
-//  E0237, // no lang item for range syntax
-//  E0238, // parenthesized parameters may only be used with a trait
-//  E0239, // `next` method of `Iterator` trait has unexpected type
-//  E0240,
-//  E0241,
-//  E0242,
-//  E0245, // not a trait
-//  E0246, // invalid recursive type
-//  E0247,
-//  E0248, // value used as a type, now reported earlier during resolution
-//         // as E0412
-//  E0249,
-//  E0257,
-//  E0258,
-//  E0272, // on_unimplemented #0
-//  E0273, // on_unimplemented #1
-//  E0274, // on_unimplemented #2
-//  E0278, // requirement is not satisfied
-//  E0279,
-//  E0280, // changed to ICE
-//  E0285, // overflow evaluation builtin bounds
-//  E0296, // replaced with a generic attribute input check
-//  E0298, // cannot compare constants
-//  E0299, // mismatched types between arms
-//  E0300, // unexpanded macro
-//  E0304, // expected signed integer constant
-//  E0305, // expected constant
-//  E0313, // removed: found unreachable
-//  E0314, // closure outlives stack frame
-//  E0315, // cannot invoke closure outside of its lifetime
-//  E0319, // trait impls for defaulted traits allowed just for structs/enums
-//  E0372, // coherence not object safe
-//  E0385, // {} in an aliasable location
-//  E0402, // cannot use an outer type parameter in this context
-//  E0406, // merged into 420
-//  E0410, // merged into 408
-//  E0413, // merged into 530
-//  E0414, // merged into 530
-//  E0417, // merged into 532
-//  E0418, // merged into 532
-//  E0419, // merged into 531
-//  E0420, // merged into 532
-//  E0421, // merged into 531
-//  E0427, // merged into 530
-//  E0445, // merged into 446 and type privacy lints
-//  E0456, // plugin `..` is not available for triple `..`
-//  E0465, // removed: merged with E0464
-//  E0467, // removed
-//  E0470, // removed
-//  E0471, // constant evaluation error (in pattern)
-//  E0473, // dereference of reference outside its lifetime
-//  E0474, // captured variable `..` does not outlive the enclosing closure
-//  E0475, // index of slice outside its lifetime
-//  E0479, // the type `..` (provided as the value of a type parameter) is...
-//  E0480, // lifetime of method receiver does not outlive the method call
-//  E0481, // lifetime of function argument does not outlive the function call
-//  E0483, // lifetime of operand does not outlive the operation
-//  E0484, // reference is not valid at the time of borrow
-//  E0485, // automatically reference is not valid at the time of borrow
-//  E0486, // type of expression contains references that are not valid during..
-//  E0487, // unsafe use of destructor: destructor might be called while...
-//  E0488, // lifetime of variable does not enclose its declaration
-//  E0489, // type/lifetime parameter not in scope here
-//  E0490, // removed: unreachable
-//  E0526, // shuffle indices are not constant
-//  E0540, // multiple rustc_deprecated attributes
-//  E0548, // replaced with a generic attribute input check
-//  E0553, // multiple rustc_const_unstable attributes
-//  E0555, // replaced with a generic attribute input check
-//  E0558, // replaced with a generic attribute input check
-//  E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
-//  E0564, // only named lifetimes are allowed in `impl Trait`,
-//         // but `{}` was found in the type `{}`
-//  E0598, // lifetime of {} is too short to guarantee its contents can be...
-//  E0611, // merged into E0616
-//  E0612, // merged into E0609
-//  E0613, // Removed (merged with E0609)
-//  E0629, // missing 'feature' (rustc_const_unstable)
-//  E0630, // rustc_const_unstable attribute must be paired with stable/unstable
-//         // attribute
-//  E0645, // trait aliases not finished
-//  E0694, // an unknown tool name found in scoped attributes
-//  E0702, // replaced with a generic attribute input check
-//  E0707, // multiple elided lifetimes used in arguments of `async fn`
-//  E0709, // multiple different lifetimes used in arguments of `async fn`
-//  E0721, // `await` keyword
-//  E0723, // unstable feature in `const` context
-//  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
-//  E0744, // merged into E0728
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index dd2818116368b..5b2766618fccb 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -1,19 +1,679 @@
+//! This library is used to gather all error codes into one place, to make
+//! their maintenance easier.
+
 #![allow(internal_features)]
 #![feature(rustdoc_internals)]
 #![doc(rust_logo)]
 #![deny(rustdoc::invalid_codeblock_attributes)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
-//! This library is used to gather all error codes into one place,
-//! the goal being to make their maintenance easier.
 
-macro_rules! register_diagnostics {
-    ($($ecode:ident: $message:expr,)*) => (
-        pub static DIAGNOSTICS: &[(&str, &str)] = &[
-            $( (stringify!($ecode), $message), )*
-        ];
+// This higher-order macro defines the error codes that are in use. It is used
+// in the `rustc_errors` crate. Removed error codes are listed in the comment
+// below.
+//
+// /!\ IMPORTANT /!\
+//
+// Error code explanation are defined in `error_codes/EXXXX.md` files. They must follow the RFC
+// 1567 available here:
+// https://rust-lang.github.io/rfcs/1567-long-error-codes-explanation-normalization.html
+//
+// Also, the contents of this macro is checked by tidy (in `check_error_codes_docs`). If you change
+// the macro syntax you will need to change tidy as well.
+//
+// Both columns are necessary because it's not possible in Rust to create a new identifier such as
+// `E0123` from an integer literal such as `0123`, unfortunately.
+#[macro_export]
+macro_rules! error_codes {
+    ($macro:path) => (
+        $macro!(
+E0001: 0001,
+E0002: 0002,
+E0004: 0004,
+E0005: 0005,
+E0007: 0007,
+E0009: 0009,
+E0010: 0010,
+E0013: 0013,
+E0014: 0014,
+E0015: 0015,
+E0023: 0023,
+E0025: 0025,
+E0026: 0026,
+E0027: 0027,
+E0029: 0029,
+E0030: 0030,
+E0033: 0033,
+E0034: 0034,
+E0038: 0038,
+E0040: 0040,
+E0044: 0044,
+E0045: 0045,
+E0046: 0046,
+E0049: 0049,
+E0050: 0050,
+E0053: 0053,
+E0054: 0054,
+E0055: 0055,
+E0057: 0057,
+E0059: 0059,
+E0060: 0060,
+E0061: 0061,
+E0062: 0062,
+E0063: 0063,
+E0067: 0067,
+E0069: 0069,
+E0070: 0070,
+E0071: 0071,
+E0072: 0072,
+E0073: 0073,
+E0074: 0074,
+E0075: 0075,
+E0076: 0076,
+E0077: 0077,
+E0080: 0080,
+E0081: 0081,
+E0084: 0084,
+E0087: 0087,
+E0088: 0088,
+E0089: 0089,
+E0090: 0090,
+E0091: 0091,
+E0092: 0092,
+E0093: 0093,
+E0094: 0094,
+E0106: 0106,
+E0107: 0107,
+E0109: 0109,
+E0110: 0110,
+E0116: 0116,
+E0117: 0117,
+E0118: 0118,
+E0119: 0119,
+E0120: 0120,
+E0121: 0121,
+E0124: 0124,
+E0128: 0128,
+E0130: 0130,
+E0131: 0131,
+E0132: 0132,
+E0133: 0133,
+E0136: 0136,
+E0137: 0137,
+E0138: 0138,
+E0139: 0139,
+E0152: 0152,
+E0154: 0154,
+E0158: 0158,
+E0161: 0161,
+E0162: 0162,
+E0164: 0164,
+E0165: 0165,
+E0170: 0170,
+E0178: 0178,
+E0183: 0183,
+E0184: 0184,
+E0185: 0185,
+E0186: 0186,
+E0191: 0191,
+E0192: 0192,
+E0193: 0193,
+E0195: 0195,
+E0197: 0197,
+E0198: 0198,
+E0199: 0199,
+E0200: 0200,
+E0201: 0201,
+E0203: 0203,
+E0204: 0204,
+E0205: 0205,
+E0206: 0206,
+E0207: 0207,
+E0208: 0208,
+E0210: 0210,
+E0211: 0211,
+E0212: 0212,
+E0214: 0214,
+E0220: 0220,
+E0221: 0221,
+E0222: 0222,
+E0223: 0223,
+E0224: 0224,
+E0225: 0225,
+E0226: 0226,
+E0227: 0227,
+E0228: 0228,
+E0229: 0229,
+E0230: 0230,
+E0231: 0231,
+E0232: 0232,
+E0243: 0243,
+E0244: 0244,
+E0251: 0251,
+E0252: 0252,
+E0253: 0253,
+E0254: 0254,
+E0255: 0255,
+E0256: 0256,
+E0259: 0259,
+E0260: 0260,
+E0261: 0261,
+E0262: 0262,
+E0263: 0263,
+E0264: 0264,
+E0267: 0267,
+E0268: 0268,
+E0271: 0271,
+E0275: 0275,
+E0276: 0276,
+E0277: 0277,
+E0281: 0281,
+E0282: 0282,
+E0283: 0283,
+E0284: 0284,
+E0297: 0297,
+E0301: 0301,
+E0302: 0302,
+E0303: 0303,
+E0307: 0307,
+E0308: 0308,
+E0309: 0309,
+E0310: 0310,
+E0311: 0311,
+E0312: 0312,
+E0316: 0316,
+E0317: 0317,
+E0320: 0320,
+E0321: 0321,
+E0322: 0322,
+E0323: 0323,
+E0324: 0324,
+E0325: 0325,
+E0326: 0326,
+E0328: 0328,
+E0329: 0329,
+E0364: 0364,
+E0365: 0365,
+E0366: 0366,
+E0367: 0367,
+E0368: 0368,
+E0369: 0369,
+E0370: 0370,
+E0371: 0371,
+E0373: 0373,
+E0374: 0374,
+E0375: 0375,
+E0376: 0376,
+E0377: 0377,
+E0378: 0378,
+E0379: 0379,
+E0380: 0380,
+E0381: 0381,
+E0382: 0382,
+E0383: 0383,
+E0384: 0384,
+E0386: 0386,
+E0387: 0387,
+E0388: 0388,
+E0389: 0389,
+E0390: 0390,
+E0391: 0391,
+E0392: 0392,
+E0393: 0393,
+E0398: 0398,
+E0399: 0399,
+E0401: 0401,
+E0403: 0403,
+E0404: 0404,
+E0405: 0405,
+E0407: 0407,
+E0408: 0408,
+E0409: 0409,
+E0411: 0411,
+E0412: 0412,
+E0415: 0415,
+E0416: 0416,
+E0422: 0422,
+E0423: 0423,
+E0424: 0424,
+E0425: 0425,
+E0426: 0426,
+E0428: 0428,
+E0429: 0429,
+E0430: 0430,
+E0431: 0431,
+E0432: 0432,
+E0433: 0433,
+E0434: 0434,
+E0435: 0435,
+E0436: 0436,
+E0437: 0437,
+E0438: 0438,
+E0439: 0439,
+E0445: 0445,
+E0446: 0446,
+E0447: 0447,
+E0448: 0448,
+E0449: 0449,
+E0451: 0451,
+E0452: 0452,
+E0453: 0453,
+E0454: 0454,
+E0455: 0455,
+E0457: 0457,
+E0458: 0458,
+E0459: 0459,
+E0460: 0460,
+E0461: 0461,
+E0462: 0462,
+E0463: 0463,
+E0464: 0464,
+E0466: 0466,
+E0468: 0468,
+E0469: 0469,
+E0472: 0472,
+E0476: 0476,
+E0477: 0477,
+E0478: 0478,
+E0482: 0482,
+E0491: 0491,
+E0492: 0492,
+E0493: 0493,
+E0495: 0495,
+E0496: 0496,
+E0497: 0497,
+E0498: 0498,
+E0499: 0499,
+E0500: 0500,
+E0501: 0501,
+E0502: 0502,
+E0503: 0503,
+E0504: 0504,
+E0505: 0505,
+E0506: 0506,
+E0507: 0507,
+E0508: 0508,
+E0509: 0509,
+E0510: 0510,
+E0511: 0511,
+E0512: 0512,
+E0514: 0514,
+E0515: 0515,
+E0516: 0516,
+E0517: 0517,
+E0518: 0518,
+E0519: 0519,
+E0520: 0520,
+E0521: 0521,
+E0522: 0522,
+E0523: 0523,
+E0524: 0524,
+E0525: 0525,
+E0527: 0527,
+E0528: 0528,
+E0529: 0529,
+E0530: 0530,
+E0531: 0531,
+E0532: 0532,
+E0533: 0533,
+E0534: 0534,
+E0535: 0535,
+E0536: 0536,
+E0537: 0537,
+E0538: 0538,
+E0539: 0539,
+E0541: 0541,
+E0542: 0542,
+E0543: 0543,
+E0544: 0544,
+E0545: 0545,
+E0546: 0546,
+E0547: 0547,
+E0549: 0549,
+E0550: 0550,
+E0551: 0551,
+E0552: 0552,
+E0554: 0554,
+E0556: 0556,
+E0557: 0557,
+E0559: 0559,
+E0560: 0560,
+E0561: 0561,
+E0562: 0562,
+E0565: 0565,
+E0566: 0566,
+E0567: 0567,
+E0568: 0568,
+E0569: 0569,
+E0570: 0570,
+E0571: 0571,
+E0572: 0572,
+E0573: 0573,
+E0574: 0574,
+E0575: 0575,
+E0576: 0576,
+E0577: 0577,
+E0578: 0578,
+E0579: 0579,
+E0580: 0580,
+E0581: 0581,
+E0582: 0582,
+E0583: 0583,
+E0584: 0584,
+E0585: 0585,
+E0586: 0586,
+E0587: 0587,
+E0588: 0588,
+E0589: 0589,
+E0590: 0590,
+E0591: 0591,
+E0592: 0592,
+E0593: 0593,
+E0594: 0594,
+E0595: 0595,
+E0596: 0596,
+E0597: 0597,
+E0599: 0599,
+E0600: 0600,
+E0601: 0601,
+E0602: 0602,
+E0603: 0603,
+E0604: 0604,
+E0605: 0605,
+E0606: 0606,
+E0607: 0607,
+E0608: 0608,
+E0609: 0609,
+E0610: 0610,
+E0614: 0614,
+E0615: 0615,
+E0616: 0616,
+E0617: 0617,
+E0618: 0618,
+E0619: 0619,
+E0620: 0620,
+E0621: 0621,
+E0622: 0622,
+E0623: 0623,
+E0624: 0624,
+E0625: 0625,
+E0626: 0626,
+E0627: 0627,
+E0628: 0628,
+E0631: 0631,
+E0632: 0632,
+E0633: 0633,
+E0634: 0634,
+E0635: 0635,
+E0636: 0636,
+E0637: 0637,
+E0638: 0638,
+E0639: 0639,
+E0640: 0640,
+E0641: 0641,
+E0642: 0642,
+E0643: 0643,
+E0644: 0644,
+E0646: 0646,
+E0647: 0647,
+E0648: 0648,
+E0657: 0657,
+E0658: 0658,
+E0659: 0659,
+E0660: 0660,
+E0661: 0661,
+E0662: 0662,
+E0663: 0663,
+E0664: 0664,
+E0665: 0665,
+E0666: 0666,
+E0667: 0667,
+E0668: 0668,
+E0669: 0669,
+E0670: 0670,
+E0671: 0671,
+E0687: 0687,
+E0688: 0688,
+E0689: 0689,
+E0690: 0690,
+E0691: 0691,
+E0692: 0692,
+E0693: 0693,
+E0695: 0695,
+E0696: 0696,
+E0697: 0697,
+E0698: 0698,
+E0699: 0699,
+E0700: 0700,
+E0701: 0701,
+E0703: 0703,
+E0704: 0704,
+E0705: 0705,
+E0706: 0706,
+E0708: 0708,
+E0710: 0710,
+E0712: 0712,
+E0713: 0713,
+E0714: 0714,
+E0715: 0715,
+E0716: 0716,
+E0711: 0711,
+E0717: 0717,
+E0718: 0718,
+E0719: 0719,
+E0720: 0720,
+E0722: 0722,
+E0724: 0724,
+E0725: 0725,
+E0726: 0726,
+E0727: 0727,
+E0728: 0728,
+E0729: 0729,
+E0730: 0730,
+E0731: 0731,
+E0732: 0732,
+E0733: 0733,
+E0734: 0734,
+E0735: 0735,
+E0736: 0736,
+E0737: 0737,
+E0739: 0739,
+E0740: 0740,
+E0741: 0741,
+E0742: 0742,
+E0743: 0743,
+E0744: 0744,
+E0745: 0745,
+E0746: 0746,
+E0747: 0747,
+E0748: 0748,
+E0749: 0749,
+E0750: 0750,
+E0751: 0751,
+E0752: 0752,
+E0753: 0753,
+E0754: 0754,
+E0755: 0755,
+E0756: 0756,
+E0757: 0757,
+E0758: 0758,
+E0759: 0759,
+E0760: 0760,
+E0761: 0761,
+E0762: 0762,
+E0763: 0763,
+E0764: 0764,
+E0765: 0765,
+E0766: 0766,
+E0767: 0767,
+E0768: 0768,
+E0769: 0769,
+E0770: 0770,
+E0771: 0771,
+E0772: 0772,
+E0773: 0773,
+E0774: 0774,
+E0775: 0775,
+E0776: 0776,
+E0777: 0777,
+E0778: 0778,
+E0779: 0779,
+E0780: 0780,
+E0781: 0781,
+E0782: 0782,
+E0783: 0783,
+E0784: 0784,
+E0785: 0785,
+E0786: 0786,
+E0787: 0787,
+E0788: 0788,
+E0789: 0789,
+E0790: 0790,
+E0791: 0791,
+E0792: 0792,
+E0793: 0793,
+E0794: 0794,
+E0795: 0795,
+E0796: 0796,
+E0797: 0797,
+        );
     )
 }
 
-mod error_codes;
-pub use error_codes::DIAGNOSTICS;
+// Undocumented removed error codes. Note that many removed error codes are kept in the list above
+// and marked as no-longer emitted with a note in the markdown file (see E0001 for an example).
+//  E0006, // merged with E0005
+//  E0008, // cannot bind by-move into a pattern guard
+//  E0019, // merged into E0015
+//  E0035, // merged into E0087/E0089
+//  E0036, // merged into E0087/E0089
+//  E0068,
+//  E0085,
+//  E0086,
+//  E0101, // replaced with E0282
+//  E0102, // replaced with E0282
+//  E0103,
+//  E0104,
+//  E0122, // bounds in type aliases are ignored, turned into proper lint
+//  E0123,
+//  E0127,
+//  E0129,
+//  E0134,
+//  E0135,
+//  E0141,
+//  E0153, // unused error code
+//  E0157, // unused error code
+//  E0159, // use of trait `{}` as struct constructor
+//  E0163, // merged into E0071
+//  E0167,
+//  E0168,
+//  E0172, // non-trait found in a type sum, moved to resolve
+//  E0173, // manual implementations of unboxed closure traits are experimental
+//  E0174,
+//  E0182, // merged into E0229
+//  E0187, // cannot infer the kind of the closure
+//  E0188, // can not cast an immutable reference to a mutable pointer
+//  E0189, // deprecated: can only cast a boxed pointer to a boxed object
+//  E0190, // deprecated: can only cast a &-pointer to an &-object
+//  E0194, // merged into E0403
+//  E0196, // cannot determine a type for this closure
+//  E0209, // builtin traits can only be implemented on structs or enums
+//  E0213, // associated types are not accepted in this context
+//  E0215, // angle-bracket notation is not stable with `Fn`
+//  E0216, // parenthetical notation is only stable with `Fn`
+//  E0217, // ambiguous associated type, defined in multiple supertraits
+//  E0218, // no associated type defined
+//  E0219, // associated type defined in higher-ranked supertrait
+//  E0233,
+//  E0234,
+//  E0235, // structure constructor specifies a structure of type but
+//  E0236, // no lang item for range syntax
+//  E0237, // no lang item for range syntax
+//  E0238, // parenthesized parameters may only be used with a trait
+//  E0239, // `next` method of `Iterator` trait has unexpected type
+//  E0240,
+//  E0241,
+//  E0242,
+//  E0245, // not a trait
+//  E0246, // invalid recursive type
+//  E0247,
+//  E0248, // value used as a type, now reported earlier during resolution
+//         // as E0412
+//  E0249,
+//  E0257,
+//  E0258,
+//  E0272, // on_unimplemented #0
+//  E0273, // on_unimplemented #1
+//  E0274, // on_unimplemented #2
+//  E0278, // requirement is not satisfied
+//  E0279,
+//  E0280, // changed to ICE
+//  E0285, // overflow evaluation builtin bounds
+//  E0296, // replaced with a generic attribute input check
+//  E0298, // cannot compare constants
+//  E0299, // mismatched types between arms
+//  E0300, // unexpanded macro
+//  E0304, // expected signed integer constant
+//  E0305, // expected constant
+//  E0313, // removed: found unreachable
+//  E0314, // closure outlives stack frame
+//  E0315, // cannot invoke closure outside of its lifetime
+//  E0319, // trait impls for defaulted traits allowed just for structs/enums
+//  E0372, // coherence not object safe
+//  E0385, // {} in an aliasable location
+//  E0402, // cannot use an outer type parameter in this context
+//  E0406, // merged into 420
+//  E0410, // merged into 408
+//  E0413, // merged into 530
+//  E0414, // merged into 530
+//  E0417, // merged into 532
+//  E0418, // merged into 532
+//  E0419, // merged into 531
+//  E0420, // merged into 532
+//  E0421, // merged into 531
+//  E0427, // merged into 530
+//  E0445, // merged into 446 and type privacy lints
+//  E0456, // plugin `..` is not available for triple `..`
+//  E0465, // removed: merged with E0464
+//  E0467, // removed
+//  E0470, // removed
+//  E0471, // constant evaluation error (in pattern)
+//  E0473, // dereference of reference outside its lifetime
+//  E0474, // captured variable `..` does not outlive the enclosing closure
+//  E0475, // index of slice outside its lifetime
+//  E0479, // the type `..` (provided as the value of a type parameter) is...
+//  E0480, // lifetime of method receiver does not outlive the method call
+//  E0481, // lifetime of function argument does not outlive the function call
+//  E0483, // lifetime of operand does not outlive the operation
+//  E0484, // reference is not valid at the time of borrow
+//  E0485, // automatically reference is not valid at the time of borrow
+//  E0486, // type of expression contains references that are not valid during..
+//  E0487, // unsafe use of destructor: destructor might be called while...
+//  E0488, // lifetime of variable does not enclose its declaration
+//  E0489, // type/lifetime parameter not in scope here
+//  E0490, // removed: unreachable
+//  E0526, // shuffle indices are not constant
+//  E0540, // multiple rustc_deprecated attributes
+//  E0548, // replaced with a generic attribute input check
+//  E0553, // multiple rustc_const_unstable attributes
+//  E0555, // replaced with a generic attribute input check
+//  E0558, // replaced with a generic attribute input check
+//  E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
+//  E0564, // only named lifetimes are allowed in `impl Trait`,
+//         // but `{}` was found in the type `{}`
+//  E0598, // lifetime of {} is too short to guarantee its contents can be...
+//  E0611, // merged into E0616
+//  E0612, // merged into E0609
+//  E0613, // Removed (merged with E0609)
+//  E0629, // missing 'feature' (rustc_const_unstable)
+//  E0630, // rustc_const_unstable attribute must be paired with stable/unstable
+//         // attribute
+//  E0645, // trait aliases not finished
+//  E0694, // an unknown tool name found in scoped attributes
+//  E0702, // replaced with a generic attribute input check
+//  E0707, // multiple elided lifetimes used in arguments of `async fn`
+//  E0709, // multiple different lifetimes used in arguments of `async fn`
+//  E0721, // `await` keyword
+//  E0723, // unstable feature in `const` context
+//  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
+//  E0744, // merged into E0728
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index 0c1fcecb57173..a2d1fd2a92419 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -10,9 +10,11 @@ derive_setters = "0.1.6"
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_error_codes = { path = "../rustc_error_codes" }
 rustc_error_messages = { path = "../rustc_error_messages" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hir = { path = "../rustc_hir" }
+rustc_index = { path = "../rustc_index" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index f0699a56f98ef..949f52ef6b586 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -9,8 +9,8 @@ use crate::emitter::FileWithAnnotatedLines;
 use crate::snippet::Line;
 use crate::translation::{to_fluent_args, Translate};
 use crate::{
-    CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle,
-    Level, MultiSpan, Style, SubDiagnostic,
+    CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, ErrCode, FluentBundle,
+    LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
 };
 use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
 use rustc_data_structures::sync::Lrc;
@@ -127,7 +127,7 @@ impl AnnotateSnippetEmitter {
         level: &Level,
         messages: &[(DiagnosticMessage, Style)],
         args: &FluentArgs<'_>,
-        code: &Option<String>,
+        code: &Option<ErrCode>,
         msp: &MultiSpan,
         _children: &[SubDiagnostic],
         _suggestions: &[CodeSuggestion],
@@ -178,6 +178,7 @@ impl AnnotateSnippetEmitter {
                         .collect::<Vec<Owned>>()
                 })
                 .collect();
+            let code = code.map(|code| code.to_string());
             let snippet = Snippet {
                 title: Some(Annotation {
                     label: Some(&message),
diff --git a/compiler/rustc_errors/src/codes.rs b/compiler/rustc_errors/src/codes.rs
new file mode 100644
index 0000000000000..947cf27ca7957
--- /dev/null
+++ b/compiler/rustc_errors/src/codes.rs
@@ -0,0 +1,39 @@
+//! This module defines the following.
+//! - The `ErrCode` type.
+//! - A constant for every error code, with a name like `E0123`.
+//! - A static table `DIAGNOSTICS` pairing every error code constant with its
+//!   long description text.
+
+use std::fmt;
+
+rustc_index::newtype_index! {
+    #[max = 9999] // Because all error codes have four digits.
+    #[orderable]
+    #[encodable]
+    #[debug_format = "ErrCode({})"]
+    pub struct ErrCode {}
+}
+
+impl fmt::Display for ErrCode {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "E{:04}", self.as_u32())
+    }
+}
+
+macro_rules! define_error_code_constants_and_diagnostics_table {
+    ($($name:ident: $num:literal,)*) => (
+        $(
+            pub const $name: $crate::ErrCode = $crate::ErrCode::from_u32($num);
+        )*
+        pub static DIAGNOSTICS: &[($crate::ErrCode, &str)] = &[
+            $( (
+                $name,
+                include_str!(
+                    concat!("../../rustc_error_codes/src/error_codes/", stringify!($name), ".md")
+                )
+            ), )*
+        ];
+    )
+}
+
+rustc_error_codes::error_codes!(define_error_code_constants_and_diagnostics_table);
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 4934bc2450c79..8a32e29ddc9dc 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1,7 +1,8 @@
 use crate::snippet::Style;
 use crate::{
-    CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level,
-    MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
+    CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee,
+    ErrCode, Level, MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart,
+    SuggestionStyle,
 };
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
@@ -104,7 +105,7 @@ pub struct Diagnostic {
     pub(crate) level: Level,
 
     pub messages: Vec<(DiagnosticMessage, Style)>,
-    pub code: Option<String>,
+    pub code: Option<ErrCode>,
     pub span: MultiSpan,
     pub children: Vec<SubDiagnostic>,
     pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
@@ -893,8 +894,8 @@ impl Diagnostic {
         self
     }
 
-    pub fn code(&mut self, s: String) -> &mut Self {
-        self.code = Some(s);
+    pub fn code(&mut self, code: ErrCode) -> &mut Self {
+        self.code = Some(code);
         self
     }
 
@@ -903,8 +904,8 @@ impl Diagnostic {
         self
     }
 
-    pub fn get_code(&self) -> Option<&str> {
-        self.code.as_deref()
+    pub fn get_code(&self) -> Option<ErrCode> {
+        self.code
     }
 
     pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self {
@@ -990,7 +991,7 @@ impl Diagnostic {
         &Level,
         &[(DiagnosticMessage, Style)],
         Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>,
-        &Option<String>,
+        &Option<ErrCode>,
         &Option<IsLint>,
         &MultiSpan,
         &Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 87e2d295c7f4c..8bfb181648628 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -1,7 +1,7 @@
 use crate::diagnostic::IntoDiagnosticArg;
 use crate::{DiagCtxt, Level, MultiSpan, StashKey};
 use crate::{
-    Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, ExplicitBug,
+    Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrCode, ErrorGuaranteed, ExplicitBug,
     SubdiagnosticMessage,
 };
 use rustc_lint_defs::Applicability;
@@ -399,7 +399,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
         name: String, has_future_breakage: bool,
     ));
     forward!((code, with_code)(
-        s: String,
+        code: ErrCode,
     ));
     forward!((arg, with_arg)(
         name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
@@ -439,12 +439,7 @@ impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> {
 
 #[macro_export]
 macro_rules! struct_span_code_err {
-    ($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $dcx.struct_span_err($span, format!($($message)*)).with_code($crate::error_code!($code))
+    ($dcx:expr, $span:expr, $code:expr, $($message:tt)*) => ({
+        $dcx.struct_span_err($span, format!($($message)*)).with_code($code)
     })
 }
-
-#[macro_export]
-macro_rules! error_code {
-    ($code:ident) => {{ stringify!($code).to_owned() }};
-}
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 39252dea28303..087603f828fe8 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -1,7 +1,7 @@
 use crate::diagnostic::DiagnosticLocation;
 use crate::{fluent_generated as fluent, AddToDiagnostic};
 use crate::{
-    DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
+    DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, ErrCode, IntoDiagnostic,
     IntoDiagnosticArg, Level,
 };
 use rustc_ast as ast;
@@ -80,6 +80,7 @@ into_diagnostic_arg_using_display!(
     &TargetTriple,
     SplitDebuginfo,
     ExitStatus,
+    ErrCode,
 );
 
 impl IntoDiagnosticArg for i32 {
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 23efdaea0ebb8..9f76c1dd248b0 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -17,8 +17,8 @@ use crate::styled_buffer::StyledBuffer;
 use crate::translation::{to_fluent_args, Translate};
 use crate::{
     diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticMessage,
-    FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight,
-    SuggestionStyle, TerminalUrl,
+    ErrCode, FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic,
+    SubstitutionHighlight, SuggestionStyle, TerminalUrl,
 };
 use rustc_lint_defs::pluralize;
 
@@ -1309,7 +1309,7 @@ impl HumanEmitter {
         msp: &MultiSpan,
         msgs: &[(DiagnosticMessage, Style)],
         args: &FluentArgs<'_>,
-        code: &Option<String>,
+        code: &Option<ErrCode>,
         level: &Level,
         max_line_num_len: usize,
         is_secondary: bool,
@@ -1340,9 +1340,9 @@ impl HumanEmitter {
                 buffer.append(0, "[", Style::Level(*level));
                 let code = if let TerminalUrl::Yes = self.terminal_url {
                     let path = "https://doc.rust-lang.org/error_codes";
-                    Cow::Owned(format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07"))
+                    format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07")
                 } else {
-                    Cow::Borrowed(code)
+                    code.to_string()
                 };
                 buffer.append(0, &code, Style::Level(*level));
                 buffer.append(0, "]", Style::Level(*level));
@@ -2076,7 +2076,7 @@ impl HumanEmitter {
         level: &Level,
         messages: &[(DiagnosticMessage, Style)],
         args: &FluentArgs<'_>,
-        code: &Option<String>,
+        code: &Option<ErrCode>,
         span: &MultiSpan,
         children: &[SubDiagnostic],
         suggestions: &[CodeSuggestion],
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index 51b064f4c617a..6f92299827950 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -400,10 +400,10 @@ impl Diagnostic {
 
         let translated_message = je.translate_messages(&diag.messages, &args);
 
-        let code = if let Some(code) = &diag.code {
+        let code = if let Some(code) = diag.code {
             Some(DiagnosticCode {
                 code: code.to_string(),
-                explanation: je.registry.as_ref().unwrap().try_find_description(&code).ok(),
+                explanation: je.registry.as_ref().unwrap().try_find_description(code).ok(),
             })
         } else if let Some(IsLint { name, .. }) = &diag.is_lint {
             Some(DiagnosticCode { code: name.to_string(), explanation: None })
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 9d80c45651725..0d303409844a7 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -2,24 +2,27 @@
 //!
 //! This module contains the code for creating and emitting diagnostics.
 
+// tidy-alphabetical-start
+#![allow(incomplete_features)]
+#![allow(internal_features)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
-#![feature(rustdoc_internals)]
 #![feature(array_windows)]
 #![feature(associated_type_defaults)]
 #![feature(box_into_inner)]
+#![feature(box_patterns)]
+#![feature(error_reporter)]
 #![feature(extract_if)]
 #![feature(if_let_guard)]
 #![feature(let_chains)]
+#![feature(min_specialization)]
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
-#![feature(yeet_expr)]
+#![feature(rustdoc_internals)]
 #![feature(try_blocks)]
-#![feature(box_patterns)]
-#![feature(error_reporter)]
-#![allow(incomplete_features)]
-#![allow(internal_features)]
+#![feature(yeet_expr)]
+// tidy-alphabetical-end
 
 #[macro_use]
 extern crate rustc_macros;
@@ -29,6 +32,7 @@ extern crate tracing;
 
 extern crate self as rustc_errors;
 
+pub use codes::*;
 pub use diagnostic::{
     AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue,
     DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
@@ -77,6 +81,7 @@ use std::path::{Path, PathBuf};
 use Level::*;
 
 pub mod annotate_snippet_emitter_writer;
+pub mod codes;
 mod diagnostic;
 mod diagnostic_builder;
 mod diagnostic_impls;
@@ -445,10 +450,10 @@ struct DiagCtxtInner {
     /// This set contains the code of all emitted diagnostics to avoid
     /// emitting the same diagnostic with extended help (`--teach`) twice, which
     /// would be unnecessary repetition.
-    taught_diagnostics: FxHashSet<String>,
+    taught_diagnostics: FxHashSet<ErrCode>,
 
     /// Used to suggest rustc --explain `<error code>`
-    emitted_diagnostic_codes: FxIndexSet<String>,
+    emitted_diagnostic_codes: FxIndexSet<ErrCode>,
 
     /// This set contains a hash of every diagnostic that has been emitted by
     /// this `DiagCtxt`. These hashes is used to avoid emitting the same error
@@ -1003,9 +1008,9 @@ impl DiagCtxt {
             let mut error_codes = inner
                 .emitted_diagnostic_codes
                 .iter()
-                .filter_map(|code| {
+                .filter_map(|&code| {
                     if registry.try_find_description(code).is_ok().clone() {
-                        Some(code.clone())
+                        Some(code.to_string())
                     } else {
                         None
                     }
@@ -1051,8 +1056,8 @@ impl DiagCtxt {
     ///
     /// Used to suppress emitting the same error multiple times with extended explanation when
     /// calling `-Zteach`.
-    pub fn must_teach(&self, code: &str) -> bool {
-        self.inner.borrow_mut().taught_diagnostics.insert(code.to_string())
+    pub fn must_teach(&self, code: ErrCode) -> bool {
+        self.inner.borrow_mut().taught_diagnostics.insert(code)
     }
 
     pub fn force_print_diagnostic(&self, db: Diagnostic) {
@@ -1312,8 +1317,8 @@ impl DiagCtxtInner {
 
         let mut guaranteed = None;
         (*TRACK_DIAGNOSTIC)(diagnostic, &mut |mut diagnostic| {
-            if let Some(ref code) = diagnostic.code {
-                self.emitted_diagnostic_codes.insert(code.clone());
+            if let Some(code) = diagnostic.code {
+                self.emitted_diagnostic_codes.insert(code);
             }
 
             let already_emitted = {
diff --git a/compiler/rustc_errors/src/registry.rs b/compiler/rustc_errors/src/registry.rs
index f26d8e7ebdc34..8834d04d9718b 100644
--- a/compiler/rustc_errors/src/registry.rs
+++ b/compiler/rustc_errors/src/registry.rs
@@ -1,3 +1,4 @@
+use crate::ErrCode;
 use rustc_data_structures::fx::FxHashMap;
 
 #[derive(Debug)]
@@ -5,17 +6,17 @@ pub struct InvalidErrorCode;
 
 #[derive(Clone)]
 pub struct Registry {
-    long_descriptions: FxHashMap<&'static str, &'static str>,
+    long_descriptions: FxHashMap<ErrCode, &'static str>,
 }
 
 impl Registry {
-    pub fn new(long_descriptions: &[(&'static str, &'static str)]) -> Registry {
+    pub fn new(long_descriptions: &[(ErrCode, &'static str)]) -> Registry {
         Registry { long_descriptions: long_descriptions.iter().copied().collect() }
     }
 
     /// Returns `InvalidErrorCode` if the code requested does not exist in the
     /// registry.
-    pub fn try_find_description(&self, code: &str) -> Result<&'static str, InvalidErrorCode> {
-        self.long_descriptions.get(code).copied().ok_or(InvalidErrorCode)
+    pub fn try_find_description(&self, code: ErrCode) -> Result<&'static str, InvalidErrorCode> {
+        self.long_descriptions.get(&code).copied().ok_or(InvalidErrorCode)
     }
 }
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 4a1c00f0104fd..2584ff62e98e6 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -1,4 +1,5 @@
 use rustc_ast::ast;
+use rustc_errors::codes::*;
 use rustc_macros::Diagnostic;
 use rustc_session::Limit;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
@@ -175,7 +176,7 @@ pub(crate) struct TakesNoArguments<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_feature_removed, code = "E0557")]
+#[diag(expand_feature_removed, code = E0557)]
 pub(crate) struct FeatureRemoved<'a> {
     #[primary_span]
     #[label]
@@ -191,7 +192,7 @@ pub(crate) struct FeatureRemovedReason<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_feature_not_allowed, code = "E0725")]
+#[diag(expand_feature_not_allowed, code = E0725)]
 pub(crate) struct FeatureNotAllowed {
     #[primary_span]
     pub span: Span,
@@ -210,7 +211,7 @@ pub(crate) struct RecursionLimitReached<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_malformed_feature_attribute, code = "E0556")]
+#[diag(expand_malformed_feature_attribute, code = E0556)]
 pub(crate) struct MalformedFeatureAttribute {
     #[primary_span]
     pub span: Span,
@@ -347,7 +348,7 @@ pub(crate) struct ModuleInBlockName {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_module_file_not_found, code = "E0583")]
+#[diag(expand_module_file_not_found, code = E0583)]
 #[help]
 #[note]
 pub(crate) struct ModuleFileNotFound {
@@ -359,7 +360,7 @@ pub(crate) struct ModuleFileNotFound {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_module_multiple_candidates, code = "E0761")]
+#[diag(expand_module_multiple_candidates, code = E0761)]
 #[help]
 pub(crate) struct ModuleMultipleCandidates {
     #[primary_span]
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index 401efff9242e9..c22daad334fc5 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -1,5 +1,5 @@
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -329,7 +329,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
         }
 
         let projection_ty = if let ty::AssocKind::Fn = assoc_kind {
-            let mut emitted_bad_param_err = false;
+            let mut emitted_bad_param_err = None;
             // If we have an method return type bound, then we need to substitute
             // the method's early bound params with suitable late-bound params.
             let mut num_bound_vars = candidate.bound_vars().len();
@@ -346,46 +346,30 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                         )
                         .into(),
                         ty::GenericParamDefKind::Type { .. } => {
-                            if !emitted_bad_param_err {
+                            let guar = *emitted_bad_param_err.get_or_insert_with(|| {
                                 tcx.dcx().emit_err(
                                     crate::errors::ReturnTypeNotationIllegalParam::Type {
                                         span: path_span,
                                         param_span: tcx.def_span(param.def_id),
                                     },
-                                );
-                                emitted_bad_param_err = true;
-                            }
-                            Ty::new_bound(
-                                tcx,
-                                ty::INNERMOST,
-                                ty::BoundTy {
-                                    var: ty::BoundVar::from_usize(num_bound_vars),
-                                    kind: ty::BoundTyKind::Param(param.def_id, param.name),
-                                },
-                            )
-                            .into()
+                                )
+                            });
+                            Ty::new_error(tcx, guar).into()
                         }
                         ty::GenericParamDefKind::Const { .. } => {
-                            if !emitted_bad_param_err {
+                            let guar = *emitted_bad_param_err.get_or_insert_with(|| {
                                 tcx.dcx().emit_err(
                                     crate::errors::ReturnTypeNotationIllegalParam::Const {
                                         span: path_span,
                                         param_span: tcx.def_span(param.def_id),
                                     },
-                                );
-                                emitted_bad_param_err = true;
-                            }
+                                )
+                            });
                             let ty = tcx
                                 .type_of(param.def_id)
                                 .no_bound_vars()
                                 .expect("ct params cannot have early bound vars");
-                            ty::Const::new_bound(
-                                tcx,
-                                ty::INNERMOST,
-                                ty::BoundVar::from_usize(num_bound_vars),
-                                ty,
-                            )
-                            .into()
+                            ty::Const::new_error(tcx, guar, ty).into()
                         }
                     };
                     num_bound_vars += 1;
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index bfe88df4e1a55..5e9076243f8be 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -7,7 +7,9 @@ use crate::fluent_generated as fluent;
 use crate::traits::error_reporting::report_object_safety_error;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
 use rustc_data_structures::unord::UnordMap;
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed};
+use rustc_errors::{
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed,
+};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::traits::FulfillmentError;
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index f9628d1d6f3ef..7fd1dfa011d4c 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -5,7 +5,9 @@ use crate::astconv::{
 };
 use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
 use rustc_ast::ast::ParamKindOrd;
-use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{
+    codes::*, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan,
+};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs
index b5f42e98127ee..70922bef74ade 100644
--- a/compiler/rustc_hir_analysis/src/astconv/lint.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs
@@ -1,5 +1,5 @@
 use rustc_ast::TraitObjectSyntax;
-use rustc_errors::{Diagnostic, StashKey};
+use rustc_errors::{codes::*, Diagnostic, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 00f0d6e7c2241..0cebc72f84f98 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -18,8 +18,8 @@ use crate::require_c_abi_if_c_variadic;
 use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{
-    error_code, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
-    ErrorGuaranteed, FatalError, MultiSpan,
+    codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+    FatalError, MultiSpan,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
@@ -1072,9 +1072,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 if let Some(binding) = binding
                     && let ConvertedBindingKind::Equality(_) = binding.kind
                 {
-                    error_code!(E0222)
+                    E0222
                 } else {
-                    error_code!(E0221)
+                    E0221
                 },
             );
 
@@ -1630,7 +1630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             let reported = tcx
                 .dcx()
                 .struct_span_err(span, msg)
-                .with_code(rustc_errors::error_code!(E0624))
+                .with_code(E0624)
                 .with_span_label(span, format!("private {kind}"))
                 .with_span_label(def_span, format!("{kind} defined here"))
                 .emit();
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
index 8967b51749c82..370837c375da7 100644
--- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -2,7 +2,7 @@ use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBou
 use crate::bounds::Bounds;
 use crate::errors::TraitObjectDeclaredWithNoTraits;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 03e2b0e00220e..1988661e9135b 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -5,7 +5,7 @@ use super::compare_impl_item::check_type_bounds;
 use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
 use super::*;
 use rustc_attr as attr;
-use rustc_errors::{ErrorGuaranteed, MultiSpan};
+use rustc_errors::{codes::*, ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{DefId, LocalDefId};
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 5b264f6f034c9..d49bedcd5b6e1 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -2,7 +2,7 @@ use super::potentially_plural_count;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
 use hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
+use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
@@ -1382,7 +1382,7 @@ fn compare_number_of_generics<'tcx>(
                     kind = kind,
                 ),
             );
-            err.code("E0049".into());
+            err.code(E0049);
 
             let msg =
                 format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),);
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 3275a81c3ddc7..9fe95487bb9e0 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -2,7 +2,7 @@
 //
 // We don't do any drop checking during hir typeck.
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{struct_span_code_err, ErrorGuaranteed};
+use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
 use rustc_middle::ty::util::CheckRegions;
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 7c3e296dfceec..3741bdef7d6bc 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -8,7 +8,7 @@ use crate::errors::{
 };
 
 use hir::def_id::DefId;
-use rustc_errors::{struct_span_code_err, DiagnosticMessage};
+use rustc_errors::{codes::*, struct_span_code_err, DiagnosticMessage};
 use rustc_hir as hir;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::{self, Ty, TyCtxt};
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 70213ee0614f8..0978a5e65969a 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -4,7 +4,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_errors::{
-    pluralize, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
+    codes::*, pluralize, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
 };
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index 63ea02720145e..951440d6a2d0b 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -1,5 +1,5 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 561a254e89ef7..b63b086adc173 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -6,7 +6,7 @@
 // mappings. That mapping code resides here.
 
 use crate::errors;
-use rustc_errors::{error_code, struct_span_code_err};
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
@@ -56,7 +56,7 @@ fn enforce_trait_manually_implementable(
         // Maintain explicit error code for `Unsize`, since it has a useful
         // explanation about using `CoerceUnsized` instead.
         if Some(trait_def_id) == tcx.lang_items().unsize_trait() {
-            err.code(error_code!(E0328));
+            err.code(E0328);
         }
 
         err.emit();
diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index 7b146573a1b3b..f31d5d0fa50f6 100644
--- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -1,7 +1,7 @@
 //! Unsafety checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::Unsafety;
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 4f049f699e6c8..7c1ea13d3a0ed 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -8,7 +8,7 @@
 
 use rustc_ast::walk_list;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index f14390b77c6e2..e5871276d6414 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -2,8 +2,8 @@
 
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
-    Level, MultiSpan,
+    codes::*, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
+    MultiSpan,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::Ty;
@@ -52,7 +52,7 @@ pub struct AssocKindMismatchWrapInBracesSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_assoc_item_not_found, code = "E0220")]
+#[diag(hir_analysis_assoc_item_not_found, code = E0220)]
 pub struct AssocItemNotFound<'a> {
     #[primary_span]
     pub span: Span,
@@ -122,7 +122,7 @@ pub enum AssocItemNotFoundSugg<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_unrecognized_atomic_operation, code = "E0092")]
+#[diag(hir_analysis_unrecognized_atomic_operation, code = E0092)]
 pub struct UnrecognizedAtomicOperation<'a> {
     #[primary_span]
     #[label]
@@ -131,7 +131,7 @@ pub struct UnrecognizedAtomicOperation<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
+#[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = E0094)]
 pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
     #[primary_span]
     #[label]
@@ -142,7 +142,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_unrecognized_intrinsic_function, code = "E0093")]
+#[diag(hir_analysis_unrecognized_intrinsic_function, code = E0093)]
 pub struct UnrecognizedIntrinsicFunction {
     #[primary_span]
     #[label]
@@ -151,7 +151,7 @@ pub struct UnrecognizedIntrinsicFunction {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
+#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = E0195)]
 pub struct LifetimesOrBoundsMismatchOnTrait {
     #[primary_span]
     #[label]
@@ -178,7 +178,7 @@ pub struct AsyncTraitImplShouldBeAsync {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")]
+#[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)]
 pub struct DropImplOnWrongItem {
     #[primary_span]
     #[label]
@@ -186,7 +186,7 @@ pub struct DropImplOnWrongItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_field_already_declared, code = "E0124")]
+#[diag(hir_analysis_field_already_declared, code = E0124)]
 pub struct FieldAlreadyDeclared {
     pub field_name: Ident,
     #[primary_span]
@@ -197,7 +197,7 @@ pub struct FieldAlreadyDeclared {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_copy_impl_on_type_with_dtor, code = "E0184")]
+#[diag(hir_analysis_copy_impl_on_type_with_dtor, code = E0184)]
 pub struct CopyImplOnTypeWithDtor {
     #[primary_span]
     #[label]
@@ -205,14 +205,14 @@ pub struct CopyImplOnTypeWithDtor {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_multiple_relaxed_default_bounds, code = "E0203")]
+#[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)]
 pub struct MultipleRelaxedDefaultBounds {
     #[primary_span]
     pub spans: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_copy_impl_on_non_adt, code = "E0206")]
+#[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)]
 pub struct CopyImplOnNonAdt {
     #[primary_span]
     #[label]
@@ -228,7 +228,7 @@ pub struct ConstParamTyImplOnNonAdt {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_trait_object_declared_with_no_traits, code = "E0224")]
+#[diag(hir_analysis_trait_object_declared_with_no_traits, code = E0224)]
 pub struct TraitObjectDeclaredWithNoTraits {
     #[primary_span]
     pub span: Span,
@@ -237,14 +237,14 @@ pub struct TraitObjectDeclaredWithNoTraits {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_ambiguous_lifetime_bound, code = "E0227")]
+#[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)]
 pub struct AmbiguousLifetimeBound {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_assoc_type_binding_not_allowed, code = "E0229")]
+#[diag(hir_analysis_assoc_type_binding_not_allowed, code = E0229)]
 pub struct AssocTypeBindingNotAllowed {
     #[primary_span]
     #[label]
@@ -264,7 +264,7 @@ pub struct ParenthesizedFnTraitExpansion {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_typeof_reserved_keyword_used, code = "E0516")]
+#[diag(hir_analysis_typeof_reserved_keyword_used, code = E0516)]
 pub struct TypeofReservedKeywordUsed<'tcx> {
     pub ty: Ty<'tcx>,
     #[primary_span]
@@ -275,7 +275,7 @@ pub struct TypeofReservedKeywordUsed<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_value_of_associated_struct_already_specified, code = "E0719")]
+#[diag(hir_analysis_value_of_associated_struct_already_specified, code = E0719)]
 pub struct ValueOfAssociatedStructAlreadySpecified {
     #[primary_span]
     #[label]
@@ -320,7 +320,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams {
     fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
         let mut err = DiagnosticBuilder::new(dcx, level, fluent::hir_analysis_missing_type_params);
         err.span(self.span);
-        err.code(error_code!(E0393));
+        err.code(E0393);
         err.arg("parameterCount", self.missing_type_params.len());
         err.arg(
             "parameters",
@@ -373,7 +373,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_manual_implementation, code = "E0183")]
+#[diag(hir_analysis_manual_implementation, code = E0183)]
 #[help]
 pub struct ManualImplementation {
     #[primary_span]
@@ -421,7 +421,7 @@ pub struct SelfInImplSelf {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_linkage_type, code = "E0791")]
+#[diag(hir_analysis_linkage_type, code = E0791)]
 pub(crate) struct LinkageType {
     #[primary_span]
     pub span: Span,
@@ -429,7 +429,7 @@ pub(crate) struct LinkageType {
 
 #[derive(Diagnostic)]
 #[help]
-#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = "E0055")]
+#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = E0055)]
 pub struct AutoDerefReachedRecursionLimit<'a> {
     #[primary_span]
     #[label]
@@ -440,7 +440,7 @@ pub struct AutoDerefReachedRecursionLimit<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_where_clause_on_main, code = "E0646")]
+#[diag(hir_analysis_where_clause_on_main, code = E0646)]
 pub(crate) struct WhereClauseOnMain {
     #[primary_span]
     pub span: Span,
@@ -485,7 +485,7 @@ pub(crate) struct StartTargetFeature {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_start_not_async, code = "E0752")]
+#[diag(hir_analysis_start_not_async, code = E0752)]
 pub(crate) struct StartAsync {
     #[primary_span]
     #[label]
@@ -493,7 +493,7 @@ pub(crate) struct StartAsync {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_start_function_where, code = "E0647")]
+#[diag(hir_analysis_start_function_where, code = E0647)]
 pub(crate) struct StartFunctionWhere {
     #[primary_span]
     #[label]
@@ -501,7 +501,7 @@ pub(crate) struct StartFunctionWhere {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_start_function_parameters, code = "E0132")]
+#[diag(hir_analysis_start_function_parameters, code = E0132)]
 pub(crate) struct StartFunctionParameters {
     #[primary_span]
     #[label]
@@ -509,14 +509,14 @@ pub(crate) struct StartFunctionParameters {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_main_function_return_type_generic, code = "E0131")]
+#[diag(hir_analysis_main_function_return_type_generic, code = E0131)]
 pub(crate) struct MainFunctionReturnTypeGeneric {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_main_function_async, code = "E0752")]
+#[diag(hir_analysis_main_function_async, code = E0752)]
 pub(crate) struct MainFunctionAsync {
     #[primary_span]
     pub span: Span,
@@ -525,7 +525,7 @@ pub(crate) struct MainFunctionAsync {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_main_function_generic_parameters, code = "E0131")]
+#[diag(hir_analysis_main_function_generic_parameters, code = E0131)]
 pub(crate) struct MainFunctionGenericParameters {
     #[primary_span]
     pub span: Span,
@@ -534,7 +534,7 @@ pub(crate) struct MainFunctionGenericParameters {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_variadic_function_compatible_convention, code = "E0045")]
+#[diag(hir_analysis_variadic_function_compatible_convention, code = E0045)]
 pub(crate) struct VariadicFunctionCompatibleConvention<'a> {
     #[primary_span]
     #[label]
@@ -587,7 +587,7 @@ pub(crate) struct TypeOf<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_pass_to_variadic_function, code = "E0617")]
+#[diag(hir_analysis_pass_to_variadic_function, code = E0617)]
 pub(crate) struct PassToVariadicFunction<'tcx, 'a> {
     #[primary_span]
     pub span: Span,
@@ -601,7 +601,7 @@ pub(crate) struct PassToVariadicFunction<'tcx, 'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_cast_thin_pointer_to_fat_pointer, code = "E0607")]
+#[diag(hir_analysis_cast_thin_pointer_to_fat_pointer, code = E0607)]
 pub(crate) struct CastThinPointerToFatPointer<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -610,7 +610,7 @@ pub(crate) struct CastThinPointerToFatPointer<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_invalid_union_field, code = "E0740")]
+#[diag(hir_analysis_invalid_union_field, code = E0740)]
 pub(crate) struct InvalidUnionField {
     #[primary_span]
     pub field_span: Span,
@@ -649,7 +649,7 @@ pub(crate) struct ReturnTypeNotationEqualityBound {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")]
+#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = E0121)]
 pub(crate) struct PlaceholderNotAllowedItemSignatures {
     #[primary_span]
     #[label]
@@ -658,7 +658,7 @@ pub(crate) struct PlaceholderNotAllowedItemSignatures {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = "E0212")]
+#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = E0212)]
 pub(crate) struct AssociatedTypeTraitUninferredGenericParams {
     #[primary_span]
     pub span: Span,
@@ -684,7 +684,7 @@ pub(crate) struct AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_enum_discriminant_overflowed, code = "E0370")]
+#[diag(hir_analysis_enum_discriminant_overflowed, code = E0370)]
 #[note]
 pub(crate) struct EnumDiscriminantOverflowed {
     #[primary_span]
@@ -774,7 +774,7 @@ pub(crate) struct SIMDFFIHighlyExperimental {
 
 #[derive(Diagnostic)]
 pub enum ImplNotMarkedDefault {
-    #[diag(hir_analysis_impl_not_marked_default, code = "E0520")]
+    #[diag(hir_analysis_impl_not_marked_default, code = E0520)]
     #[note]
     Ok {
         #[primary_span]
@@ -784,7 +784,7 @@ pub enum ImplNotMarkedDefault {
         ok_label: Span,
         ident: Symbol,
     },
-    #[diag(hir_analysis_impl_not_marked_default_err, code = "E0520")]
+    #[diag(hir_analysis_impl_not_marked_default_err, code = E0520)]
     #[note]
     Err {
         #[primary_span]
@@ -795,7 +795,7 @@ pub enum ImplNotMarkedDefault {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_missing_trait_item, code = "E0046")]
+#[diag(hir_analysis_missing_trait_item, code = E0046)]
 pub(crate) struct MissingTraitItem {
     #[primary_span]
     #[label]
@@ -846,7 +846,7 @@ pub(crate) struct MissingTraitItemSuggestionNone {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_missing_one_of_trait_item, code = "E0046")]
+#[diag(hir_analysis_missing_one_of_trait_item, code = E0046)]
 pub(crate) struct MissingOneOfTraitItem {
     #[primary_span]
     #[label]
@@ -857,7 +857,7 @@ pub(crate) struct MissingOneOfTraitItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_missing_trait_item_unstable, code = "E0046")]
+#[diag(hir_analysis_missing_trait_item_unstable, code = E0046)]
 #[note]
 pub(crate) struct MissingTraitItemUnstable {
     #[primary_span]
@@ -872,7 +872,7 @@ pub(crate) struct MissingTraitItemUnstable {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_transparent_enum_variant, code = "E0731")]
+#[diag(hir_analysis_transparent_enum_variant, code = E0731)]
 pub(crate) struct TransparentEnumVariant {
     #[primary_span]
     #[label]
@@ -886,7 +886,7 @@ pub(crate) struct TransparentEnumVariant {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_transparent_non_zero_sized_enum, code = "E0690")]
+#[diag(hir_analysis_transparent_non_zero_sized_enum, code = E0690)]
 pub(crate) struct TransparentNonZeroSizedEnum<'a> {
     #[primary_span]
     #[label]
@@ -898,7 +898,7 @@ pub(crate) struct TransparentNonZeroSizedEnum<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_transparent_non_zero_sized, code = "E0690")]
+#[diag(hir_analysis_transparent_non_zero_sized, code = E0690)]
 pub(crate) struct TransparentNonZeroSized<'a> {
     #[primary_span]
     #[label]
@@ -1045,7 +1045,7 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_ty_outside, code = "E0390")]
+#[diag(hir_analysis_inherent_ty_outside, code = E0390)]
 #[help]
 pub struct InherentTyOutside {
     #[primary_span]
@@ -1054,7 +1054,7 @@ pub struct InherentTyOutside {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0378")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0378)]
 pub struct DispatchFromDynCoercion<'a> {
     #[primary_span]
     pub span: Span,
@@ -1066,14 +1066,14 @@ pub struct DispatchFromDynCoercion<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_dispatch_from_dyn_repr, code = "E0378")]
+#[diag(hir_analysis_dispatch_from_dyn_repr, code = E0378)]
 pub struct DispatchFromDynRepr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_ty_outside_relevant, code = "E0390")]
+#[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)]
 #[help]
 pub struct InherentTyOutsideRelevant {
     #[primary_span]
@@ -1083,7 +1083,7 @@ pub struct InherentTyOutsideRelevant {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_ty_outside_new, code = "E0116")]
+#[diag(hir_analysis_inherent_ty_outside_new, code = E0116)]
 #[note]
 pub struct InherentTyOutsideNew {
     #[primary_span]
@@ -1092,7 +1092,7 @@ pub struct InherentTyOutsideNew {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_ty_outside_primitive, code = "E0390")]
+#[diag(hir_analysis_inherent_ty_outside_primitive, code = E0390)]
 #[help]
 pub struct InherentTyOutsidePrimitive {
     #[primary_span]
@@ -1102,7 +1102,7 @@ pub struct InherentTyOutsidePrimitive {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_primitive_ty, code = "E0390")]
+#[diag(hir_analysis_inherent_primitive_ty, code = E0390)]
 #[help]
 pub struct InherentPrimitiveTy<'a> {
     #[primary_span]
@@ -1118,7 +1118,7 @@ pub struct InherentPrimitiveTyNote<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_dyn, code = "E0785")]
+#[diag(hir_analysis_inherent_dyn, code = E0785)]
 #[note]
 pub struct InherentDyn {
     #[primary_span]
@@ -1127,7 +1127,7 @@ pub struct InherentDyn {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_nominal, code = "E0118")]
+#[diag(hir_analysis_inherent_nominal, code = E0118)]
 #[note]
 pub struct InherentNominal {
     #[primary_span]
@@ -1136,7 +1136,7 @@ pub struct InherentNominal {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_dispatch_from_dyn_zst, code = "E0378")]
+#[diag(hir_analysis_dispatch_from_dyn_zst, code = E0378)]
 #[note]
 pub struct DispatchFromDynZST<'a> {
     #[primary_span]
@@ -1146,7 +1146,7 @@ pub struct DispatchFromDynZST<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0378")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0378)]
 pub struct DispatchFromDynSingle<'a> {
     #[primary_span]
     pub span: Span,
@@ -1156,7 +1156,7 @@ pub struct DispatchFromDynSingle<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_dispatch_from_dyn_multi, code = "E0378")]
+#[diag(hir_analysis_dispatch_from_dyn_multi, code = E0378)]
 #[note]
 pub struct DispatchFromDynMulti {
     #[primary_span]
@@ -1168,7 +1168,7 @@ pub struct DispatchFromDynMulti {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0376")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0376)]
 pub struct DispatchFromDynStruct<'a> {
     #[primary_span]
     pub span: Span,
@@ -1176,7 +1176,7 @@ pub struct DispatchFromDynStruct<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0377")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0377)]
 pub struct DispatchFromDynSame<'a> {
     #[primary_span]
     pub span: Span,
@@ -1188,7 +1188,7 @@ pub struct DispatchFromDynSame<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0374")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0374)]
 pub struct CoerceUnsizedOneField<'a> {
     #[primary_span]
     pub span: Span,
@@ -1198,7 +1198,7 @@ pub struct CoerceUnsizedOneField<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_multi, code = "E0375")]
+#[diag(hir_analysis_coerce_unsized_multi, code = E0375)]
 #[note]
 pub struct CoerceUnsizedMulti {
     #[primary_span]
@@ -1211,7 +1211,7 @@ pub struct CoerceUnsizedMulti {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0378")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0378)]
 pub struct CoerceUnsizedMay<'a> {
     #[primary_span]
     pub span: Span,
@@ -1219,7 +1219,7 @@ pub struct CoerceUnsizedMay<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_trait_cannot_impl_for_ty, code = "E0204")]
+#[diag(hir_analysis_trait_cannot_impl_for_ty, code = E0204)]
 pub struct TraitCannotImplForTy {
     #[primary_span]
     pub span: Span,
@@ -1241,7 +1241,7 @@ pub struct ImplForTyRequires {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_traits_with_defualt_impl, code = "E0321")]
+#[diag(hir_analysis_traits_with_defualt_impl, code = E0321)]
 #[note]
 pub struct TraitsWithDefaultImpl<'a> {
     #[primary_span]
@@ -1252,7 +1252,7 @@ pub struct TraitsWithDefaultImpl<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_cross_crate_traits, code = "E0321")]
+#[diag(hir_analysis_cross_crate_traits, code = E0321)]
 pub struct CrossCrateTraits<'a> {
     #[primary_span]
     #[label]
@@ -1262,7 +1262,7 @@ pub struct CrossCrateTraits<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_cross_crate_traits_defined, code = "E0321")]
+#[diag(hir_analysis_cross_crate_traits_defined, code = E0321)]
 pub struct CrossCrateTraitsDefined {
     #[primary_span]
     #[label]
@@ -1271,7 +1271,7 @@ pub struct CrossCrateTraitsDefined {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_ty_param_first_local, code = "E0210")]
+#[diag(hir_analysis_ty_param_first_local, code = E0210)]
 #[note]
 pub struct TyParamFirstLocal<'a> {
     #[primary_span]
@@ -1284,7 +1284,7 @@ pub struct TyParamFirstLocal<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_ty_param_some, code = "E0210")]
+#[diag(hir_analysis_ty_param_some, code = E0210)]
 #[note]
 pub struct TyParamSome<'a> {
     #[primary_span]
@@ -1297,7 +1297,7 @@ pub struct TyParamSome<'a> {
 
 #[derive(Diagnostic)]
 pub enum OnlyCurrentTraits<'a> {
-    #[diag(hir_analysis_only_current_traits_outside, code = "E0117")]
+    #[diag(hir_analysis_only_current_traits_outside, code = E0117)]
     Outside {
         #[primary_span]
         #[label(hir_analysis_only_current_traits_label)]
@@ -1317,7 +1317,7 @@ pub enum OnlyCurrentTraits<'a> {
         #[subdiagnostic]
         sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
     },
-    #[diag(hir_analysis_only_current_traits_primitive, code = "E0117")]
+    #[diag(hir_analysis_only_current_traits_primitive, code = E0117)]
     Primitive {
         #[primary_span]
         #[label(hir_analysis_only_current_traits_label)]
@@ -1337,7 +1337,7 @@ pub enum OnlyCurrentTraits<'a> {
         #[subdiagnostic]
         sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
     },
-    #[diag(hir_analysis_only_current_traits_arbitrary, code = "E0117")]
+    #[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)]
     Arbitrary {
         #[primary_span]
         #[label(hir_analysis_only_current_traits_label)]
@@ -1412,7 +1412,7 @@ pub struct OnlyCurrentTraitsPointerSugg<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_static_mut_ref, code = "E0796")]
+#[diag(hir_analysis_static_mut_ref, code = E0796)]
 #[note]
 pub struct StaticMutRef {
     #[primary_span]
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 2fe08ead72b2a..c072891e2952e 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -12,7 +12,7 @@ use crate::constrained_generic_params as cgp;
 use min_specialization::check_min_specialization;
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{LocalDefId, LocalModDefId};
 use rustc_middle::query::Providers;
diff --git a/compiler/rustc_hir_analysis/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs
index b061d6371388f..6846e4defe5e5 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors.rs
@@ -6,18 +6,18 @@ pub use self::{
     missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*,
 };
 
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{DiagnosticBuilder, ErrCode};
 use rustc_session::Session;
 
 pub trait StructuredDiagnostic<'tcx> {
     fn session(&self) -> &Session;
 
-    fn code(&self) -> String;
+    fn code(&self) -> ErrCode;
 
     fn diagnostic(&self) -> DiagnosticBuilder<'tcx> {
         let err = self.diagnostic_common();
 
-        if self.session().teach(&self.code()) {
+        if self.session().teach(self.code()) {
             self.diagnostic_extended(err)
         } else {
             self.diagnostic_regular(err)
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
index 6f4435db41143..50b4ef623ac7e 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
@@ -1,5 +1,5 @@
 use crate::{errors, structured_errors::StructuredDiagnostic};
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{codes::*, DiagnosticBuilder, ErrCode};
 use rustc_middle::ty::{Ty, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::Span;
@@ -16,8 +16,8 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> {
         self.sess
     }
 
-    fn code(&self) -> String {
-        rustc_errors::error_code!(E0617)
+    fn code(&self) -> ErrCode {
+        E0617
     }
 
     fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
index 19cac4a38aaab..54d54a2af93a6 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
@@ -1,5 +1,5 @@
 use crate::{errors, structured_errors::StructuredDiagnostic};
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{codes::*, DiagnosticBuilder, ErrCode};
 use rustc_middle::ty::{Ty, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::Span;
@@ -16,8 +16,8 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
         self.sess
     }
 
-    fn code(&self) -> String {
-        rustc_errors::error_code!(E0607)
+    fn code(&self) -> ErrCode {
+        E0607
     }
 
     fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index ba81e7f1f8165..501915d2e7e53 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -1,5 +1,7 @@
 use crate::structured_errors::StructuredDiagnostic;
-use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
+use rustc_errors::{
+    codes::*, pluralize, Applicability, Diagnostic, DiagnosticBuilder, ErrCode, MultiSpan,
+};
 use rustc_hir as hir;
 use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt};
 use rustc_session::Session;
@@ -1105,8 +1107,8 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
         self.tcx.sess
     }
 
-    fn code(&self) -> String {
-        rustc_errors::error_code!(E0107)
+    fn code(&self) -> ErrCode {
+        E0107
     }
 
     fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index a720a858f3c13..031184a0f5e1c 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -33,7 +33,7 @@ use super::FnCtxt;
 use crate::errors;
 use crate::type_error_struct;
 use hir::ExprKind;
-use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{codes::*, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_macros::{TypeFoldable, TypeVisitable};
 use rustc_middle::mir::Mutability;
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index e9d373119fa4d..de257db0b6dbc 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -36,7 +36,9 @@
 //! ```
 
 use crate::FnCtxt;
-use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
+use rustc_errors::{
+    codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan,
+};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, Visitor};
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 4f92906888796..b75cf4b4e8bca 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -3,8 +3,8 @@ use std::borrow::Cow;
 
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, MultiSpan,
-    SubdiagnosticMessage,
+    codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg,
+    MultiSpan, SubdiagnosticMessage,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::Ty;
@@ -15,7 +15,7 @@ use rustc_span::{
 };
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_field_multiply_specified_in_initializer, code = "E0062")]
+#[diag(hir_typeck_field_multiply_specified_in_initializer, code = E0062)]
 pub struct FieldMultiplySpecifiedInInitializer {
     #[primary_span]
     #[label]
@@ -26,7 +26,7 @@ pub struct FieldMultiplySpecifiedInInitializer {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_return_stmt_outside_of_fn_body, code = "E0572")]
+#[diag(hir_typeck_return_stmt_outside_of_fn_body, code = E0572)]
 pub struct ReturnStmtOutsideOfFnBody {
     #[primary_span]
     pub span: Span,
@@ -62,14 +62,14 @@ pub struct RustCallIncorrectArgs {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_yield_expr_outside_of_coroutine, code = "E0627")]
+#[diag(hir_typeck_yield_expr_outside_of_coroutine, code = E0627)]
 pub struct YieldExprOutsideOfCoroutine {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_struct_expr_non_exhaustive, code = "E0639")]
+#[diag(hir_typeck_struct_expr_non_exhaustive, code = E0639)]
 pub struct StructExprNonExhaustive {
     #[primary_span]
     pub span: Span,
@@ -77,7 +77,7 @@ pub struct StructExprNonExhaustive {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_method_call_on_unknown_raw_pointee, code = "E0699")]
+#[diag(hir_typeck_method_call_on_unknown_raw_pointee, code = E0699)]
 pub struct MethodCallOnUnknownRawPointee {
     #[primary_span]
     pub span: Span,
@@ -92,14 +92,14 @@ pub struct MissingFnLangItems {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_functional_record_update_on_non_struct, code = "E0436")]
+#[diag(hir_typeck_functional_record_update_on_non_struct, code = E0436)]
 pub struct FunctionalRecordUpdateOnNonStruct {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_address_of_temporary_taken, code = "E0745")]
+#[diag(hir_typeck_address_of_temporary_taken, code = E0745)]
 pub struct AddressOfTemporaryTaken {
     #[primary_span]
     #[label]
@@ -145,7 +145,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_explicit_destructor, code = "E0040")]
+#[diag(hir_typeck_explicit_destructor, code = E0040)]
 pub struct ExplicitDestructorCall {
     #[primary_span]
     #[label]
@@ -168,7 +168,7 @@ pub enum ExplicitDestructorCallSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_missing_parentheses_in_range, code = "E0689")]
+#[diag(hir_typeck_missing_parentheses_in_range, code = E0689)]
 pub struct MissingParenthesesInRange {
     #[primary_span]
     #[label(hir_typeck_missing_parentheses_in_range)]
@@ -321,7 +321,7 @@ impl HelpUseLatestEdition {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_invalid_callee, code = "E0618")]
+#[diag(hir_typeck_invalid_callee, code = E0618)]
 pub struct InvalidCallee {
     #[primary_span]
     pub span: Span,
@@ -329,7 +329,7 @@ pub struct InvalidCallee {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_int_to_fat, code = "E0606")]
+#[diag(hir_typeck_int_to_fat, code = E0606)]
 pub struct IntToWide<'tcx> {
     #[primary_span]
     #[label(hir_typeck_int_to_fat_label)]
@@ -510,7 +510,7 @@ pub struct TrivialCast<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_no_associated_item, code = "E0599")]
+#[diag(hir_typeck_no_associated_item, code = E0599)]
 pub struct NoAssociatedItem {
     #[primary_span]
     pub span: Span,
@@ -532,7 +532,7 @@ pub struct CandidateTraitNote {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_cannot_cast_to_bool, code = "E0054")]
+#[diag(hir_typeck_cannot_cast_to_bool, code = E0054)]
 pub struct CannotCastToBool<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -549,7 +549,7 @@ pub struct CastEnumDrop<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_cast_unknown_pointer, code = "E0641")]
+#[diag(hir_typeck_cast_unknown_pointer, code = E0641)]
 pub struct CastUnknownPointer {
     #[primary_span]
     pub span: Span,
@@ -600,7 +600,7 @@ pub enum CannotCastToBoolHelp {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_ctor_is_private, code = "E0603")]
+#[diag(hir_typeck_ctor_is_private, code = E0603)]
 pub struct CtorIsPrivate {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index aca17ec77a4bb..62f9155fbae87 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -25,8 +25,8 @@ use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
-    pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
-    ErrorGuaranteed, StashKey,
+    codes::*, pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diagnostic,
+    DiagnosticBuilder, ErrCode, ErrorGuaranteed, StashKey,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -520,7 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Ty::new_error(tcx, e)
             }
             Res::Def(DefKind::Variant, _) => {
-                let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, "E0533", "value");
+                let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, E0533, "value");
                 Ty::new_error(tcx, e)
             }
             _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
@@ -932,7 +932,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(crate) fn check_lhs_assignable(
         &self,
         lhs: &'tcx hir::Expr<'tcx>,
-        err_code: &'static str,
+        code: ErrCode,
         op_span: Span,
         adjust_err: impl FnOnce(&mut Diagnostic),
     ) {
@@ -941,7 +941,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment");
-        err.code(err_code.into());
+        err.code(code);
         err.span_label(lhs.span, "cannot assign to this expression");
 
         self.comes_from_while_condition(lhs.hir_id, |expr| {
@@ -1237,7 +1237,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             diag.emit();
         }
 
-        self.check_lhs_assignable(lhs, "E0070", span, |err| {
+        self.check_lhs_assignable(lhs, E0070, span, |err| {
             if let Some(rhs_ty) = self.typeck_results.borrow().expr_ty_opt(rhs) {
                 suggest_deref_binop(err, rhs_ty);
             }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index ddb4224b60db1..b57795d0ad59f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -12,7 +12,9 @@ use crate::{
 use itertools::Itertools;
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{pluralize, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey};
+use rustc_errors::{
+    codes::*, pluralize, Applicability, Diagnostic, ErrCode, ErrorGuaranteed, MultiSpan, StashKey,
+};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -177,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
         }
 
-        let mut err_code = "E0061";
+        let mut err_code = E0061;
 
         // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
         let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
@@ -187,7 +189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ty::Tuple(arg_types) => {
                     // Argument length differs
                     if arg_types.len() != provided_args.len() {
-                        err_code = "E0057";
+                        err_code = E0057;
                     }
                     let expected_input_tys = match expected_input_tys {
                         Some(expected_input_tys) => match expected_input_tys.get(0) {
@@ -358,7 +360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if c_variadic && provided_arg_count < minimum_input_count {
-            err_code = "E0060";
+            err_code = E0060;
         }
 
         for arg in provided_args.iter().skip(minimum_input_count) {
@@ -443,7 +445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
         provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
         c_variadic: bool,
-        err_code: &str,
+        err_code: ErrCode,
         fn_def_id: Option<DefId>,
         call_span: Span,
         call_expr: &'tcx hir::Expr<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index e087733130e33..2dee5093e876d 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -1,5 +1,5 @@
 use hir::HirId;
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_index::Idx;
 use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 80467ca9381e3..ba77289b58357 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -52,7 +52,7 @@ use crate::expectation::Expectation;
 use crate::fn_ctxt::RawTy;
 use crate::gather_locals::GatherLocalsVisitor;
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{struct_span_code_err, ErrorGuaranteed};
+use rustc_errors::{codes::*, struct_span_code_err, ErrCode, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::Visitor;
@@ -72,7 +72,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
 #[macro_export]
 macro_rules! type_error_struct {
-    ($dcx:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
+    ($dcx:expr, $span:expr, $typ:expr, $code:expr, $($message:tt)*) => ({
         let mut err = rustc_errors::struct_span_code_err!($dcx, $span, $code, $($message)*);
 
         if $typ.references_error() {
@@ -376,7 +376,7 @@ fn report_unexpected_variant_res(
     res: Res,
     qpath: &hir::QPath<'_>,
     span: Span,
-    err_code: &str,
+    err_code: ErrCode,
     expected: &str,
 ) -> ErrorGuaranteed {
     let res_descr = match res {
@@ -387,9 +387,9 @@ fn report_unexpected_variant_res(
     let err = tcx
         .dcx()
         .struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
-        .with_code(err_code.into());
+        .with_code(err_code);
     match res {
-        Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => {
+        Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == E0164 => {
             let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html";
             err.with_span_label(span, "`fn` calls are not allowed in patterns")
                 .with_help(format!("for more information, visit {patterns_url}"))
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 0b8a25eedafad..70a076c768ddb 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -3,17 +3,16 @@
 
 // ignore-tidy-filelength
 
-use crate::errors;
-use crate::errors::{CandidateTraitNote, NoAssociatedItem};
+use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
 use crate::Expectation;
 use crate::FnCtxt;
 use rustc_ast::ast::Mutability;
 use rustc_attr::parse_confusables;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::StashKey;
 use rustc_errors::{
-    pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan,
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
+    MultiSpan, StashKey,
 };
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index ee411f8ed5f1c..c16a724f43085 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -4,7 +4,7 @@ use super::method::MethodCallee;
 use super::{has_expected_num_generic_args, FnCtxt};
 use crate::Expectation;
 use rustc_ast as ast;
-use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::traits::ObligationCauseCode;
@@ -43,7 +43,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return_ty
             };
 
-        self.check_lhs_assignable(lhs, "E0067", op.span, |err| {
+        self.check_lhs_assignable(lhs, E0067, op.span, |err| {
             if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) {
                 if self
                     .lookup_op_method(
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 3710686727703..0e83d29df9d27 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -3,8 +3,8 @@ use crate::{errors, FnCtxt, RawTy};
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{
-    pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
-    MultiSpan,
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
+    ErrorGuaranteed, MultiSpan,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -576,7 +576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if (lhs, rhs).references_error() {
             err.downgrade_to_delayed_bug();
         }
-        if self.tcx.sess.teach(&err.get_code().unwrap()) {
+        if self.tcx.sess.teach(err.get_code().unwrap()) {
             err.note(
                 "In a match expression, only numbers and characters can be matched \
                     against a range. This is because the compiler checks that the range \
@@ -847,7 +847,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 type_str
             );
             err.span_label(span, format!("type `{type_str}` cannot be dereferenced"));
-            if self.tcx.sess.teach(&err.get_code().unwrap()) {
+            if self.tcx.sess.teach(err.get_code().unwrap()) {
                 err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ);
             }
             return Err(err.emit());
@@ -907,7 +907,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
                 let expected = "unit struct, unit variant or constant";
-                let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0533", expected);
+                let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, E0533, expected);
                 return Ty::new_error(tcx, e);
             }
             Res::SelfCtor(..)
@@ -1061,7 +1061,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
         let report_unexpected_res = |res: Res| {
             let expected = "tuple struct or tuple variant";
-            let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0164", expected);
+            let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, E0164, expected);
             on_error(e);
             e
         };
@@ -1669,7 +1669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
         }
-        if tcx.sess.teach(&err.get_code().unwrap()) {
+        if tcx.sess.teach(err.get_code().unwrap()) {
             err.note(
                 "This error indicates that a struct pattern attempted to \
                  extract a nonexistent field from a struct. Struct fields \
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index aee99063e0396..4e9f573091b09 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1,7 +1,7 @@
 use hir::GenericParamKind;
 use rustc_errors::{
-    AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
-    IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage,
+    codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage,
+    DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage,
 };
 use rustc_hir as hir;
 use rustc_hir::FnRetTy;
@@ -33,7 +33,7 @@ pub struct OpaqueHiddenTypeDiag {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = "E0282")]
+#[diag(infer_type_annotations_needed, code = E0282)]
 pub struct AnnotationRequired<'a> {
     #[primary_span]
     pub span: Span,
@@ -51,7 +51,7 @@ pub struct AnnotationRequired<'a> {
 
 // Copy of `AnnotationRequired` for E0283
 #[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = "E0283")]
+#[diag(infer_type_annotations_needed, code = E0283)]
 pub struct AmbiguousImpl<'a> {
     #[primary_span]
     pub span: Span,
@@ -69,7 +69,7 @@ pub struct AmbiguousImpl<'a> {
 
 // Copy of `AnnotationRequired` for E0284
 #[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = "E0284")]
+#[diag(infer_type_annotations_needed, code = E0284)]
 pub struct AmbiguousReturn<'a> {
     #[primary_span]
     pub span: Span,
@@ -421,7 +421,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_lifetime_mismatch, code = "E0623")]
+#[diag(infer_lifetime_mismatch, code = E0623)]
 pub struct LifetimeMismatch<'a> {
     #[primary_span]
     pub span: Span,
@@ -495,7 +495,7 @@ pub struct MismatchedStaticLifetime<'a> {
 
 #[derive(Diagnostic)]
 pub enum ExplicitLifetimeRequired<'a> {
-    #[diag(infer_explicit_lifetime_required_with_ident, code = "E0621")]
+    #[diag(infer_explicit_lifetime_required_with_ident, code = E0621)]
     WithIdent {
         #[primary_span]
         #[label]
@@ -511,7 +511,7 @@ pub enum ExplicitLifetimeRequired<'a> {
         #[skip_arg]
         new_ty: Ty<'a>,
     },
-    #[diag(infer_explicit_lifetime_required_with_param_type, code = "E0621")]
+    #[diag(infer_explicit_lifetime_required_with_param_type, code = E0621)]
     WithParamType {
         #[primary_span]
         #[label]
@@ -819,7 +819,7 @@ impl AddToDiagnostic for DynTraitConstraintSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_but_calling_introduces, code = "E0772")]
+#[diag(infer_but_calling_introduces, code = E0772)]
 pub struct ButCallingIntroduces {
     #[label(infer_label1)]
     pub param_ty_span: Span,
@@ -871,14 +871,14 @@ impl AddToDiagnostic for MoreTargeted {
     where
         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
     {
-        diag.code(rustc_errors::error_code!(E0772));
+        diag.code(E0772);
         diag.primary_message(fluent::infer_more_targeted);
         diag.arg("ident", self.ident);
     }
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_but_needs_to_satisfy, code = "E0759")]
+#[diag(infer_but_needs_to_satisfy, code = E0759)]
 pub struct ButNeedsToSatisfy {
     #[primary_span]
     pub sp: Span,
@@ -904,7 +904,7 @@ pub struct ButNeedsToSatisfy {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_outlives_content, code = "E0312")]
+#[diag(infer_outlives_content, code = E0312)]
 pub struct OutlivesContent<'a> {
     #[primary_span]
     pub span: Span,
@@ -913,7 +913,7 @@ pub struct OutlivesContent<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_outlives_bound, code = "E0476")]
+#[diag(infer_outlives_bound, code = E0476)]
 pub struct OutlivesBound<'a> {
     #[primary_span]
     pub span: Span,
@@ -922,7 +922,7 @@ pub struct OutlivesBound<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_fulfill_req_lifetime, code = "E0477")]
+#[diag(infer_fulfill_req_lifetime, code = E0477)]
 pub struct FulfillReqLifetime<'a> {
     #[primary_span]
     pub span: Span,
@@ -932,7 +932,7 @@ pub struct FulfillReqLifetime<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_lf_bound_not_satisfied, code = "E0478")]
+#[diag(infer_lf_bound_not_satisfied, code = E0478)]
 pub struct LfBoundNotSatisfied<'a> {
     #[primary_span]
     pub span: Span,
@@ -941,7 +941,7 @@ pub struct LfBoundNotSatisfied<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_ref_longer_than_data, code = "E0491")]
+#[diag(infer_ref_longer_than_data, code = E0491)]
 pub struct RefLongerThanData<'a> {
     #[primary_span]
     pub span: Span,
@@ -1117,7 +1117,7 @@ pub enum PlaceholderRelationLfNotSatisfied {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_opaque_captures_lifetime, code = "E0700")]
+#[diag(infer_opaque_captures_lifetime, code = E0700)]
 pub struct OpaqueCapturesLifetime<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -1378,73 +1378,73 @@ pub enum TypeErrorAdditionalDiags {
 
 #[derive(Diagnostic)]
 pub enum ObligationCauseFailureCode {
-    #[diag(infer_oc_method_compat, code = "E0308")]
+    #[diag(infer_oc_method_compat, code = E0308)]
     MethodCompat {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_type_compat, code = "E0308")]
+    #[diag(infer_oc_type_compat, code = E0308)]
     TypeCompat {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_const_compat, code = "E0308")]
+    #[diag(infer_oc_const_compat, code = E0308)]
     ConstCompat {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_try_compat, code = "E0308")]
+    #[diag(infer_oc_try_compat, code = E0308)]
     TryCompat {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_match_compat, code = "E0308")]
+    #[diag(infer_oc_match_compat, code = E0308)]
     MatchCompat {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_if_else_different, code = "E0308")]
+    #[diag(infer_oc_if_else_different, code = E0308)]
     IfElseDifferent {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_no_else, code = "E0317")]
+    #[diag(infer_oc_no_else, code = E0317)]
     NoElse {
         #[primary_span]
         span: Span,
     },
-    #[diag(infer_oc_no_diverge, code = "E0308")]
+    #[diag(infer_oc_no_diverge, code = E0308)]
     NoDiverge {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_fn_main_correct_type, code = "E0580")]
+    #[diag(infer_oc_fn_main_correct_type, code = E0580)]
     FnMainCorrectType {
         #[primary_span]
         span: Span,
     },
-    #[diag(infer_oc_fn_start_correct_type, code = "E0308")]
+    #[diag(infer_oc_fn_start_correct_type, code = E0308)]
     FnStartCorrectType {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_fn_lang_correct_type, code = "E0308")]
+    #[diag(infer_oc_fn_lang_correct_type, code = E0308)]
     FnLangCorrectType {
         #[primary_span]
         span: Span,
@@ -1452,33 +1452,33 @@ pub enum ObligationCauseFailureCode {
         subdiags: Vec<TypeErrorAdditionalDiags>,
         lang_item_name: Symbol,
     },
-    #[diag(infer_oc_intrinsic_correct_type, code = "E0308")]
+    #[diag(infer_oc_intrinsic_correct_type, code = E0308)]
     IntrinsicCorrectType {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_method_correct_type, code = "E0308")]
+    #[diag(infer_oc_method_correct_type, code = E0308)]
     MethodCorrectType {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_closure_selfref, code = "E0644")]
+    #[diag(infer_oc_closure_selfref, code = E0644)]
     ClosureSelfref {
         #[primary_span]
         span: Span,
     },
-    #[diag(infer_oc_cant_coerce, code = "E0308")]
+    #[diag(infer_oc_cant_coerce, code = E0308)]
     CantCoerce {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_generic, code = "E0308")]
+    #[diag(infer_oc_generic, code = E0308)]
     Generic {
         #[primary_span]
         span: Span,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 7882e761a0c31..e19177fccefd8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -60,7 +60,7 @@ use crate::traits::{
 
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::{
-    error_code, pluralize, struct_span_code_err, Applicability, DiagCtxt, Diagnostic,
+    codes::*, pluralize, struct_span_code_err, Applicability, DiagCtxt, Diagnostic,
     DiagnosticBuilder, DiagnosticStyledString, ErrorGuaranteed, IntoDiagnosticArg,
 };
 use rustc_hir as hir;
@@ -2362,9 +2362,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             .dcx()
             .struct_span_err(span, format!("{labeled_user_string} may not live long enough"));
         err.code(match sub.kind() {
-            ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => error_code!(E0309),
-            ty::ReStatic => error_code!(E0310),
-            _ => error_code!(E0311),
+            ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => E0309,
+            ty::ReStatic => E0310,
+            _ => E0311,
         });
 
         '_explain: {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 03c8e08aa01ac..cf1e042c529a4 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -5,7 +5,7 @@ use crate::errors::{
 use crate::infer::error_reporting::TypeErrCtxt;
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::InferCtxt;
-use rustc_errors::{DiagnosticBuilder, IntoDiagnosticArg};
+use rustc_errors::{codes::*, DiagnosticBuilder, ErrCode, IntoDiagnosticArg};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
@@ -43,12 +43,12 @@ pub enum TypeAnnotationNeeded {
     E0284,
 }
 
-impl Into<String> for TypeAnnotationNeeded {
-    fn into(self) -> String {
+impl Into<ErrCode> for TypeAnnotationNeeded {
+    fn into(self) -> ErrCode {
         match self {
-            Self::E0282 => rustc_errors::error_code!(E0282),
-            Self::E0283 => rustc_errors::error_code!(E0283),
-            Self::E0284 => rustc_errors::error_code!(E0284),
+            Self::E0282 => E0282,
+            Self::E0283 => E0283,
+            Self::E0284 => E0284,
         }
     }
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index afb3c5c1e5656..8def08d5a04eb 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -195,7 +195,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             }
                         }
                         diag.help("type parameters must be constrained to match other types");
-                        if tcx.sess.teach(&diag.get_code().unwrap()) {
+                        if tcx.sess.teach(diag.get_code().unwrap()) {
                             diag.help(
                                 "given a type parameter `T` and a method `foo`:
 ```
@@ -523,7 +523,7 @@ impl<T> Trait<T> for X {
                  https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
             );
         }
-        if tcx.sess.teach(&diag.get_code().unwrap()) {
+        if tcx.sess.teach(diag.get_code().unwrap()) {
             diag.help(
                 "given an associated type `T` and a method `foo`:
 ```
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index 6f218019dee5a..eabc1b953af1c 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -2,7 +2,7 @@ use super::ObjectSafetyViolation;
 
 use crate::infer::InferCtxt;
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{struct_span_code_err, Applicability, DiagnosticBuilder, MultiSpan};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability, DiagnosticBuilder, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Map;
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index 841d282a09942..3bd0c1b803199 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -1,11 +1,11 @@
 use crate::fluent_generated as fluent;
-use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessage};
+use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessage};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_session::lint::Level;
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
-#[diag(lint_overruled_attribute, code = "E0453")]
+#[diag(lint_overruled_attribute, code = E0453)]
 pub struct OverruledAttribute<'a> {
     #[primary_span]
     pub span: Span,
@@ -48,7 +48,7 @@ impl AddToDiagnostic for OverruledAttributeSub {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint_malformed_attribute, code = "E0452")]
+#[diag(lint_malformed_attribute, code = E0452)]
 pub struct MalformedAttribute {
     #[primary_span]
     pub span: Span,
@@ -67,7 +67,7 @@ pub enum MalformedAttributeSub {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint_unknown_tool_in_scoped_lint, code = "E0710")]
+#[diag(lint_unknown_tool_in_scoped_lint, code = E0710)]
 pub struct UnknownToolInScopedLint {
     #[primary_span]
     pub span: Option<Span>,
@@ -78,7 +78,7 @@ pub struct UnknownToolInScopedLint {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = "E0783")]
+#[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = E0783)]
 pub struct BuiltinEllipsisInclusiveRangePatterns {
     #[primary_span]
     pub span: Span,
@@ -95,13 +95,13 @@ pub struct RequestedLevel<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint_unsupported_group, code = "E0602")]
+#[diag(lint_unsupported_group, code = E0602)]
 pub struct UnsupportedGroup {
     pub lint_group: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(lint_check_name_unknown_tool, code = "E0602")]
+#[diag(lint_check_name_unknown_tool, code = E0602)]
 pub struct CheckNameUnknownTool<'a> {
     pub tool_name: Symbol,
     #[subdiagnostic]
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 65d47b9acc204..d2d7fa7e95fb1 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -5,8 +5,8 @@ use std::num::NonZeroU32;
 use crate::errors::RequestedLevel;
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, DiagnosticMessage,
-    DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle,
+    codes::*, AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder,
+    DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle,
 };
 use rustc_hir::def_id::DefId;
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
@@ -1066,7 +1066,7 @@ pub enum UnknownLintSuggestion {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_unknown_lint, code = "E0602")]
+#[diag(lint_unknown_lint, code = E0602)]
 pub struct UnknownLintFromCommandLine<'a> {
     pub name: String,
     #[subdiagnostic]
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index e917e7cb02b39..e6d837ecd92bd 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2755,6 +2755,11 @@ declare_lint! {
     pub UNSAFE_OP_IN_UNSAFE_FN,
     Allow,
     "unsafe operations in unsafe functions without an explicit unsafe block are deprecated",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
+        reference: "issue #71668 <https://github.com/rust-lang/rust/issues/71668>",
+        explain_reason: false
+    };
     @edition Edition2024 => Warn;
 }
 
@@ -4604,3 +4609,50 @@ declare_lint! {
         reference: "issue #X <https://github.com/rust-lang/rust/issues/X>",
     };
 }
+
+declare_lint! {
+    /// The `private_macro_use` lint detects private macros that are imported
+    /// with `#[macro_use]`.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (needs extern crate)
+    /// // extern_macro.rs
+    /// macro_rules! foo_ { () => {}; }
+    /// use foo_ as foo;
+    ///
+    /// // code.rs
+    ///
+    /// #![deny(private_macro_use)]
+    ///
+    /// #[macro_use]
+    /// extern crate extern_macro;
+    ///
+    /// fn main() {
+    ///     foo!();
+    /// }
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// error: cannot find macro `foo` in this scope
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// This lint arises from overlooking visibility checks for macros
+    /// in an external crate.
+    ///
+    /// This is a [future-incompatible] lint to transition this to a
+    /// hard error in the future.
+    ///
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    pub PRIVATE_MACRO_USE,
+    Warn,
+    "detects certain macro bindings that should not be re-exported",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reference: "issue #120192 <https://github.com/rust-lang/rust/issues/120192>",
+    };
+}
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 0b7ecff8148b3..85bb9584a0575 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -209,9 +209,9 @@ impl DiagnosticDeriveVariantBuilder {
                 if path.is_ident("code") {
                     self.code.set_once((), path.span().unwrap());
 
-                    let code = nested.parse::<syn::LitStr>()?;
+                    let code = nested.parse::<syn::Expr>()?;
                     tokens.extend(quote! {
-                        diag.code(#code.to_string());
+                        diag.code(#code);
                     });
                 } else {
                     span_err(path.span().unwrap(), "unknown argument")
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index d3a4e7ba7d191..2c278ee85c777 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -20,7 +20,7 @@ use synstructure::Structure;
 /// # extern crate rust_middle;
 /// # use rustc_middle::ty::Ty;
 /// #[derive(Diagnostic)]
-/// #[diag(borrowck_move_out_of_borrow, code = "E0505")]
+/// #[diag(borrowck_move_out_of_borrow, code = E0505)]
 /// pub struct MoveOutOfBorrowError<'tcx> {
 ///     pub name: Ident,
 ///     pub ty: Ty<'tcx>,
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index 27c26d3178144..d17bf0cf708f6 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -4,7 +4,7 @@ use std::{
 };
 
 use rustc_errors::{
-    error_code, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
+    codes::*, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
 };
 use rustc_macros::Diagnostic;
 use rustc_session::config;
@@ -122,7 +122,7 @@ pub struct WasmImportForm {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_empty_link_name, code = "E0454")]
+#[diag(metadata_empty_link_name, code = E0454)]
 pub struct EmptyLinkName {
     #[primary_span]
     #[label]
@@ -130,21 +130,21 @@ pub struct EmptyLinkName {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_link_framework_apple, code = "E0455")]
+#[diag(metadata_link_framework_apple, code = E0455)]
 pub struct LinkFrameworkApple {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_framework_only_windows, code = "E0455")]
+#[diag(metadata_framework_only_windows, code = E0455)]
 pub struct FrameworkOnlyWindows {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_unknown_link_kind, code = "E0458")]
+#[diag(metadata_unknown_link_kind, code = E0458)]
 pub struct UnknownLinkKind<'a> {
     #[primary_span]
     #[label]
@@ -239,7 +239,7 @@ pub struct IncompatibleWasmLink {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_link_requires_name, code = "E0459")]
+#[diag(metadata_link_requires_name, code = E0459)]
 pub struct LinkRequiresName {
     #[primary_span]
     #[label]
@@ -502,7 +502,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for MultipleCandidates {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_multiple_candidates);
         diag.arg("crate_name", self.crate_name);
         diag.arg("flavor", self.flavor);
-        diag.code(error_code!(E0464));
+        diag.code(E0464);
         diag.span(self.span);
         for (i, candidate) in self.candidates.iter().enumerate() {
             diag.note(format!("candidate #{}: {}", i + 1, candidate.display()));
@@ -512,7 +512,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for MultipleCandidates {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_symbol_conflicts_current, code = "E0519")]
+#[diag(metadata_symbol_conflicts_current, code = E0519)]
 pub struct SymbolConflictsCurrent {
     #[primary_span]
     pub span: Span,
@@ -537,7 +537,7 @@ pub struct DlError {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_newer_crate_version, code = "E0460")]
+#[diag(metadata_newer_crate_version, code = E0460)]
 #[note]
 #[note(metadata_found_crate_versions)]
 pub struct NewerCrateVersion {
@@ -549,7 +549,7 @@ pub struct NewerCrateVersion {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_no_crate_with_triple, code = "E0461")]
+#[diag(metadata_no_crate_with_triple, code = E0461)]
 #[note(metadata_found_crate_versions)]
 pub struct NoCrateWithTriple<'a> {
     #[primary_span]
@@ -561,7 +561,7 @@ pub struct NoCrateWithTriple<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_found_staticlib, code = "E0462")]
+#[diag(metadata_found_staticlib, code = E0462)]
 #[note(metadata_found_crate_versions)]
 #[help]
 pub struct FoundStaticlib {
@@ -573,7 +573,7 @@ pub struct FoundStaticlib {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_incompatible_rustc, code = "E0514")]
+#[diag(metadata_incompatible_rustc, code = E0514)]
 #[note(metadata_found_crate_versions)]
 #[help]
 pub struct IncompatibleRustc {
@@ -598,7 +598,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for InvalidMetadataFiles {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_invalid_meta_files);
         diag.arg("crate_name", self.crate_name);
         diag.arg("add_info", self.add_info);
-        diag.code(error_code!(E0786));
+        diag.code(E0786);
         diag.span(self.span);
         for crate_rejection in self.crate_rejections {
             diag.note(crate_rejection);
@@ -627,7 +627,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for CannotFindCrate {
         diag.arg("current_crate", self.current_crate);
         diag.arg("add_info", self.add_info);
         diag.arg("locator_triple", self.locator_triple.triple());
-        diag.code(error_code!(E0463));
+        diag.code(E0463);
         diag.span(self.span);
         if (self.crate_name == sym::std || self.crate_name == sym::core)
             && self.locator_triple != TargetTriple::from_triple(config::host_triple())
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 3c5536570872a..e0436b38c4be6 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -1,14 +1,14 @@
 use std::borrow::Cow;
 use std::fmt;
 
-use rustc_errors::{DiagnosticArgValue, DiagnosticMessage};
+use rustc_errors::{codes::*, DiagnosticArgValue, DiagnosticMessage};
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
 
 use crate::ty::Ty;
 
 #[derive(Diagnostic)]
-#[diag(middle_drop_check_overflow, code = "E0320")]
+#[diag(middle_drop_check_overflow, code = E0320)]
 #[note]
 pub struct DropCheckOverflow<'tcx> {
     #[primary_span]
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 6a03bf243eb46..27b48f46e75a2 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -1,7 +1,7 @@
 use crate::dep_graph::dep_kinds;
 use crate::query::plumbing::CyclePlaceholder;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan};
+use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_middle::ty::Representability;
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index e3cc21cef11c7..6929c8040c503 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -1,7 +1,7 @@
 use crate::fluent_generated as fluent;
 use rustc_errors::DiagnosticArgValue;
 use rustc_errors::{
-    error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
+    codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
     IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessage,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -138,7 +138,7 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = "E0133")]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = E0133)]
 #[note]
 pub struct CallToUnsafeFunctionRequiresUnsafe<'a> {
     #[primary_span]
@@ -150,7 +150,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafe<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = "E0133")]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)]
 #[note]
 pub struct CallToUnsafeFunctionRequiresUnsafeNameless {
     #[primary_span]
@@ -161,7 +161,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNameless {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
     #[primary_span]
@@ -175,7 +175,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
 #[derive(Diagnostic)]
 #[diag(
     mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed,
-    code = "E0133"
+    code = E0133
 )]
 #[note]
 pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed {
@@ -187,7 +187,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_inline_assembly_requires_unsafe, code = "E0133")]
+#[diag(mir_build_inline_assembly_requires_unsafe, code = E0133)]
 #[note]
 pub struct UseOfInlineAssemblyRequiresUnsafe {
     #[primary_span]
@@ -198,7 +198,7 @@ pub struct UseOfInlineAssemblyRequiresUnsafe {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
@@ -209,7 +209,7 @@ pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_initializing_type_with_requires_unsafe, code = "E0133")]
+#[diag(mir_build_initializing_type_with_requires_unsafe, code = E0133)]
 #[note]
 pub struct InitializingTypeWithRequiresUnsafe {
     #[primary_span]
@@ -222,7 +222,7 @@ pub struct InitializingTypeWithRequiresUnsafe {
 #[derive(Diagnostic)]
 #[diag(
     mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
-    code = "E0133"
+    code = E0133
 )]
 #[note]
 pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
@@ -234,7 +234,7 @@ pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_mutable_static_requires_unsafe, code = "E0133")]
+#[diag(mir_build_mutable_static_requires_unsafe, code = E0133)]
 #[note]
 pub struct UseOfMutableStaticRequiresUnsafe {
     #[primary_span]
@@ -245,7 +245,7 @@ pub struct UseOfMutableStaticRequiresUnsafe {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
@@ -256,7 +256,7 @@ pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_extern_static_requires_unsafe, code = "E0133")]
+#[diag(mir_build_extern_static_requires_unsafe, code = E0133)]
 #[note]
 pub struct UseOfExternStaticRequiresUnsafe {
     #[primary_span]
@@ -267,7 +267,7 @@ pub struct UseOfExternStaticRequiresUnsafe {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
@@ -278,7 +278,7 @@ pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = "E0133")]
+#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = E0133)]
 #[note]
 pub struct DerefOfRawPointerRequiresUnsafe {
     #[primary_span]
@@ -289,7 +289,7 @@ pub struct DerefOfRawPointerRequiresUnsafe {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
@@ -300,7 +300,7 @@ pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_union_field_requires_unsafe, code = "E0133")]
+#[diag(mir_build_union_field_requires_unsafe, code = E0133)]
 #[note]
 pub struct AccessToUnionFieldRequiresUnsafe {
     #[primary_span]
@@ -311,7 +311,7 @@ pub struct AccessToUnionFieldRequiresUnsafe {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
@@ -322,7 +322,7 @@ pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = "E0133")]
+#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = E0133)]
 #[note]
 pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe {
     #[primary_span]
@@ -335,7 +335,7 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe {
 #[derive(Diagnostic)]
 #[diag(
     mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
-    code = "E0133"
+    code = E0133
 )]
 #[note]
 pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
@@ -347,7 +347,7 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllow
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = "E0133")]
+#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = E0133)]
 #[note]
 pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe {
     #[primary_span]
@@ -360,7 +360,7 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe {
 #[derive(Diagnostic)]
 #[diag(
     mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
-    code = "E0133"
+    code = E0133
 )]
 #[note]
 pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
@@ -372,7 +372,7 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")]
+#[diag(mir_build_call_to_fn_with_requires_unsafe, code = E0133)]
 #[help]
 pub struct CallToFunctionWithRequiresUnsafe<'a> {
     #[primary_span]
@@ -390,7 +390,7 @@ pub struct CallToFunctionWithRequiresUnsafe<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[help]
 pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
     #[primary_span]
@@ -430,7 +430,7 @@ impl AddToDiagnostic for UnsafeNotInheritedLintNote {
         diag.tool_only_multipart_suggestion(
             fluent::mir_build_wrap_suggestion,
             vec![(body_start, "{ unsafe ".into()), (body_end, "}".into())],
-            Applicability::MaybeIncorrect,
+            Applicability::MachineApplicable,
         );
     }
 }
@@ -468,7 +468,7 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
             fluent::mir_build_non_exhaustive_patterns_type_not_empty,
         );
         diag.span(self.span);
-        diag.code(error_code!(E0004));
+        diag.code(E0004);
         let peeled_ty = self.ty.peel_refs();
         diag.arg("ty", self.ty);
         diag.arg("peeled_ty", peeled_ty);
@@ -539,28 +539,28 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
 pub struct NonExhaustiveMatchAllArmsGuarded;
 
 #[derive(Diagnostic)]
-#[diag(mir_build_static_in_pattern, code = "E0158")]
+#[diag(mir_build_static_in_pattern, code = E0158)]
 pub struct StaticInPattern {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_assoc_const_in_pattern, code = "E0158")]
+#[diag(mir_build_assoc_const_in_pattern, code = E0158)]
 pub struct AssocConstInPattern {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_const_param_in_pattern, code = "E0158")]
+#[diag(mir_build_const_param_in_pattern, code = E0158)]
 pub struct ConstParamInPattern {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_non_const_path, code = "E0080")]
+#[diag(mir_build_non_const_path, code = E0080)]
 pub struct NonConstPath {
     #[primary_span]
     pub span: Span,
@@ -590,7 +590,7 @@ pub struct CouldNotEvalConstPattern {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = "E0030")]
+#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = E0030)]
 pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper {
     #[primary_span]
     #[label]
@@ -611,7 +611,7 @@ pub struct LiteralOutOfRange<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = "E0579")]
+#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = E0579)]
 pub struct LowerRangeBoundMustBeLessThanUpper {
     #[primary_span]
     pub span: Span,
@@ -634,7 +634,7 @@ pub struct TrailingIrrefutableLetPatterns {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_bindings_with_variant_name, code = "E0170")]
+#[diag(mir_build_bindings_with_variant_name, code = E0170)]
 pub struct BindingsWithVariantName {
     #[suggestion(code = "{ty_path}::{name}", applicability = "machine-applicable")]
     pub suggestion: Option<Span>,
@@ -821,7 +821,7 @@ pub struct NonPartialEqMatch<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_pattern_not_covered, code = "E0005")]
+#[diag(mir_build_pattern_not_covered, code = E0005)]
 pub(crate) struct PatternNotCovered<'s, 'tcx> {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 693dc49c6e8f3..0c1bfb605e132 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -12,7 +12,7 @@ use rustc_ast::Mutability;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
-    struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
+    codes::*, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
 };
 use rustc_hir as hir;
 use rustc_hir::def::*;
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index ff7e985bdfdcc..2190ad14b5511 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -8,7 +8,7 @@ pub(crate) use self::check_match::check_match;
 use crate::errors::*;
 use crate::thir::util::UserAnnotatedTyHelpers;
 
-use rustc_errors::error_code;
+use rustc_errors::codes::*;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
@@ -209,7 +209,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     RangeEnd::Included => {
                         self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
                             span,
-                            teach: self.tcx.sess.teach(&error_code!(E0030)).then_some(()),
+                            teach: self.tcx.sess.teach(E0030).then_some(()),
                         })
                     }
                     RangeEnd::Excluded => {
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 2ee660ddc9be1..cf5d2c9745570 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -1,7 +1,7 @@
 use std::borrow::Cow;
 
 use rustc_errors::{
-    Applicability, DecorateLint, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder,
+    codes::*, Applicability, DecorateLint, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder,
     DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, Level,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -33,7 +33,7 @@ pub(crate) enum ConstMutate {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_transform_unaligned_packed_ref, code = "E0793")]
+#[diag(mir_transform_unaligned_packed_ref, code = E0793)]
 #[note]
 #[note(mir_transform_note_ub)]
 #[help]
@@ -66,7 +66,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe {
     #[track_caller]
     fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe);
-        diag.code("E0133".to_string());
+        diag.code(E0133);
         diag.span(self.span);
         diag.span_label(self.span, self.details.label());
         let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter());
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 40852048293a9..053a9c03d7483 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -3,7 +3,7 @@ use std::borrow::Cow;
 use rustc_ast::token::Token;
 use rustc_ast::{Path, Visibility};
 use rustc_errors::{
-    AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, IntoDiagnostic, Level,
+    codes::*, AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, IntoDiagnostic, Level,
     SubdiagnosticMessage,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
@@ -25,7 +25,7 @@ pub(crate) struct AmbiguousPlus {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_maybe_recover_from_bad_type_plus, code = "E0178")]
+#[diag(parse_maybe_recover_from_bad_type_plus, code = E0178)]
 pub(crate) struct BadTypePlus {
     pub ty: String,
     #[primary_span]
@@ -807,7 +807,7 @@ pub(crate) struct InclusiveRangeMatchArrow {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_inclusive_range_no_end, code = "E0586")]
+#[diag(parse_inclusive_range_no_end, code = E0586)]
 #[note]
 pub(crate) struct InclusiveRangeNoEnd {
     #[primary_span]
@@ -901,7 +901,7 @@ pub(crate) struct MismatchedClosingDelimiter {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_incorrect_visibility_restriction, code = "E0704")]
+#[diag(parse_incorrect_visibility_restriction, code = E0704)]
 #[help]
 pub(crate) struct IncorrectVisibilityRestriction {
     #[primary_span]
@@ -925,7 +925,7 @@ pub(crate) struct ExpectedStatementAfterOuterAttr {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_doc_comment_does_not_document_anything, code = "E0585")]
+#[diag(parse_doc_comment_does_not_document_anything, code = E0585)]
 #[help]
 pub(crate) struct DocCommentDoesNotDocumentAnything {
     #[primary_span]
@@ -1357,7 +1357,7 @@ pub(crate) struct AttributeOnParamType {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_pattern_method_param_without_body, code = "E0642")]
+#[diag(parse_pattern_method_param_without_body, code = E0642)]
 pub(crate) struct PatternMethodParamWithoutBody {
     #[primary_span]
     #[suggestion(code = "_", applicability = "machine-applicable")]
@@ -1565,7 +1565,7 @@ pub(crate) struct WhereClauseBeforeTupleStructBodySugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_async_fn_in_2015, code = "E0670")]
+#[diag(parse_async_fn_in_2015, code = E0670)]
 pub(crate) struct AsyncFnIn2015 {
     #[primary_span]
     #[label]
@@ -1929,7 +1929,7 @@ pub struct CrDocComment {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_no_digits_literal, code = "E0768")]
+#[diag(parse_no_digits_literal, code = E0768)]
 pub struct NoDigitsLiteral {
     #[primary_span]
     pub span: Span,
@@ -2499,7 +2499,7 @@ pub(crate) struct FnPointerCannotBeAsync {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_nested_c_variadic_type, code = "E0743")]
+#[diag(parse_nested_c_variadic_type, code = E0743)]
 pub(crate) struct NestedCVariadicType {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index d7ecf577ed676..91f6b752d9f6e 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -7,7 +7,7 @@ use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::util::unicode::contains_text_flow_control_chars;
-use rustc_errors::{error_code, Applicability, DiagCtxt, DiagnosticBuilder, StashKey};
+use rustc_errors::{codes::*, Applicability, DiagCtxt, DiagnosticBuilder, StashKey};
 use rustc_lexer::unescape::{self, EscapeError, Mode};
 use rustc_lexer::{Base, DocStyle, RawStrError};
 use rustc_lexer::{Cursor, LiteralKind};
@@ -397,7 +397,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                 if !terminated {
                     self.dcx()
                         .struct_span_fatal(self.mk_sp(start, end), "unterminated character literal")
-                        .with_code(error_code!(E0762))
+                        .with_code(E0762)
                         .emit()
                 }
                 self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' '
@@ -409,7 +409,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                             self.mk_sp(start + BytePos(1), end),
                             "unterminated byte constant",
                         )
-                        .with_code(error_code!(E0763))
+                        .with_code(E0763)
                         .emit()
                 }
                 self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' '
@@ -421,7 +421,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                             self.mk_sp(start, end),
                             "unterminated double quote string",
                         )
-                        .with_code(error_code!(E0765))
+                        .with_code(E0765)
                         .emit()
                 }
                 self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " "
@@ -433,7 +433,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                             self.mk_sp(start + BytePos(1), end),
                             "unterminated double quote byte string",
                         )
-                        .with_code(error_code!(E0766))
+                        .with_code(E0766)
                         .emit()
                 }
                 self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" "
@@ -445,7 +445,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                             self.mk_sp(start + BytePos(1), end),
                             "unterminated C string",
                         )
-                        .with_code(error_code!(E0767))
+                        .with_code(E0767)
                         .emit()
                 }
                 self.cook_c_string(token::CStr, Mode::CStr, start, end, 2, 1) // c" "
@@ -582,7 +582,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
     ) -> ! {
         let mut err =
             self.dcx().struct_span_fatal(self.mk_sp(start, start), "unterminated raw string");
-        err.code(error_code!(E0748));
+        err.code(E0748);
         err.span_label(self.mk_sp(start, start), "unterminated raw string");
 
         if n_hashes > 0 {
@@ -614,7 +614,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
         };
         let last_bpos = self.pos;
         let mut err = self.dcx().struct_span_fatal(self.mk_sp(start, last_bpos), msg);
-        err.code(error_code!(E0758));
+        err.code(E0758);
         let mut nested_block_comment_open_idxs = vec![];
         let mut last_nested_block_comment_idxs = None;
         let mut content_chars = self.str_from(start).char_indices().peekable();
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index a92609c2c2f87..98e062dd784d4 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -8,7 +8,7 @@ use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle
 use rustc_ast as ast;
 use rustc_ast::attr;
 use rustc_ast::token::{self, Delimiter, Nonterminal};
-use rustc_errors::{error_code, Diagnostic, PResult};
+use rustc_errors::{codes::*, Diagnostic, PResult};
 use rustc_span::{sym, BytePos, Span};
 use thin_vec::ThinVec;
 use tracing::debug;
@@ -61,7 +61,7 @@ impl<'a> Parser<'a> {
                     let mut err = self
                         .dcx()
                         .struct_span_err(span, fluent::parse_inner_doc_comment_not_permitted);
-                    err.code(error_code!(E0753));
+                    err.code(E0753);
                     if let Some(replacement_span) = self.annotate_following_item_if_applicable(
                         &mut err,
                         span,
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 3bd8ae0258628..9a77643f9510f 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -10,7 +10,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use rustc_ast::util::case::Case;
 use rustc_ast::{self as ast};
 use rustc_ast_pretty::pprust;
-use rustc_errors::{struct_span_code_err, Applicability, PResult, StashKey};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability, PResult, StashKey};
 use rustc_span::edit_distance::edit_distance;
 use rustc_span::edition::Edition;
 use rustc_span::source_map;
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 25ca685cbfade..97c70e327f0fe 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -1,6 +1,6 @@
 use rustc_ast::attr;
 use rustc_ast::entry::EntryPointType;
-use rustc_errors::error_code;
+use rustc_errors::codes::*;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
@@ -180,8 +180,8 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
         Default::default()
     });
     let main_def_opt = tcx.resolutions(()).main_def;
-    let code = error_code!(E0601);
-    let add_teach_note = tcx.sess.teach(&code);
+    let code = E0601;
+    let add_teach_note = tcx.sess.teach(code);
     // The file may be empty, which leads to the diagnostic machinery not emitting this
     // note. This is a relatively simple way to detect that case and emit a span-less
     // note instead.
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index cf3c7cc4ace0d..77bfe57e3706f 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -6,7 +6,7 @@ use std::{
 use crate::fluent_generated as fluent;
 use rustc_ast::Label;
 use rustc_errors::{
-    error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
+    codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
     DiagnosticSymbolList, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan,
 };
 use rustc_hir::{self as hir, ExprKind, Target};
@@ -55,7 +55,7 @@ pub struct IgnoredInlineAttrFnProto;
 pub struct IgnoredInlineAttrConstants;
 
 #[derive(Diagnostic)]
-#[diag(passes_inline_not_fn_or_closure, code = "E0518")]
+#[diag(passes_inline_not_fn_or_closure, code = E0518)]
 pub struct InlineNotFnOrClosure {
     #[primary_span]
     pub attr_span: Span,
@@ -76,7 +76,7 @@ pub struct IgnoredCoveragePropagate;
 pub struct IgnoredCoverageFnDefn;
 
 #[derive(Diagnostic)]
-#[diag(passes_coverage_not_coverable, code = "E0788")]
+#[diag(passes_coverage_not_coverable, code = E0788)]
 pub struct IgnoredCoverageNotCoverable {
     #[primary_span]
     pub attr_span: Span,
@@ -95,14 +95,14 @@ pub struct AttrShouldBeAppliedToFn {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_naked_tracked_caller, code = "E0736")]
+#[diag(passes_naked_tracked_caller, code = E0736)]
 pub struct NakedTrackedCaller {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_should_be_applied_to_fn, code = "E0739")]
+#[diag(passes_should_be_applied_to_fn, code = E0739)]
 pub struct TrackedCallerWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -112,7 +112,7 @@ pub struct TrackedCallerWrongLocation {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_should_be_applied_to_struct_enum, code = "E0701")]
+#[diag(passes_should_be_applied_to_struct_enum, code = E0701)]
 pub struct NonExhaustiveWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -370,28 +370,28 @@ pub struct HasIncoherentInherentImpl {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_both_ffi_const_and_pure, code = "E0757")]
+#[diag(passes_both_ffi_const_and_pure, code = E0757)]
 pub struct BothFfiConstAndPure {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_ffi_pure_invalid_target, code = "E0755")]
+#[diag(passes_ffi_pure_invalid_target, code = E0755)]
 pub struct FfiPureInvalidTarget {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_ffi_const_invalid_target, code = "E0756")]
+#[diag(passes_ffi_const_invalid_target, code = E0756)]
 pub struct FfiConstInvalidTarget {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_ffi_returns_twice_invalid_target, code = "E0724")]
+#[diag(passes_ffi_returns_twice_invalid_target, code = E0724)]
 pub struct FfiReturnsTwiceInvalidTarget {
     #[primary_span]
     pub attr_span: Span,
@@ -552,21 +552,21 @@ pub struct NoMangle {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_repr_ident, code = "E0565")]
+#[diag(passes_repr_ident, code = E0565)]
 pub struct ReprIdent {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_repr_conflicting, code = "E0566")]
+#[diag(passes_repr_conflicting, code = E0566)]
 pub struct ReprConflicting {
     #[primary_span]
     pub hint_spans: Vec<Span>,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes_repr_conflicting, code = "E0566")]
+#[diag(passes_repr_conflicting, code = E0566)]
 pub struct ReprConflictingLint;
 
 #[derive(Diagnostic)]
@@ -667,7 +667,7 @@ pub(crate) struct EmptyConfusables {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_incorrect_meta_item, code = "E0539")]
+#[diag(passes_incorrect_meta_item, code = E0539)]
 pub(crate) struct IncorrectMetaItem {
     #[primary_span]
     pub span: Span,
@@ -737,7 +737,7 @@ pub struct Unused {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_non_exported_macro_invalid_attrs, code = "E0518")]
+#[diag(passes_non_exported_macro_invalid_attrs, code = E0518)]
 pub struct NonExportedMacroInvalidAttrs {
     #[primary_span]
     #[label]
@@ -801,7 +801,7 @@ pub struct DeprecatedAnnotationHasNoEffect {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unknown_external_lang_item, code = "E0264")]
+#[diag(passes_unknown_external_lang_item, code = E0264)]
 pub struct UnknownExternLangItem {
     #[primary_span]
     pub span: Span,
@@ -837,7 +837,7 @@ pub struct LangItemWithTargetFeature {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_lang_item_on_incorrect_target, code = "E0718")]
+#[diag(passes_lang_item_on_incorrect_target, code = E0718)]
 pub struct LangItemOnIncorrectTarget {
     #[primary_span]
     #[label]
@@ -848,7 +848,7 @@ pub struct LangItemOnIncorrectTarget {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unknown_lang_item, code = "E0522")]
+#[diag(passes_unknown_lang_item, code = E0522)]
 pub struct UnknownLangItem {
     #[primary_span]
     #[label]
@@ -990,7 +990,7 @@ pub struct UnrecognizedField {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_feature_stable_twice, code = "E0711")]
+#[diag(passes_feature_stable_twice, code = E0711)]
 pub struct FeatureStableTwice {
     #[primary_span]
     pub span: Span,
@@ -1000,7 +1000,7 @@ pub struct FeatureStableTwice {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_feature_previously_declared, code = "E0711")]
+#[diag(passes_feature_previously_declared, code = E0711)]
 pub struct FeaturePreviouslyDeclared<'a, 'b> {
     #[primary_span]
     pub span: Span,
@@ -1025,7 +1025,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> {
     fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_break_non_loop);
         diag.span(self.span);
-        diag.code(error_code!(E0571));
+        diag.code(E0571);
         diag.arg("kind", self.kind);
         diag.span_label(self.span, fluent::passes_label);
         if let Some(head) = self.head {
@@ -1063,7 +1063,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_continue_labeled_block, code = "E0696")]
+#[diag(passes_continue_labeled_block, code = E0696)]
 pub struct ContinueLabeledBlock {
     #[primary_span]
     #[label]
@@ -1073,7 +1073,7 @@ pub struct ContinueLabeledBlock {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_break_inside_closure, code = "E0267")]
+#[diag(passes_break_inside_closure, code = E0267)]
 pub struct BreakInsideClosure<'a> {
     #[primary_span]
     #[label]
@@ -1084,7 +1084,7 @@ pub struct BreakInsideClosure<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_break_inside_async_block, code = "E0267")]
+#[diag(passes_break_inside_async_block, code = E0267)]
 pub struct BreakInsideAsyncBlock<'a> {
     #[primary_span]
     #[label]
@@ -1095,7 +1095,7 @@ pub struct BreakInsideAsyncBlock<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_outside_loop, code = "E0268")]
+#[diag(passes_outside_loop, code = E0268)]
 pub struct OutsideLoop<'a> {
     #[primary_span]
     #[label]
@@ -1115,7 +1115,7 @@ pub struct OutsideLoopSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unlabeled_in_labeled_block, code = "E0695")]
+#[diag(passes_unlabeled_in_labeled_block, code = E0695)]
 pub struct UnlabeledInLabeledBlock<'a> {
     #[primary_span]
     #[label]
@@ -1124,7 +1124,7 @@ pub struct UnlabeledInLabeledBlock<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unlabeled_cf_in_while_condition, code = "E0590")]
+#[diag(passes_unlabeled_cf_in_while_condition, code = E0590)]
 pub struct UnlabeledCfInWhileCondition<'a> {
     #[primary_span]
     #[label]
@@ -1169,7 +1169,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock {
     fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_naked_functions_asm_block);
         diag.span(self.span);
-        diag.code(error_code!(E0787));
+        diag.code(E0787);
         for span in self.multiple_asms.iter() {
             diag.span_label(*span, fluent::passes_label_multiple_asm);
         }
@@ -1181,14 +1181,14 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_naked_functions_operands, code = "E0787")]
+#[diag(passes_naked_functions_operands, code = E0787)]
 pub struct NakedFunctionsOperands {
     #[primary_span]
     pub unsupported_operands: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_naked_functions_asm_options, code = "E0787")]
+#[diag(passes_naked_functions_asm_options, code = E0787)]
 pub struct NakedFunctionsAsmOptions {
     #[primary_span]
     pub span: Span,
@@ -1196,7 +1196,7 @@ pub struct NakedFunctionsAsmOptions {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_naked_functions_must_use_noreturn, code = "E0787")]
+#[diag(passes_naked_functions_must_use_noreturn, code = E0787)]
 pub struct NakedFunctionsMustUseNoreturn {
     #[primary_span]
     pub span: Span,
@@ -1229,7 +1229,7 @@ pub struct AttrOnlyInFunctions {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_multiple_rustc_main, code = "E0137")]
+#[diag(passes_multiple_rustc_main, code = E0137)]
 pub struct MultipleRustcMain {
     #[primary_span]
     pub span: Span,
@@ -1240,7 +1240,7 @@ pub struct MultipleRustcMain {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_multiple_start_functions, code = "E0138")]
+#[diag(passes_multiple_start_functions, code = E0138)]
 pub struct MultipleStartFunctions {
     #[primary_span]
     pub span: Span,
@@ -1280,7 +1280,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr {
     fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_no_main_function);
         diag.span(DUMMY_SP);
-        diag.code(error_code!(E0601));
+        diag.code(E0601);
         diag.arg("crate_name", self.crate_name);
         diag.arg("filename", self.filename);
         diag.arg("has_filename", self.has_filename);
@@ -1345,7 +1345,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for DuplicateLangItem {
                 Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends,
             },
         );
-        diag.code(error_code!(E0152));
+        diag.code(E0152);
         diag.arg("lang_item_name", self.lang_item_name);
         diag.arg("crate_name", self.crate_name);
         diag.arg("dependency_of", self.dependency_of);
@@ -1382,7 +1382,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for DuplicateLangItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_incorrect_target, code = "E0718")]
+#[diag(passes_incorrect_target, code = E0718)]
 pub struct IncorrectTarget<'a> {
     #[primary_span]
     pub span: Span,
@@ -1418,7 +1418,7 @@ pub struct ObjectLifetimeErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unrecognized_repr_hint, code = "E0552")]
+#[diag(passes_unrecognized_repr_hint, code = E0552)]
 #[help]
 pub struct UnrecognizedReprHint {
     #[primary_span]
@@ -1427,35 +1427,35 @@ pub struct UnrecognizedReprHint {
 
 #[derive(Diagnostic)]
 pub enum AttrApplication {
-    #[diag(passes_attr_application_enum, code = "E0517")]
+    #[diag(passes_attr_application_enum, code = E0517)]
     Enum {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes_attr_application_struct, code = "E0517")]
+    #[diag(passes_attr_application_struct, code = E0517)]
     Struct {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes_attr_application_struct_union, code = "E0517")]
+    #[diag(passes_attr_application_struct_union, code = E0517)]
     StructUnion {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes_attr_application_struct_enum_union, code = "E0517")]
+    #[diag(passes_attr_application_struct_enum_union, code = E0517)]
     StructEnumUnion {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes_attr_application_struct_enum_function_method_union, code = "E0517")]
+    #[diag(passes_attr_application_struct_enum_function_method_union, code = E0517)]
     StructEnumFunctionMethodUnion {
         #[primary_span]
         hint_span: Span,
@@ -1465,7 +1465,7 @@ pub enum AttrApplication {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_transparent_incompatible, code = "E0692")]
+#[diag(passes_transparent_incompatible, code = E0692)]
 pub struct TransparentIncompatible {
     #[primary_span]
     pub hint_spans: Vec<Span>,
@@ -1473,7 +1473,7 @@ pub struct TransparentIncompatible {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_deprecated_attribute, code = "E0549")]
+#[diag(passes_deprecated_attribute, code = E0549)]
 pub struct DeprecatedAttribute {
     #[primary_span]
     pub span: Span,
@@ -1524,7 +1524,7 @@ pub struct TraitImplConstStable {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_feature_only_on_nightly, code = "E0554")]
+#[diag(passes_feature_only_on_nightly, code = E0554)]
 pub struct FeatureOnlyOnNightly {
     #[primary_span]
     pub span: Span,
@@ -1532,7 +1532,7 @@ pub struct FeatureOnlyOnNightly {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unknown_feature, code = "E0635")]
+#[diag(passes_unknown_feature, code = E0635)]
 pub struct UnknownFeature {
     #[primary_span]
     pub span: Span,
@@ -1549,7 +1549,7 @@ pub struct ImpliedFeatureNotExist {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_duplicate_feature_err, code = "E0636")]
+#[diag(passes_duplicate_feature_err, code = E0636)]
 pub struct DuplicateFeatureErr {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index b1242f82f4fec..01c6d18c0e1be 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -1,9 +1,9 @@
-use rustc_errors::DiagnosticArgFromDisplay;
+use rustc_errors::{codes::*, DiagnosticArgFromDisplay};
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
-#[diag(privacy_field_is_private, code = "E0451")]
+#[diag(privacy_field_is_private, code = E0451)]
 pub struct FieldIsPrivate {
     #[primary_span]
     pub span: Span,
@@ -48,7 +48,7 @@ pub struct UnnamedItemIsPrivate {
 }
 
 #[derive(Diagnostic)]
-#[diag(privacy_in_public_interface, code = "E0446")]
+#[diag(privacy_in_public_interface, code = E0446)]
 pub struct InPublicInterface<'a> {
     #[primary_span]
     #[label]
diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs
index 5829e17ec1625..9db6fac8036a9 100644
--- a/compiler/rustc_query_system/src/error.rs
+++ b/compiler/rustc_query_system/src/error.rs
@@ -1,3 +1,4 @@
+use rustc_errors::codes::*;
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_session::Limit;
 use rustc_span::{Span, Symbol};
@@ -45,7 +46,7 @@ pub struct CycleUsage {
 }
 
 #[derive(Diagnostic)]
-#[diag(query_system_cycle, code = "E0391")]
+#[diag(query_system_cycle, code = E0391)]
 pub struct Cycle {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index a4e2f9e3ff8cd..7eb7c8c2bca22 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -19,7 +19,7 @@ use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
 use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
 use rustc_attr as attr;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{struct_span_code_err, Applicability};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability};
 use rustc_expand::expand::AstFragment;
 use rustc_hir::def::{self, *};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
@@ -1029,9 +1029,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             }
         }
 
-        let macro_use_import = |this: &Self, span| {
+        let macro_use_import = |this: &Self, span, warn_private| {
             this.r.arenas.alloc_import(ImportData {
-                kind: ImportKind::MacroUse,
+                kind: ImportKind::MacroUse { warn_private },
                 root_id: item.id,
                 parent_scope: this.parent_scope,
                 imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
@@ -1048,11 +1048,25 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
         let allow_shadowing = self.parent_scope.expansion == LocalExpnId::ROOT;
         if let Some(span) = import_all {
-            let import = macro_use_import(self, span);
+            let import = macro_use_import(self, span, false);
             self.r.potentially_unused_imports.push(import);
             module.for_each_child(self, |this, ident, ns, binding| {
                 if ns == MacroNS {
-                    let imported_binding = this.r.import(binding, import);
+                    let imported_binding =
+                        if this.r.is_accessible_from(binding.vis, this.parent_scope.module) {
+                            this.r.import(binding, import)
+                        } else if !this.r.is_builtin_macro(binding.res())
+                            && !this.r.macro_use_prelude.contains_key(&ident.name)
+                        {
+                            // - `!r.is_builtin_macro(res)` excluding the built-in macros such as `Debug` or `Hash`.
+                            // - `!r.macro_use_prelude.contains_key(name)` excluding macros defined in other extern
+                            //    crates such as `std`.
+                            // FIXME: This branch should eventually be removed.
+                            let import = macro_use_import(this, span, true);
+                            this.r.import(binding, import)
+                        } else {
+                            return;
+                        };
                     this.add_macro_use_binding(ident.name, imported_binding, span, allow_shadowing);
                 }
             });
@@ -1065,7 +1079,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                     &self.parent_scope,
                 );
                 if let Ok(binding) = result {
-                    let import = macro_use_import(self, ident.span);
+                    let import = macro_use_import(self, ident.span, false);
                     self.r.potentially_unused_imports.push(import);
                     let imported_binding = self.r.import(binding, import);
                     self.add_macro_use_binding(
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 0e43a35ce7389..fc72d76c3a797 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -290,7 +290,7 @@ impl Resolver<'_, '_> {
                     || import.expect_vis().is_public()
                     || import.span.is_dummy() =>
                 {
-                    if let ImportKind::MacroUse = import.kind {
+                    if let ImportKind::MacroUse { .. } = import.kind {
                         if !import.span.is_dummy() {
                             self.lint_buffer.buffer_lint(
                                 MACRO_USE_EXTERN_CRATE,
@@ -315,7 +315,7 @@ impl Resolver<'_, '_> {
                         maybe_unused_extern_crates.insert(id, import.span);
                     }
                 }
-                ImportKind::MacroUse => {
+                ImportKind::MacroUse { .. } => {
                     let msg = "unused `#[macro_use]` import";
                     self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.root_id, import.span, msg);
                 }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 4a0c522b6ec5d..f3a6eb65a7235 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -6,8 +6,8 @@ use rustc_ast::{MetaItemKind, NestedMetaItem};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{
-    pluralize, report_ambiguity_error, struct_span_code_err, Applicability, DiagCtxt, Diagnostic,
-    DiagnosticBuilder, ErrorGuaranteed, MultiSpan, SuggestionStyle,
+    codes::*, pluralize, report_ambiguity_error, struct_span_code_err, Applicability, DiagCtxt,
+    Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, SuggestionStyle,
 };
 use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
@@ -285,7 +285,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         use NameBindingKind::Import;
         let can_suggest = |binding: NameBinding<'_>, import: self::Import<'_>| {
             !binding.span.is_dummy()
-                && !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport)
+                && !matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport)
         };
         let import = match (&new_binding.kind, &old_binding.kind) {
             // If there are two imports where one or both have attributes then prefer removing the
@@ -1819,9 +1819,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         next_ident = source;
                         Some(binding)
                     }
-                    ImportKind::Glob { .. } | ImportKind::MacroUse | ImportKind::MacroExport => {
-                        Some(binding)
-                    }
+                    ImportKind::Glob { .. }
+                    | ImportKind::MacroUse { .. }
+                    | ImportKind::MacroExport => Some(binding),
                     ImportKind::ExternCrate { .. } => None,
                 },
                 _ => None,
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 821b1e946f31c..50ff09feb4d9b 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -1,3 +1,4 @@
+use rustc_errors::codes::*;
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{
     symbol::{Ident, Symbol},
@@ -7,16 +8,16 @@ use rustc_span::{
 use crate::{late::PatternSource, Res};
 
 #[derive(Diagnostic)]
-#[diag(resolve_parent_module_reset_for_binding, code = "E0637")]
+#[diag(resolve_parent_module_reset_for_binding, code = E0637)]
 pub(crate) struct ParentModuleResetForBinding;
 
 #[derive(Diagnostic)]
-#[diag(resolve_ampersand_used_without_explicit_lifetime_name, code = "E0637")]
+#[diag(resolve_ampersand_used_without_explicit_lifetime_name, code = E0637)]
 #[note]
 pub(crate) struct AmpersandUsedWithoutExplicitLifetimeName(#[primary_span] pub(crate) Span);
 
 #[derive(Diagnostic)]
-#[diag(resolve_underscore_lifetime_name_cannot_be_used_here, code = "E0637")]
+#[diag(resolve_underscore_lifetime_name_cannot_be_used_here, code = E0637)]
 #[note]
 pub(crate) struct UnderscoreLifetimeNameCannotBeUsedHere(#[primary_span] pub(crate) Span);
 
@@ -33,7 +34,7 @@ pub(crate) struct CrateRootNamesMustBeNamedExplicitly(#[primary_span] pub(crate)
 pub(crate) struct ResolutionError(#[primary_span] pub(crate) Span);
 
 #[derive(Diagnostic)]
-#[diag(resolve_generic_params_from_outer_item, code = "E0401")]
+#[diag(resolve_generic_params_from_outer_item, code = E0401)]
 pub(crate) struct GenericParamsFromOuterItem {
     #[primary_span]
     #[label]
@@ -67,7 +68,7 @@ pub(crate) struct GenericParamsFromOuterItemSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_name_is_already_used_as_generic_parameter, code = "E0403")]
+#[diag(resolve_name_is_already_used_as_generic_parameter, code = E0403)]
 pub(crate) struct NameAlreadyUsedInParameterList {
     #[primary_span]
     #[label]
@@ -78,7 +79,7 @@ pub(crate) struct NameAlreadyUsedInParameterList {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_method_not_member_of_trait, code = "E0407")]
+#[diag(resolve_method_not_member_of_trait, code = E0407)]
 pub(crate) struct MethodNotMemberOfTrait {
     #[primary_span]
     #[label]
@@ -102,7 +103,7 @@ pub(crate) struct AssociatedFnWithSimilarNameExists {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_type_not_member_of_trait, code = "E0437")]
+#[diag(resolve_type_not_member_of_trait, code = E0437)]
 pub(crate) struct TypeNotMemberOfTrait {
     #[primary_span]
     #[label]
@@ -126,7 +127,7 @@ pub(crate) struct AssociatedTypeWithSimilarNameExists {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_const_not_member_of_trait, code = "E0438")]
+#[diag(resolve_const_not_member_of_trait, code = E0438)]
 pub(crate) struct ConstNotMemberOfTrait {
     #[primary_span]
     #[label]
@@ -150,7 +151,7 @@ pub(crate) struct AssociatedConstWithSimilarNameExists {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_variable_bound_with_different_mode, code = "E0409")]
+#[diag(resolve_variable_bound_with_different_mode, code = E0409)]
 pub(crate) struct VariableBoundWithDifferentMode {
     #[primary_span]
     #[label]
@@ -161,7 +162,7 @@ pub(crate) struct VariableBoundWithDifferentMode {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_ident_bound_more_than_once_in_parameter_list, code = "E0415")]
+#[diag(resolve_ident_bound_more_than_once_in_parameter_list, code = E0415)]
 pub(crate) struct IdentifierBoundMoreThanOnceInParameterList {
     #[primary_span]
     #[label]
@@ -170,7 +171,7 @@ pub(crate) struct IdentifierBoundMoreThanOnceInParameterList {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_ident_bound_more_than_once_in_same_pattern, code = "E0416")]
+#[diag(resolve_ident_bound_more_than_once_in_same_pattern, code = E0416)]
 pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern {
     #[primary_span]
     #[label]
@@ -179,7 +180,7 @@ pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_undeclared_label, code = "E0426")]
+#[diag(resolve_undeclared_label, code = E0426)]
 pub(crate) struct UndeclaredLabel {
     #[primary_span]
     #[label]
@@ -217,7 +218,7 @@ pub(crate) struct UnreachableLabelWithSimilarNameExists {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = "E0430")]
+#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = E0430)]
 pub(crate) struct SelfImportCanOnlyAppearOnceInTheList {
     #[primary_span]
     #[label]
@@ -225,7 +226,7 @@ pub(crate) struct SelfImportCanOnlyAppearOnceInTheList {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = "E0431")]
+#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = E0431)]
 pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix {
     #[primary_span]
     #[label]
@@ -233,7 +234,7 @@ pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = "E0434")]
+#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = E0434)]
 #[help]
 pub(crate) struct CannotCaptureDynamicEnvironmentInFnItem {
     #[primary_span]
@@ -241,7 +242,7 @@ pub(crate) struct CannotCaptureDynamicEnvironmentInFnItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_attempt_to_use_non_constant_value_in_constant, code = "E0435")]
+#[diag(resolve_attempt_to_use_non_constant_value_in_constant, code = E0435)]
 pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> {
     #[primary_span]
     pub(crate) span: Span,
@@ -283,7 +284,7 @@ pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_self_imports_only_allowed_within, code = "E0429")]
+#[diag(resolve_self_imports_only_allowed_within, code = E0429)]
 pub(crate) struct SelfImportsOnlyAllowedWithin {
     #[primary_span]
     pub(crate) span: Span,
@@ -317,7 +318,7 @@ pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_binding_shadows_something_unacceptable, code = "E0530")]
+#[diag(resolve_binding_shadows_something_unacceptable, code = E0530)]
 pub(crate) struct BindingShadowsSomethingUnacceptable<'a> {
     #[primary_span]
     #[label]
@@ -346,7 +347,7 @@ pub(crate) struct BindingShadowsSomethingUnacceptableSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_forward_declared_generic_param, code = "E0128")]
+#[diag(resolve_forward_declared_generic_param, code = E0128)]
 pub(crate) struct ForwardDeclaredGenericParam {
     #[primary_span]
     #[label]
@@ -354,7 +355,7 @@ pub(crate) struct ForwardDeclaredGenericParam {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_param_in_ty_of_const_param, code = "E0770")]
+#[diag(resolve_param_in_ty_of_const_param, code = E0770)]
 pub(crate) struct ParamInTyOfConstParam {
     #[primary_span]
     #[label]
@@ -376,7 +377,7 @@ pub(crate) enum ParamKindInTyOfConstParam {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_self_in_generic_param_default, code = "E0735")]
+#[diag(resolve_self_in_generic_param_default, code = E0735)]
 pub(crate) struct SelfInGenericParamDefault {
     #[primary_span]
     #[label]
@@ -412,7 +413,7 @@ pub(crate) enum ParamKindInNonTrivialAnonConst {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_unreachable_label, code = "E0767")]
+#[diag(resolve_unreachable_label, code = E0767)]
 #[note]
 pub(crate) struct UnreachableLabel {
     #[primary_span]
@@ -456,7 +457,7 @@ pub(crate) struct UnreachableLabelSubLabelUnreachable {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_trait_impl_mismatch, code = "{code}")]
+#[diag(resolve_trait_impl_mismatch)]
 pub(crate) struct TraitImplMismatch {
     #[primary_span]
     #[label]
@@ -466,7 +467,6 @@ pub(crate) struct TraitImplMismatch {
     #[label(resolve_label_trait_item)]
     pub(crate) trait_item_span: Span,
     pub(crate) trait_path: String,
-    pub(crate) code: String,
 }
 
 #[derive(Diagnostic)]
@@ -496,7 +496,7 @@ pub(crate) struct BindingInNeverPattern {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_trait_impl_duplicate, code = "E0201")]
+#[diag(resolve_trait_impl_duplicate, code = E0201)]
 pub(crate) struct TraitImplDuplicate {
     #[primary_span]
     #[label]
@@ -519,11 +519,11 @@ pub(crate) struct Relative2018 {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_ancestor_only, code = "E0742")]
+#[diag(resolve_ancestor_only, code = E0742)]
 pub(crate) struct AncestorOnly(#[primary_span] pub(crate) Span);
 
 #[derive(Diagnostic)]
-#[diag(resolve_expected_found, code = "E0577")]
+#[diag(resolve_expected_found, code = E0577)]
 pub(crate) struct ExpectedFound {
     #[primary_span]
     #[label]
@@ -533,7 +533,7 @@ pub(crate) struct ExpectedFound {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_indeterminate, code = "E0578")]
+#[diag(resolve_indeterminate, code = E0578)]
 pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span);
 
 #[derive(Diagnostic)]
@@ -715,7 +715,7 @@ pub(crate) struct CannotDetermineMacroResolution {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_cannot_be_reexported_private, code = "E0364")]
+#[diag(resolve_cannot_be_reexported_private, code = E0364)]
 pub(crate) struct CannotBeReexportedPrivate {
     #[primary_span]
     pub(crate) span: Span,
@@ -723,7 +723,7 @@ pub(crate) struct CannotBeReexportedPrivate {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_cannot_be_reexported_crate_public, code = "E0364")]
+#[diag(resolve_cannot_be_reexported_crate_public, code = E0364)]
 pub(crate) struct CannotBeReexportedCratePublic {
     #[primary_span]
     pub(crate) span: Span,
@@ -731,7 +731,7 @@ pub(crate) struct CannotBeReexportedCratePublic {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_cannot_be_reexported_private, code = "E0365")]
+#[diag(resolve_cannot_be_reexported_private, code = E0365)]
 #[note(resolve_consider_declaring_with_pub)]
 pub(crate) struct CannotBeReexportedPrivateNS {
     #[primary_span]
@@ -741,7 +741,7 @@ pub(crate) struct CannotBeReexportedPrivateNS {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_cannot_be_reexported_crate_public, code = "E0365")]
+#[diag(resolve_cannot_be_reexported_crate_public, code = E0365)]
 #[note(resolve_consider_declaring_with_pub)]
 pub(crate) struct CannotBeReexportedCratePublicNS {
     #[primary_span]
@@ -780,7 +780,7 @@ pub(crate) struct ItemsInTraitsAreNotImportable {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_is_not_directly_importable, code = "E0253")]
+#[diag(resolve_is_not_directly_importable, code = E0253)]
 pub(crate) struct IsNotDirectlyImportable {
     #[primary_span]
     #[label]
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index f846dbec2c697..30fb35238c3c7 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -17,7 +17,7 @@ use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult};
 use rustc_ast::NodeId;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::intern::Interned;
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan};
+use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, MultiSpan};
 use rustc_hir::def::{self, DefKind, PartialRes};
 use rustc_middle::metadata::ModChild;
 use rustc_middle::metadata::Reexport;
@@ -80,7 +80,11 @@ pub(crate) enum ImportKind<'a> {
         target: Ident,
         id: NodeId,
     },
-    MacroUse,
+    MacroUse {
+        /// A field has been added indicating whether it should be reported as a lint,
+        /// addressing issue#119301.
+        warn_private: bool,
+    },
     MacroExport,
 }
 
@@ -127,7 +131,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
                 .field("target", target)
                 .field("id", id)
                 .finish(),
-            MacroUse => f.debug_struct("MacroUse").finish(),
+            MacroUse { .. } => f.debug_struct("MacroUse").finish(),
             MacroExport => f.debug_struct("MacroExport").finish(),
         }
     }
@@ -197,7 +201,7 @@ impl<'a> ImportData<'a> {
             ImportKind::Single { id, .. }
             | ImportKind::Glob { id, .. }
             | ImportKind::ExternCrate { id, .. } => Some(id),
-            ImportKind::MacroUse | ImportKind::MacroExport => None,
+            ImportKind::MacroUse { .. } | ImportKind::MacroExport => None,
         }
     }
 
@@ -207,7 +211,7 @@ impl<'a> ImportData<'a> {
             ImportKind::Single { id, .. } => Reexport::Single(to_def_id(id)),
             ImportKind::Glob { id, .. } => Reexport::Glob(to_def_id(id)),
             ImportKind::ExternCrate { id, .. } => Reexport::ExternCrate(to_def_id(id)),
-            ImportKind::MacroUse => Reexport::MacroUse,
+            ImportKind::MacroUse { .. } => Reexport::MacroUse,
             ImportKind::MacroExport => Reexport::MacroExport,
         }
     }
@@ -1482,7 +1486,7 @@ fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String {
         ImportKind::Single { source, .. } => source.to_string(),
         ImportKind::Glob { .. } => "*".to_string(),
         ImportKind::ExternCrate { .. } => "<extern crate>".to_string(),
-        ImportKind::MacroUse => "#[macro_use]".to_string(),
+        ImportKind::MacroUse { .. } => "#[macro_use]".to_string(),
         ImportKind::MacroExport => "#[macro_export]".to_string(),
     }
 }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index abd724a6cc25c..38b27800d3ca4 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -16,7 +16,9 @@ use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
 use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
-use rustc_errors::{Applicability, DiagnosticArgValue, IntoDiagnosticArg};
+use rustc_errors::{
+    codes::*, struct_span_code_err, Applicability, DiagnosticArgValue, ErrCode, IntoDiagnosticArg,
+};
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
@@ -533,21 +535,20 @@ impl<'a> PathSource<'a> {
         }
     }
 
-    fn error_code(self, has_unexpected_resolution: bool) -> String {
-        use rustc_errors::error_code;
+    fn error_code(self, has_unexpected_resolution: bool) -> ErrCode {
         match (self, has_unexpected_resolution) {
-            (PathSource::Trait(_), true) => error_code!(E0404),
-            (PathSource::Trait(_), false) => error_code!(E0405),
-            (PathSource::Type, true) => error_code!(E0573),
-            (PathSource::Type, false) => error_code!(E0412),
-            (PathSource::Struct, true) => error_code!(E0574),
-            (PathSource::Struct, false) => error_code!(E0422),
-            (PathSource::Expr(..), true) | (PathSource::Delegation, true) => error_code!(E0423),
-            (PathSource::Expr(..), false) | (PathSource::Delegation, false) => error_code!(E0425),
-            (PathSource::Pat | PathSource::TupleStruct(..), true) => error_code!(E0532),
-            (PathSource::Pat | PathSource::TupleStruct(..), false) => error_code!(E0531),
-            (PathSource::TraitItem(..), true) => error_code!(E0575),
-            (PathSource::TraitItem(..), false) => error_code!(E0576),
+            (PathSource::Trait(_), true) => E0404,
+            (PathSource::Trait(_), false) => E0405,
+            (PathSource::Type, true) => E0573,
+            (PathSource::Type, false) => E0412,
+            (PathSource::Struct, true) => E0574,
+            (PathSource::Struct, false) => E0422,
+            (PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423,
+            (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425,
+            (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532,
+            (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531,
+            (PathSource::TraitItem(..), true) => E0575,
+            (PathSource::TraitItem(..), false) => E0576,
         }
     }
 }
@@ -1673,13 +1674,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     } else {
                         ("`'_` cannot be used here", "`'_` is a reserved lifetime name")
                     };
-                    let mut diag = rustc_errors::struct_span_code_err!(
-                        self.r.dcx(),
-                        lifetime.ident.span,
-                        E0637,
-                        "{}",
-                        msg,
-                    );
+                    let mut diag =
+                        struct_span_code_err!(self.r.dcx(), lifetime.ident.span, E0637, "{}", msg,);
                     diag.span_label(lifetime.ident.span, note);
                     if elided {
                         for rib in self.lifetime_ribs[i..].iter().rev() {
@@ -1863,7 +1859,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. }
                     | LifetimeRibKind::AnonymousWarn(_) => {
                         let sess = self.r.tcx.sess;
-                        let mut err = rustc_errors::struct_span_code_err!(
+                        let mut err = struct_span_code_err!(
                             sess.dcx(),
                             path_span,
                             E0726,
@@ -2608,7 +2604,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             }
 
             if param.ident.name == kw::UnderscoreLifetime {
-                rustc_errors::struct_span_code_err!(
+                struct_span_code_err!(
                     self.r.dcx(),
                     param.ident.span,
                     E0637,
@@ -2622,7 +2618,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             }
 
             if param.ident.name == kw::StaticLifetime {
-                rustc_errors::struct_span_code_err!(
+                struct_span_code_err!(
                     self.r.dcx(),
                     param.ident.span,
                     E0262,
@@ -3164,10 +3160,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         // The method kind does not correspond to what appeared in the trait, report.
         let path = &self.current_trait_ref.as_ref().unwrap().1.path;
         let (code, kind) = match kind {
-            AssocItemKind::Const(..) => (rustc_errors::error_code!(E0323), "const"),
-            AssocItemKind::Fn(..) => (rustc_errors::error_code!(E0324), "method"),
-            AssocItemKind::Type(..) => (rustc_errors::error_code!(E0325), "type"),
-            AssocItemKind::Delegation(..) => (rustc_errors::error_code!(E0324), "method"),
+            AssocItemKind::Const(..) => (E0323, "const"),
+            AssocItemKind::Fn(..) => (E0324, "method"),
+            AssocItemKind::Type(..) => (E0325, "type"),
+            AssocItemKind::Delegation(..) => (E0324, "method"),
             AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"),
         };
         let trait_path = path_names_to_string(path);
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index abb0a7a465aa1..a4c041f1ff247 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -16,8 +16,8 @@ use rustc_ast::{
 use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{
-    pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
-    MultiSpan, SuggestionStyle,
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
+    ErrorGuaranteed, MultiSpan, SuggestionStyle,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
@@ -922,8 +922,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         path: &[Segment],
         span: Span,
     ) {
-        if let Some(err_code) = &err.code {
-            if err_code == &rustc_errors::error_code!(E0425) {
+        if let Some(err_code) = err.code {
+            if err_code == E0425 {
                 for label_rib in &self.label_ribs {
                     for (label_ident, node_id) in &label_rib.bindings {
                         let ident = path.last().unwrap().ident;
@@ -946,7 +946,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         }
                     }
                 }
-            } else if err_code == &rustc_errors::error_code!(E0412) {
+            } else if err_code == E0412 {
                 if let Some(correct) = Self::likely_rust_type(path) {
                     err.span_suggestion(
                         span,
@@ -970,7 +970,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         if !is_self_type(path, source.namespace()) {
             return false;
         }
-        err.code(rustc_errors::error_code!(E0411));
+        err.code(E0411);
         err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
         if let Some(item_kind) = self.diagnostic_metadata.current_item {
             if !item_kind.ident.span.is_dummy() {
@@ -999,7 +999,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         }
 
         debug!("smart_resolve_path_fragment: E0424, source={:?}", source);
-        err.code(rustc_errors::error_code!(E0424));
+        err.code(E0424);
         err.span_label(
             span,
             match source {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 341c566d97fc1..ca931c158ec1c 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -37,7 +37,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{FreezeReadGuard, Lrc};
-use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{Applicability, DiagnosticBuilder, ErrCode};
 use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind};
 use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
@@ -55,6 +55,7 @@ use rustc_middle::span_bug;
 use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt};
 use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
 use rustc_query_system::ich::StableHashingContext;
+use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
 use rustc_session::lint::LintBuffer;
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -257,7 +258,7 @@ enum ResolutionError<'a> {
         kind: &'static str,
         trait_path: String,
         trait_item_span: Span,
-        code: String,
+        code: ErrCode,
     },
     /// Error E0201: multiple impl items for the same trait item.
     TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span },
@@ -1799,6 +1800,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
         }
         if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind {
+            if let ImportKind::MacroUse { warn_private: true } = import.kind {
+                let msg = format!("macro `{ident}` is private");
+                self.lint_buffer().buffer_lint(PRIVATE_MACRO_USE, import.root_id, ident.span, msg);
+            }
             // Avoid marking `extern crate` items that refer to a name from extern prelude,
             // but not introduce it, as used if they are accessed from lexical scope.
             if is_lexical_scope {
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 1c085ddf57bf6..a6bf289a76a4c 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust;
 use rustc_attr::StabilityLevel;
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{struct_span_code_err, Applicability};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability};
 use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand};
 use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::compile_declarative_macro;
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index e19f0fd84de56..c36cec6f35327 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -3,7 +3,7 @@ use std::num::NonZeroU32;
 use rustc_ast::token;
 use rustc_ast::util::literal::LitError;
 use rustc_errors::{
-    error_code, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan,
+    codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan,
 };
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
@@ -19,9 +19,7 @@ pub struct FeatureGateError {
 impl<'a> IntoDiagnostic<'a> for FeatureGateError {
     #[track_caller]
     fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> {
-        DiagnosticBuilder::new(dcx, level, self.explain)
-            .with_span(self.span)
-            .with_code(error_code!(E0658))
+        DiagnosticBuilder::new(dcx, level, self.explain).with_span(self.span).with_code(E0658)
     }
 }
 
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 24aa336c68fe9..dd61325566c7f 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -22,7 +22,7 @@ use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType};
 use rustc_errors::json::JsonEmitter;
 use rustc_errors::registry::Registry;
 use rustc_errors::{
-    error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticMessage,
+    codes::*, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, ErrCode,
     ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, LazyFallbackBundle, TerminalUrl,
 };
 use rustc_macros::HashStable_Generic;
@@ -316,7 +316,7 @@ impl Session {
     ) -> DiagnosticBuilder<'a> {
         let mut err = self.dcx().create_err(err);
         if err.code.is_none() {
-            err.code(error_code!(E0658));
+            err.code(E0658);
         }
         add_feature_diagnostics(&mut err, self, feature);
         err
@@ -907,7 +907,7 @@ impl Session {
         CodegenUnits::Default(16)
     }
 
-    pub fn teach(&self, code: &str) -> bool {
+    pub fn teach(&self, code: ErrCode) -> bool {
         self.opts.unstable_opts.teach && self.dcx().must_teach(code)
     }
 
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 5eff52afbca2b..7894f8dd98fff 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1,7 +1,7 @@
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee,
-    IntoDiagnostic, Level, SubdiagnosticMessage,
+    codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
+    EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessage,
 };
 use rustc_macros::Diagnostic;
 use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty};
@@ -25,7 +25,7 @@ pub struct UnableToConstructConstantValue<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = E0232)]
 pub struct EmptyOnClauseInOnUnimplemented {
     #[primary_span]
     #[label]
@@ -33,7 +33,7 @@ pub struct EmptyOnClauseInOnUnimplemented {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+#[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = E0232)]
 pub struct InvalidOnClauseInOnUnimplemented {
     #[primary_span]
     #[label]
@@ -41,7 +41,7 @@ pub struct InvalidOnClauseInOnUnimplemented {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = "E0232")]
+#[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = E0232)]
 #[note]
 pub struct NoValueInOnUnimplemented {
     #[primary_span]
@@ -59,17 +59,13 @@ pub struct NegativePositiveConflict<'tcx> {
 
 impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NegativePositiveConflict<'_> {
     #[track_caller]
-    fn into_diagnostic(
-        self,
-        dcx: &DiagCtxt,
-        level: Level,
-    ) -> rustc_errors::DiagnosticBuilder<'_, G> {
+    fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
         let mut diag =
             DiagnosticBuilder::new(dcx, level, fluent::trait_selection_negative_positive_conflict);
         diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string());
         diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string()));
         diag.span(self.impl_span);
-        diag.code(rustc_errors::error_code!(E0751));
+        diag.code(E0751);
         match self.negative_impl_span {
             Ok(span) => {
                 diag.span_label(span, fluent::trait_selection_negative_implementation_here);
@@ -132,7 +128,7 @@ impl AddToDiagnostic for AdjustSignatureBorrow {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection_closure_kind_mismatch, code = "E0525")]
+#[diag(trait_selection_closure_kind_mismatch, code = E0525)]
 pub struct ClosureKindMismatch {
     #[primary_span]
     #[label]
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
index 864580afe623b..ca43436848bae 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
@@ -1,7 +1,7 @@
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::InferCtxt;
 use crate::traits::{Obligation, ObligationCause, ObligationCtxt};
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, DiagnosticBuilder};
+use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::Node;
 use rustc_middle::ty::{self, Ty};
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 532e2cb36e3cc..ea79534c3af37 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -6,7 +6,7 @@ use rustc_ast::AttrKind;
 use rustc_ast::{Attribute, MetaItem, NestedMetaItem};
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{struct_span_code_err, ErrorGuaranteed};
+use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::GenericArgsRef;
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 0e33e9cd790d0..8cad922528216 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -13,7 +13,7 @@ use hir::def::CtorOf;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
-    error_code, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
     MultiSpan, Style, SuggestionStyle,
 };
 use rustc_hir as hir;
@@ -2014,7 +2014,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             return false;
         };
 
-        err.code(error_code!(E0746));
+        err.code(E0746);
         err.primary_message("return type cannot have an unboxed trait object");
         err.children.clear();
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 149dcffe333de..2a09e95b2c55e 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -19,8 +19,8 @@ use crate::traits::{
 };
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::{
-    pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
-    MultiSpan, StashKey, Style,
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
+    ErrorGuaranteed, MultiSpan, StashKey, Style,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, Res};
@@ -2529,7 +2529,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                  corresponding `impl` type",
                             ),
                         );
-                        err.code(rustc_errors::error_code!(E0790));
+                        err.code(E0790);
 
                         if let Some(local_def_id) = data.trait_ref.def_id.as_local()
                             && let Some(hir::Node::Item(hir::Item {
@@ -3162,7 +3162,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             | ObligationCauseCode::ItemObligation(def_id)
                 if self.tcx.is_fn_trait(*def_id) =>
             {
-                err.code(rustc_errors::error_code!(E0059));
+                err.code(E0059);
                 err.primary_message(format!(
                     "type parameter to bare `{}` trait must be a tuple",
                     self.tcx.def_path_str(*def_id)
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index b37d9714ddd8c..e2c457930bb12 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -20,7 +20,7 @@ use crate::traits::{
     self, coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt,
 };
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{error_code, DelayDm, Diagnostic};
+use rustc_errors::{codes::*, DelayDm, Diagnostic};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
@@ -449,7 +449,7 @@ fn report_conflicting_impls<'tcx>(
                 || tcx.orphan_check_impl(impl_def_id).is_ok()
             {
                 let mut err = tcx.dcx().struct_span_err(impl_span, msg);
-                err.code(error_code!(E0119));
+                err.code(E0119);
                 decorate(tcx, &overlap, impl_span, &mut err);
                 err.emit()
             } else {
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index 947d4bbe86e1c..bfbb45f0cb501 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -1,5 +1,6 @@
 //! Errors emitted by ty_utils
 
+use rustc_errors::codes::*;
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_middle::ty::{GenericArg, Ty};
 use rustc_span::Span;
@@ -113,7 +114,7 @@ pub struct DuplicateArg<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(ty_utils_impl_trait_not_param, code = "E0792")]
+#[diag(ty_utils_impl_trait_not_param, code = E0792)]
 pub struct NotParam<'tcx> {
     pub arg: GenericArg<'tcx>,
     #[primary_span]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 24ad78efa83b1..1dc3f49df38bf 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -185,6 +185,7 @@
 #![feature(set_ptr_value)]
 #![feature(slice_ptr_get)]
 #![feature(slice_split_at_unchecked)]
+#![feature(split_at_checked)]
 #![feature(str_internals)]
 #![feature(str_split_inclusive_remainder)]
 #![feature(str_split_remainder)]
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index c191877c434f2..6d0bb924073ce 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1842,7 +1842,8 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `mid > len`.
+    /// Panics if `mid > len`.  For a non-panicking alternative see
+    /// [`split_at_checked`](slice::split_at_checked).
     ///
     /// # Examples
     ///
@@ -1869,14 +1870,15 @@ impl<T> [T] {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "1.71.0")]
+    #[rustc_allow_const_fn_unstable(split_at_checked)]
     #[inline]
     #[track_caller]
     #[must_use]
     pub const fn split_at(&self, mid: usize) -> (&[T], &[T]) {
-        assert!(mid <= self.len());
-        // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
-        // fulfills the requirements of `split_at_unchecked`.
-        unsafe { self.split_at_unchecked(mid) }
+        match self.split_at_checked(mid) {
+            Some(pair) => pair,
+            None => panic!("mid > len"),
+        }
     }
 
     /// Divides one mutable slice into two at an index.
@@ -1887,7 +1889,8 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `mid > len`.
+    /// Panics if `mid > len`.  For a non-panicking alternative see
+    /// [`split_at_mut_checked`](slice::split_at_mut_checked).
     ///
     /// # Examples
     ///
@@ -1906,10 +1909,10 @@ impl<T> [T] {
     #[must_use]
     #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")]
     pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
-        assert!(mid <= self.len());
-        // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
-        // fulfills the requirements of `from_raw_parts_mut`.
-        unsafe { self.split_at_mut_unchecked(mid) }
+        match self.split_at_mut_checked(mid) {
+            Some(pair) => pair,
+            None => panic!("mid > len"),
+        }
     }
 
     /// Divides one slice into two at an index, without doing bounds checking.
@@ -2031,6 +2034,98 @@ impl<T> [T] {
         unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) }
     }
 
+    /// Divides one slice into two at an index, returning `None` if the slice is
+    /// too short.
+    ///
+    /// If `mid ≤ len` returns a pair of slices where the first will contain all
+    /// indices from `[0, mid)` (excluding the index `mid` itself) and the
+    /// second will contain all indices from `[mid, len)` (excluding the index
+    /// `len` itself).
+    ///
+    /// Otherwise, if `mid > len`, returns `None`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(split_at_checked)]
+    ///
+    /// let v = [1, -2, 3, -4, 5, -6];
+    ///
+    /// {
+    ///    let (left, right) = v.split_at_checked(0).unwrap();
+    ///    assert_eq!(left, []);
+    ///    assert_eq!(right, [1, -2, 3, -4, 5, -6]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.split_at_checked(2).unwrap();
+    ///     assert_eq!(left, [1, -2]);
+    ///     assert_eq!(right, [3, -4, 5, -6]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.split_at_checked(6).unwrap();
+    ///     assert_eq!(left, [1, -2, 3, -4, 5, -6]);
+    ///     assert_eq!(right, []);
+    /// }
+    ///
+    /// assert_eq!(None, v.split_at_checked(7));
+    /// ```
+    #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
+    #[rustc_const_unstable(feature = "split_at_checked", issue = "119128")]
+    #[inline]
+    #[must_use]
+    pub const fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])> {
+        if mid <= self.len() {
+            // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
+            // fulfills the requirements of `split_at_unchecked`.
+            Some(unsafe { self.split_at_unchecked(mid) })
+        } else {
+            None
+        }
+    }
+
+    /// Divides one mutable slice into two at an index, returning `None` if the
+    /// slice is too short.
+    ///
+    /// If `mid ≤ len` returns a pair of slices where the first will contain all
+    /// indices from `[0, mid)` (excluding the index `mid` itself) and the
+    /// second will contain all indices from `[mid, len)` (excluding the index
+    /// `len` itself).
+    ///
+    /// Otherwise, if `mid > len`, returns `None`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(split_at_checked)]
+    ///
+    /// let mut v = [1, 0, 3, 0, 5, 6];
+    ///
+    /// if let Some((left, right)) = v.split_at_mut_checked(2) {
+    ///     assert_eq!(left, [1, 0]);
+    ///     assert_eq!(right, [3, 0, 5, 6]);
+    ///     left[1] = 2;
+    ///     right[1] = 4;
+    /// }
+    /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
+    ///
+    /// assert_eq!(None, v.split_at_mut_checked(7));
+    /// ```
+    #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
+    #[rustc_const_unstable(feature = "split_at_checked", issue = "119128")]
+    #[inline]
+    #[must_use]
+    pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [T], &mut [T])> {
+        if mid <= self.len() {
+            // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
+            // fulfills the requirements of `split_at_unchecked`.
+            Some(unsafe { self.split_at_mut_unchecked(mid) })
+        } else {
+            None
+        }
+    }
+
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`. The matched element is not contained in the subslices.
     ///
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index a22c46edce254..80c5fe0de8da7 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -641,8 +641,9 @@ impl str {
     ///
     /// # Panics
     ///
-    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
-    /// past the end of the last code point of the string slice.
+    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is past
+    /// the end of the last code point of the string slice.  For a non-panicking
+    /// alternative see [`split_at_checked`](str::split_at_checked).
     ///
     /// # Examples
     ///
@@ -658,12 +659,9 @@ impl str {
     #[must_use]
     #[stable(feature = "str_split_at", since = "1.4.0")]
     pub fn split_at(&self, mid: usize) -> (&str, &str) {
-        // is_char_boundary checks that the index is in [0, .len()]
-        if self.is_char_boundary(mid) {
-            // SAFETY: just checked that `mid` is on a char boundary.
-            unsafe { (self.get_unchecked(0..mid), self.get_unchecked(mid..self.len())) }
-        } else {
-            slice_error_fail(self, 0, mid)
+        match self.split_at_checked(mid) {
+            None => slice_error_fail(self, 0, mid),
+            Some(pair) => pair,
         }
     }
 
@@ -681,8 +679,9 @@ impl str {
     ///
     /// # Panics
     ///
-    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
-    /// past the end of the last code point of the string slice.
+    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is past
+    /// the end of the last code point of the string slice.  For a non-panicking
+    /// alternative see [`split_at_mut_checked`](str::split_at_mut_checked).
     ///
     /// # Examples
     ///
@@ -702,20 +701,114 @@ impl str {
     pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
-            let len = self.len();
-            let ptr = self.as_mut_ptr();
             // SAFETY: just checked that `mid` is on a char boundary.
-            unsafe {
-                (
-                    from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
-                    from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr.add(mid), len - mid)),
-                )
-            }
+            unsafe { self.split_at_mut_unchecked(mid) }
         } else {
             slice_error_fail(self, 0, mid)
         }
     }
 
+    /// Divide one string slice into two at an index.
+    ///
+    /// The argument, `mid`, should be a valid byte offset from the start of the
+    /// string. It must also be on the boundary of a UTF-8 code point. The
+    /// method returns `None` if that’s not the case.
+    ///
+    /// The two slices returned go from the start of the string slice to `mid`,
+    /// and from `mid` to the end of the string slice.
+    ///
+    /// To get mutable string slices instead, see the [`split_at_mut_checked`]
+    /// method.
+    ///
+    /// [`split_at_mut_checked`]: str::split_at_mut_checked
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(split_at_checked)]
+    ///
+    /// let s = "Per Martin-Löf";
+    ///
+    /// let (first, last) = s.split_at_checked(3).unwrap();
+    /// assert_eq!("Per", first);
+    /// assert_eq!(" Martin-Löf", last);
+    ///
+    /// assert_eq!(None, s.split_at_checked(13));  // Inside “ö”
+    /// assert_eq!(None, s.split_at_checked(16));  // Beyond the string length
+    /// ```
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
+    pub fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> {
+        // is_char_boundary checks that the index is in [0, .len()]
+        if self.is_char_boundary(mid) {
+            // SAFETY: just checked that `mid` is on a char boundary.
+            Some(unsafe { (self.get_unchecked(0..mid), self.get_unchecked(mid..self.len())) })
+        } else {
+            None
+        }
+    }
+
+    /// Divide one mutable string slice into two at an index.
+    ///
+    /// The argument, `mid`, should be a valid byte offset from the start of the
+    /// string. It must also be on the boundary of a UTF-8 code point. The
+    /// method returns `None` if that’s not the case.
+    ///
+    /// The two slices returned go from the start of the string slice to `mid`,
+    /// and from `mid` to the end of the string slice.
+    ///
+    /// To get immutable string slices instead, see the [`split_at_checked`] method.
+    ///
+    /// [`split_at_checked`]: str::split_at_checked
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(split_at_checked)]
+    ///
+    /// let mut s = "Per Martin-Löf".to_string();
+    /// if let Some((first, last)) = s.split_at_mut_checked(3) {
+    ///     first.make_ascii_uppercase();
+    ///     assert_eq!("PER", first);
+    ///     assert_eq!(" Martin-Löf", last);
+    /// }
+    /// assert_eq!("PER Martin-Löf", s);
+    ///
+    /// assert_eq!(None, s.split_at_mut_checked(13));  // Inside “ö”
+    /// assert_eq!(None, s.split_at_mut_checked(16));  // Beyond the string length
+    /// ```
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
+    pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str)> {
+        // is_char_boundary checks that the index is in [0, .len()]
+        if self.is_char_boundary(mid) {
+            // SAFETY: just checked that `mid` is on a char boundary.
+            Some(unsafe { self.split_at_mut_unchecked(mid) })
+        } else {
+            None
+        }
+    }
+
+    /// Divide one string slice into two at an index.
+    ///
+    /// # Safety
+    ///
+    /// The caller must ensure that `mid` is a valid byte offset from the start
+    /// of the string and falls on the boundary of a UTF-8 code point.
+    unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut str, &mut str) {
+        let len = self.len();
+        let ptr = self.as_mut_ptr();
+        // SAFETY: caller guarantees `mid` is on a char boundary.
+        unsafe {
+            (
+                from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
+                from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr.add(mid), len - mid)),
+            )
+        }
+    }
+
     /// Returns an iterator over the [`char`]s of a string slice.
     ///
     /// As a string slice consists of valid UTF-8, we can iterate through a
diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs
index 8bf1e2dca6f7b..ecc0bbce5437a 100644
--- a/library/std/src/os/unix/net/listener.rs
+++ b/library/std/src/os/unix/net/listener.rs
@@ -80,7 +80,12 @@ impl UnixListener {
                 target_os = "horizon"
             ))]
             const backlog: libc::c_int = 128;
-            #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))]
+            #[cfg(any(
+                target_os = "linux",
+                target_os = "freebsd",
+                target_os = "openbsd",
+                target_os = "macos"
+            ))]
             const backlog: libc::c_int = -1;
             #[cfg(not(any(
                 target_os = "windows",
@@ -88,6 +93,7 @@ impl UnixListener {
                 target_os = "linux",
                 target_os = "freebsd",
                 target_os = "openbsd",
+                target_os = "macos",
                 target_os = "espidf",
                 target_os = "horizon"
             )))]
diff --git a/library/std/src/os/xous/ffi.rs b/library/std/src/os/xous/ffi.rs
index 8be7fbb102f3e..7fe84db515c34 100644
--- a/library/std/src/os/xous/ffi.rs
+++ b/library/std/src/os/xous/ffi.rs
@@ -88,29 +88,31 @@ fn lend_impl(
     let a3 = opcode;
     let a4 = data.as_ptr() as usize;
     let a5 = data.len();
-    let mut a6 = arg1;
-    let mut a7 = arg2;
+    let a6 = arg1;
+    let a7 = arg2;
+    let mut ret1;
+    let mut ret2;
 
     unsafe {
         core::arch::asm!(
             "ecall",
             inlateout("a0") a0,
-            inlateout("a1") a1 => _,
-            inlateout("a2") a2 => _,
+            inlateout("a1") a1 => ret1,
+            inlateout("a2") a2 => ret2,
             inlateout("a3") a3 => _,
             inlateout("a4") a4 => _,
             inlateout("a5") a5 => _,
-            inlateout("a6") a6,
-            inlateout("a7") a7,
+            inlateout("a6") a6 => _,
+            inlateout("a7") a7 => _,
         )
     };
 
     let result = a0;
 
     if result == SyscallResult::MemoryReturned as usize {
-        Ok((a6, a7))
+        Ok((ret1, ret2))
     } else if result == SyscallResult::Error as usize {
-        Err(a1.into())
+        Err(ret1.into())
     } else {
         Err(Error::InternalError)
     }
@@ -405,7 +407,7 @@ pub(crate) unsafe fn map_memory<T>(
 pub(crate) unsafe fn unmap_memory<T>(range: *mut [T]) -> Result<(), Error> {
     let mut a0 = Syscall::UnmapMemory as usize;
     let mut a1 = range.as_mut_ptr() as usize;
-    let a2 = range.len();
+    let a2 = range.len() * core::mem::size_of::<T>();
     let a3 = 0;
     let a4 = 0;
     let a5 = 0;
@@ -450,7 +452,7 @@ pub(crate) unsafe fn update_memory_flags<T>(
 ) -> Result<(), Error> {
     let mut a0 = Syscall::UpdateMemoryFlags as usize;
     let mut a1 = range.as_mut_ptr() as usize;
-    let a2 = range.len();
+    let a2 = range.len() * core::mem::size_of::<T>();
     let a3 = new_flags.bits();
     let a4 = 0; // Process ID is currently None
     let a5 = 0;
diff --git a/library/std/src/os/xous/services.rs b/library/std/src/os/xous/services.rs
index 5c219f1fbb95e..a75be1b857003 100644
--- a/library/std/src/os/xous/services.rs
+++ b/library/std/src/os/xous/services.rs
@@ -1,9 +1,15 @@
 use crate::os::xous::ffi::Connection;
 use core::sync::atomic::{AtomicU32, Ordering};
 
+mod dns;
+pub(crate) use dns::*;
+
 mod log;
 pub(crate) use log::*;
 
+mod net;
+pub(crate) use net::*;
+
 mod systime;
 pub(crate) use systime::*;
 
diff --git a/library/std/src/os/xous/services/dns.rs b/library/std/src/os/xous/services/dns.rs
new file mode 100644
index 0000000000000..a7d88f4892cda
--- /dev/null
+++ b/library/std/src/os/xous/services/dns.rs
@@ -0,0 +1,28 @@
+use crate::os::xous::ffi::Connection;
+use crate::os::xous::services::connect;
+use core::sync::atomic::{AtomicU32, Ordering};
+
+#[repr(usize)]
+pub(crate) enum DnsLendMut {
+    RawLookup = 6,
+}
+
+impl Into<usize> for DnsLendMut {
+    fn into(self) -> usize {
+        self as usize
+    }
+}
+
+/// Return a `Connection` to the DNS lookup server. This server is used for
+/// querying domain name values.
+pub(crate) fn dns_server() -> Connection {
+    static DNS_CONNECTION: AtomicU32 = AtomicU32::new(0);
+    let cid = DNS_CONNECTION.load(Ordering::Relaxed);
+    if cid != 0 {
+        return cid.into();
+    }
+
+    let cid = connect("_DNS Resolver Middleware_").unwrap();
+    DNS_CONNECTION.store(cid.into(), Ordering::Relaxed);
+    cid
+}
diff --git a/library/std/src/os/xous/services/log.rs b/library/std/src/os/xous/services/log.rs
index e6bae929eac0e..55a501dc7d00e 100644
--- a/library/std/src/os/xous/services/log.rs
+++ b/library/std/src/os/xous/services/log.rs
@@ -45,6 +45,17 @@ impl<'a> Into<[usize; 5]> for LogScalar<'a> {
     }
 }
 
+pub(crate) enum LogLend {
+    StandardOutput = 1,
+    StandardError = 2,
+}
+
+impl Into<usize> for LogLend {
+    fn into(self) -> usize {
+        self as usize
+    }
+}
+
 /// Return a `Connection` to the log server, which is used for printing messages to
 /// the console and reporting panics. If the log server has not yet started, this
 /// will block until the server is running. It is safe to call this multiple times,
diff --git a/library/std/src/os/xous/services/net.rs b/library/std/src/os/xous/services/net.rs
new file mode 100644
index 0000000000000..26d337dcef168
--- /dev/null
+++ b/library/std/src/os/xous/services/net.rs
@@ -0,0 +1,95 @@
+use crate::os::xous::ffi::Connection;
+use crate::os::xous::services::connect;
+use core::sync::atomic::{AtomicU32, Ordering};
+
+pub(crate) enum NetBlockingScalar {
+    StdGetTtlUdp(u16 /* fd */),                /* 36 */
+    StdSetTtlUdp(u16 /* fd */, u32 /* ttl */), /* 37 */
+    StdGetTtlTcp(u16 /* fd */),                /* 36 */
+    StdSetTtlTcp(u16 /* fd */, u32 /* ttl */), /* 37 */
+    StdGetNodelay(u16 /* fd */),               /* 38 */
+    StdSetNodelay(u16 /* fd */, bool),         /* 39 */
+    StdTcpClose(u16 /* fd */),                 /* 34 */
+    StdUdpClose(u16 /* fd */),                 /* 41 */
+    StdTcpStreamShutdown(u16 /* fd */, crate::net::Shutdown /* how */), /* 46 */
+}
+
+pub(crate) enum NetLendMut {
+    StdTcpConnect,                                    /* 30 */
+    StdTcpTx(u16 /* fd */),                           /* 31 */
+    StdTcpPeek(u16 /* fd */, bool /* nonblocking */), /* 32 */
+    StdTcpRx(u16 /* fd */, bool /* nonblocking */),   /* 33 */
+    StdGetAddress(u16 /* fd */),                      /* 35 */
+    StdUdpBind,                                       /* 40 */
+    StdUdpRx(u16 /* fd */),                           /* 42 */
+    StdUdpTx(u16 /* fd */),                           /* 43 */
+    StdTcpListen,                                     /* 44 */
+    StdTcpAccept(u16 /* fd */),                       /* 45 */
+}
+
+impl Into<usize> for NetLendMut {
+    fn into(self) -> usize {
+        match self {
+            NetLendMut::StdTcpConnect => 30,
+            NetLendMut::StdTcpTx(fd) => 31 | ((fd as usize) << 16),
+            NetLendMut::StdTcpPeek(fd, blocking) => {
+                32 | ((fd as usize) << 16) | if blocking { 0x8000 } else { 0 }
+            }
+            NetLendMut::StdTcpRx(fd, blocking) => {
+                33 | ((fd as usize) << 16) | if blocking { 0x8000 } else { 0 }
+            }
+            NetLendMut::StdGetAddress(fd) => 35 | ((fd as usize) << 16),
+            NetLendMut::StdUdpBind => 40,
+            NetLendMut::StdUdpRx(fd) => 42 | ((fd as usize) << 16),
+            NetLendMut::StdUdpTx(fd) => 43 | ((fd as usize) << 16),
+            NetLendMut::StdTcpListen => 44,
+            NetLendMut::StdTcpAccept(fd) => 45 | ((fd as usize) << 16),
+        }
+    }
+}
+
+impl<'a> Into<[usize; 5]> for NetBlockingScalar {
+    fn into(self) -> [usize; 5] {
+        match self {
+            NetBlockingScalar::StdGetTtlTcp(fd) => [36 | ((fd as usize) << 16), 0, 0, 0, 0],
+            NetBlockingScalar::StdGetTtlUdp(fd) => [36 | ((fd as usize) << 16), 0, 0, 0, 1],
+            NetBlockingScalar::StdSetTtlTcp(fd, ttl) => {
+                [37 | ((fd as usize) << 16), ttl as _, 0, 0, 0]
+            }
+            NetBlockingScalar::StdSetTtlUdp(fd, ttl) => {
+                [37 | ((fd as usize) << 16), ttl as _, 0, 0, 1]
+            }
+            NetBlockingScalar::StdGetNodelay(fd) => [38 | ((fd as usize) << 16), 0, 0, 0, 0],
+            NetBlockingScalar::StdSetNodelay(fd, enabled) => {
+                [39 | ((fd as usize) << 16), if enabled { 1 } else { 0 }, 0, 0, 1]
+            }
+            NetBlockingScalar::StdTcpClose(fd) => [34 | ((fd as usize) << 16), 0, 0, 0, 0],
+            NetBlockingScalar::StdUdpClose(fd) => [41 | ((fd as usize) << 16), 0, 0, 0, 0],
+            NetBlockingScalar::StdTcpStreamShutdown(fd, how) => [
+                46 | ((fd as usize) << 16),
+                match how {
+                    crate::net::Shutdown::Read => 1,
+                    crate::net::Shutdown::Write => 2,
+                    crate::net::Shutdown::Both => 3,
+                },
+                0,
+                0,
+                0,
+            ],
+        }
+    }
+}
+
+/// Return a `Connection` to the Network server. This server provides all
+/// OS-level networking functions.
+pub(crate) fn net_server() -> Connection {
+    static NET_CONNECTION: AtomicU32 = AtomicU32::new(0);
+    let cid = NET_CONNECTION.load(Ordering::Relaxed);
+    if cid != 0 {
+        return cid.into();
+    }
+
+    let cid = connect("_Middleware Network Server_").unwrap();
+    NET_CONNECTION.store(cid.into(), Ordering::Relaxed);
+    cid
+}
diff --git a/library/std/src/sys/pal/xous/alloc.rs b/library/std/src/sys/pal/xous/alloc.rs
index b3a3e691e0d0c..0d540e9552072 100644
--- a/library/std/src/sys/pal/xous/alloc.rs
+++ b/library/std/src/sys/pal/xous/alloc.rs
@@ -1,7 +1,15 @@
 use crate::alloc::{GlobalAlloc, Layout, System};
 
+#[cfg(not(test))]
+#[export_name = "_ZN16__rust_internals3std3sys4xous5alloc8DLMALLOCE"]
 static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new();
 
+#[cfg(test)]
+extern "Rust" {
+    #[link_name = "_ZN16__rust_internals3std3sys4xous5alloc8DLMALLOCE"]
+    static mut DLMALLOC: dlmalloc::Dlmalloc;
+}
+
 #[stable(feature = "alloc_system_type", since = "1.28.0")]
 unsafe impl GlobalAlloc for System {
     #[inline]
diff --git a/library/std/src/sys/pal/xous/locks/condvar.rs b/library/std/src/sys/pal/xous/locks/condvar.rs
index 1bb38dfa34154..510235046e195 100644
--- a/library/std/src/sys/pal/xous/locks/condvar.rs
+++ b/library/std/src/sys/pal/xous/locks/condvar.rs
@@ -1,14 +1,17 @@
 use super::mutex::Mutex;
 use crate::os::xous::ffi::{blocking_scalar, scalar};
-use crate::os::xous::services::ticktimer_server;
-use crate::sync::Mutex as StdMutex;
+use crate::os::xous::services::{ticktimer_server, TicktimerScalar};
 use crate::time::Duration;
+use core::sync::atomic::{AtomicUsize, Ordering};
 
 // The implementation is inspired by Andrew D. Birrell's paper
 // "Implementing Condition Variables with Semaphores"
 
+const NOTIFY_TRIES: usize = 3;
+
 pub struct Condvar {
-    counter: StdMutex<usize>,
+    counter: AtomicUsize,
+    timed_out: AtomicUsize,
 }
 
 unsafe impl Send for Condvar {}
@@ -18,94 +21,128 @@ impl Condvar {
     #[inline]
     #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
     pub const fn new() -> Condvar {
-        Condvar { counter: StdMutex::new(0) }
+        Condvar { counter: AtomicUsize::new(0), timed_out: AtomicUsize::new(0) }
     }
 
-    pub fn notify_one(&self) {
-        let mut counter = self.counter.lock().unwrap();
-        if *counter <= 0 {
+    fn notify_some(&self, to_notify: usize) {
+        // Assumption: The Mutex protecting this condvar is locked throughout the
+        // entirety of this call, preventing calls to `wait` and `wait_timeout`.
+
+        // Logic check: Ensure that there aren't any missing waiters. Remove any that
+        // timed-out, ensuring the counter doesn't underflow.
+        assert!(self.timed_out.load(Ordering::Relaxed) <= self.counter.load(Ordering::Relaxed));
+        self.counter.fetch_sub(self.timed_out.swap(0, Ordering::Relaxed), Ordering::Relaxed);
+
+        // Figure out how many threads to notify. Note that it is impossible for `counter`
+        // to increase during this operation because Mutex is locked. However, it is
+        // possible for `counter` to decrease due to a condvar timing out, in which
+        // case the corresponding `timed_out` will increase accordingly.
+        let Ok(waiter_count) =
+            self.counter.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |counter| {
+                if counter == 0 {
+                    return None;
+                } else {
+                    Some(counter - counter.min(to_notify))
+                }
+            })
+        else {
+            // No threads are waiting on this condvar
             return;
-        } else {
-            *counter -= 1;
-        }
-        let result = blocking_scalar(
-            ticktimer_server(),
-            crate::os::xous::services::TicktimerScalar::NotifyCondition(self.index(), 1).into(),
-        );
-        drop(counter);
-        result.expect("failure to send NotifyCondition command");
-    }
+        };
 
-    pub fn notify_all(&self) {
-        let mut counter = self.counter.lock().unwrap();
-        if *counter <= 0 {
+        let mut remaining_to_wake = waiter_count.min(to_notify);
+        if remaining_to_wake == 0 {
             return;
         }
-        let result = blocking_scalar(
-            ticktimer_server(),
-            crate::os::xous::services::TicktimerScalar::NotifyCondition(self.index(), *counter)
-                .into(),
-        );
-        *counter = 0;
-        drop(counter);
+        for _wake_tries in 0..NOTIFY_TRIES {
+            let result = blocking_scalar(
+                ticktimer_server(),
+                TicktimerScalar::NotifyCondition(self.index(), remaining_to_wake).into(),
+            )
+            .expect("failure to send NotifyCondition command");
+
+            // Remove the list of waiters that were notified
+            remaining_to_wake -= result[0];
+
+            // Also remove the number of waiters that timed out. Clamp it to 0 in order to
+            // ensure we don't wait forever in case the waiter woke up between the time
+            // we counted the remaining waiters and now.
+            remaining_to_wake =
+                remaining_to_wake.saturating_sub(self.timed_out.swap(0, Ordering::Relaxed));
+            if remaining_to_wake == 0 {
+                return;
+            }
+            crate::thread::yield_now();
+        }
+    }
 
-        result.expect("failure to send NotifyCondition command");
+    pub fn notify_one(&self) {
+        self.notify_some(1)
+    }
+
+    pub fn notify_all(&self) {
+        self.notify_some(self.counter.load(Ordering::Relaxed))
     }
 
     fn index(&self) -> usize {
-        self as *const Condvar as usize
+        core::ptr::from_ref(self).addr()
     }
 
-    pub unsafe fn wait(&self, mutex: &Mutex) {
-        let mut counter = self.counter.lock().unwrap();
-        *counter += 1;
+    /// Unlock the given Mutex and wait for the notification. Wait at most
+    /// `ms` milliseconds, or pass `0` to wait forever.
+    ///
+    /// Returns `true` if the condition was received, `false` if it timed out
+    fn wait_ms(&self, mutex: &Mutex, ms: usize) -> bool {
+        self.counter.fetch_add(1, Ordering::Relaxed);
         unsafe { mutex.unlock() };
-        drop(counter);
 
+        // Threading concern: There is a chance that the `notify` thread wakes up here before
+        // we have a chance to wait for the condition. This is fine because we've recorded
+        // the fact that we're waiting by incrementing the counter.
         let result = blocking_scalar(
             ticktimer_server(),
-            crate::os::xous::services::TicktimerScalar::WaitForCondition(self.index(), 0).into(),
+            TicktimerScalar::WaitForCondition(self.index(), ms).into(),
         );
+        let awoken = result.expect("Ticktimer: failure to send WaitForCondition command")[0] == 0;
+
+        // If we awoke due to a timeout, increment the `timed_out` counter so that the
+        // main loop of `notify` knows there's a timeout.
+        //
+        // This is done with the Mutex still unlocked, because the Mutex might still
+        // be locked by the `notify` process above.
+        if !awoken {
+            self.timed_out.fetch_add(1, Ordering::Relaxed);
+        }
+
         unsafe { mutex.lock() };
+        awoken
+    }
 
-        result.expect("Ticktimer: failure to send WaitForCondition command");
+    pub unsafe fn wait(&self, mutex: &Mutex) {
+        // Wait for 0 ms, which is a special case to "wait forever"
+        self.wait_ms(mutex, 0);
     }
 
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        let mut counter = self.counter.lock().unwrap();
-        *counter += 1;
-        unsafe { mutex.unlock() };
-        drop(counter);
-
         let mut millis = dur.as_millis() as usize;
+        // Ensure we don't wait for 0 ms, which would cause us to wait forever
         if millis == 0 {
             millis = 1;
         }
-
-        let result = blocking_scalar(
-            ticktimer_server(),
-            crate::os::xous::services::TicktimerScalar::WaitForCondition(self.index(), millis)
-                .into(),
-        );
-        unsafe { mutex.lock() };
-
-        let result = result.expect("Ticktimer: failure to send WaitForCondition command")[0] == 0;
-
-        // If we awoke due to a timeout, decrement the wake count, as that would not have
-        // been done in the `notify()` call.
-        if !result {
-            *self.counter.lock().unwrap() -= 1;
-        }
-        result
+        self.wait_ms(mutex, millis)
     }
 }
 
 impl Drop for Condvar {
     fn drop(&mut self) {
-        scalar(
-            ticktimer_server(),
-            crate::os::xous::services::TicktimerScalar::FreeCondition(self.index()).into(),
-        )
-        .ok();
+        let remaining_count = self.counter.load(Ordering::Relaxed);
+        let timed_out = self.timed_out.load(Ordering::Relaxed);
+        assert!(
+            remaining_count - timed_out == 0,
+            "counter was {} and timed_out was {} not 0",
+            remaining_count,
+            timed_out
+        );
+        scalar(ticktimer_server(), TicktimerScalar::FreeCondition(self.index()).into()).ok();
     }
 }
diff --git a/library/std/src/sys/pal/xous/locks/mutex.rs b/library/std/src/sys/pal/xous/locks/mutex.rs
index ea51776d54eca..a8c9518ff0bcf 100644
--- a/library/std/src/sys/pal/xous/locks/mutex.rs
+++ b/library/std/src/sys/pal/xous/locks/mutex.rs
@@ -1,5 +1,5 @@
-use crate::os::xous::ffi::{blocking_scalar, do_yield, scalar};
-use crate::os::xous::services::ticktimer_server;
+use crate::os::xous::ffi::{blocking_scalar, do_yield};
+use crate::os::xous::services::{ticktimer_server, TicktimerScalar};
 use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering::Relaxed, Ordering::SeqCst};
 
 pub struct Mutex {
@@ -29,7 +29,7 @@ impl Mutex {
     }
 
     fn index(&self) -> usize {
-        self as *const Mutex as usize
+        core::ptr::from_ref(self).addr()
     }
 
     #[inline]
@@ -83,11 +83,8 @@ impl Mutex {
         }
 
         // Unblock one thread that is waiting on this message.
-        scalar(
-            ticktimer_server(),
-            crate::os::xous::services::TicktimerScalar::UnlockMutex(self.index()).into(),
-        )
-        .expect("failure to send UnlockMutex command");
+        blocking_scalar(ticktimer_server(), TicktimerScalar::UnlockMutex(self.index()).into())
+            .expect("failure to send UnlockMutex command");
     }
 
     #[inline]
@@ -106,11 +103,8 @@ impl Drop for Mutex {
         // If there was Mutex contention, then we involved the ticktimer. Free
         // the resources associated with this Mutex as it is deallocated.
         if self.contended.load(Relaxed) {
-            scalar(
-                ticktimer_server(),
-                crate::os::xous::services::TicktimerScalar::FreeMutex(self.index()).into(),
-            )
-            .ok();
+            blocking_scalar(ticktimer_server(), TicktimerScalar::FreeMutex(self.index()).into())
+                .ok();
         }
     }
 }
diff --git a/library/std/src/sys/pal/xous/locks/rwlock.rs b/library/std/src/sys/pal/xous/locks/rwlock.rs
index 618da758adfa7..ab45b33e1f69b 100644
--- a/library/std/src/sys/pal/xous/locks/rwlock.rs
+++ b/library/std/src/sys/pal/xous/locks/rwlock.rs
@@ -1,5 +1,5 @@
-use crate::os::xous::ffi::do_yield;
-use crate::sync::atomic::{AtomicIsize, Ordering::SeqCst};
+use crate::sync::atomic::{AtomicIsize, Ordering::Acquire};
+use crate::thread::yield_now;
 
 pub struct RwLock {
     /// The "mode" value indicates how many threads are waiting on this
@@ -14,6 +14,9 @@ pub struct RwLock {
     mode: AtomicIsize,
 }
 
+const RWLOCK_WRITING: isize = -1;
+const RWLOCK_FREE: isize = 0;
+
 unsafe impl Send for RwLock {}
 unsafe impl Sync for RwLock {}
 
@@ -21,52 +24,51 @@ impl RwLock {
     #[inline]
     #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
     pub const fn new() -> RwLock {
-        RwLock { mode: AtomicIsize::new(0) }
+        RwLock { mode: AtomicIsize::new(RWLOCK_FREE) }
     }
 
     #[inline]
     pub unsafe fn read(&self) {
         while !unsafe { self.try_read() } {
-            do_yield();
+            yield_now();
         }
     }
 
     #[inline]
     pub unsafe fn try_read(&self) -> bool {
-        // Non-atomically determine the current value.
-        let current = self.mode.load(SeqCst);
-
-        // If it's currently locked for writing, then we cannot read.
-        if current < 0 {
-            return false;
-        }
-
-        // Attempt to lock. If the `current` value has changed, then this
-        // operation will fail and we will not obtain the lock even if we
-        // could potentially keep it.
-        let new = current + 1;
-        self.mode.compare_exchange(current, new, SeqCst, SeqCst).is_ok()
+        self.mode
+            .fetch_update(
+                Acquire,
+                Acquire,
+                |v| if v == RWLOCK_WRITING { None } else { Some(v + 1) },
+            )
+            .is_ok()
     }
 
     #[inline]
     pub unsafe fn write(&self) {
         while !unsafe { self.try_write() } {
-            do_yield();
+            yield_now();
         }
     }
 
     #[inline]
     pub unsafe fn try_write(&self) -> bool {
-        self.mode.compare_exchange(0, -1, SeqCst, SeqCst).is_ok()
+        self.mode.compare_exchange(RWLOCK_FREE, RWLOCK_WRITING, Acquire, Acquire).is_ok()
     }
 
     #[inline]
     pub unsafe fn read_unlock(&self) {
-        self.mode.fetch_sub(1, SeqCst);
+        let previous = self.mode.fetch_sub(1, Acquire);
+        assert!(previous != RWLOCK_FREE);
+        assert!(previous != RWLOCK_WRITING);
     }
 
     #[inline]
     pub unsafe fn write_unlock(&self) {
-        assert_eq!(self.mode.compare_exchange(-1, 0, SeqCst, SeqCst), Ok(-1));
+        assert_eq!(
+            self.mode.compare_exchange(RWLOCK_WRITING, RWLOCK_FREE, Acquire, Acquire),
+            Ok(RWLOCK_WRITING)
+        );
     }
 }
diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs
index 230067907c8f0..516d0a68720c6 100644
--- a/library/std/src/sys/pal/xous/mod.rs
+++ b/library/std/src/sys/pal/xous/mod.rs
@@ -12,10 +12,7 @@ pub mod fs;
 #[path = "../unsupported/io.rs"]
 pub mod io;
 pub mod locks;
-#[path = "../unsupported/net.rs"]
 pub mod net;
-#[path = "../unsupported/once.rs"]
-pub mod once;
 pub mod os;
 #[path = "../unix/path.rs"]
 pub mod path;
diff --git a/library/std/src/sys/pal/xous/net/dns.rs b/library/std/src/sys/pal/xous/net/dns.rs
new file mode 100644
index 0000000000000..63056324bfbd9
--- /dev/null
+++ b/library/std/src/sys/pal/xous/net/dns.rs
@@ -0,0 +1,127 @@
+use crate::io;
+use crate::net::{Ipv4Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+use crate::os::xous::ffi::lend_mut;
+use crate::os::xous::services::{dns_server, DnsLendMut};
+use core::convert::{TryFrom, TryInto};
+
+pub struct DnsError {
+    pub code: u8,
+}
+
+#[repr(C, align(4096))]
+struct LookupHostQuery([u8; 4096]);
+
+pub struct LookupHost {
+    data: LookupHostQuery,
+    port: u16,
+    offset: usize,
+    count: usize,
+}
+
+impl LookupHost {
+    pub fn port(&self) -> u16 {
+        self.port
+    }
+}
+
+impl Iterator for LookupHost {
+    type Item = SocketAddr;
+    fn next(&mut self) -> Option<SocketAddr> {
+        if self.offset >= self.data.0.len() {
+            return None;
+        }
+        match self.data.0.get(self.offset) {
+            Some(&4) => {
+                self.offset += 1;
+                if self.offset + 4 > self.data.0.len() {
+                    return None;
+                }
+                let result = Some(SocketAddr::V4(SocketAddrV4::new(
+                    Ipv4Addr::new(
+                        self.data.0[self.offset],
+                        self.data.0[self.offset + 1],
+                        self.data.0[self.offset + 2],
+                        self.data.0[self.offset + 3],
+                    ),
+                    self.port,
+                )));
+                self.offset += 4;
+                result
+            }
+            Some(&6) => {
+                self.offset += 1;
+                if self.offset + 16 > self.data.0.len() {
+                    return None;
+                }
+                let mut new_addr = [0u8; 16];
+                for (src, octet) in self.data.0[(self.offset + 1)..(self.offset + 16 + 1)]
+                    .iter()
+                    .zip(new_addr.iter_mut())
+                {
+                    *octet = *src;
+                }
+                let result =
+                    Some(SocketAddr::V6(SocketAddrV6::new(new_addr.into(), self.port, 0, 0)));
+                self.offset += 16;
+                result
+            }
+            _ => None,
+        }
+    }
+}
+
+pub fn lookup(query: &str, port: u16) -> Result<LookupHost, DnsError> {
+    let mut result = LookupHost { data: LookupHostQuery([0u8; 4096]), offset: 0, count: 0, port };
+
+    // Copy the query into the message that gets sent to the DNS server
+    for (query_byte, result_byte) in query.as_bytes().iter().zip(result.data.0.iter_mut()) {
+        *result_byte = *query_byte;
+    }
+
+    lend_mut(
+        dns_server(),
+        DnsLendMut::RawLookup.into(),
+        &mut result.data.0,
+        0,
+        query.as_bytes().len(),
+    )
+    .unwrap();
+    if result.data.0[0] != 0 {
+        return Err(DnsError { code: result.data.0[1] });
+    }
+    assert_eq!(result.offset, 0);
+    result.count = result.data.0[1] as usize;
+
+    // Advance the offset to the first record
+    result.offset = 2;
+    Ok(result)
+}
+
+impl TryFrom<&str> for LookupHost {
+    type Error = io::Error;
+
+    fn try_from(s: &str) -> io::Result<LookupHost> {
+        macro_rules! try_opt {
+            ($e:expr, $msg:expr) => {
+                match $e {
+                    Some(r) => r,
+                    None => return Err(io::const_io_error!(io::ErrorKind::InvalidInput, &$msg)),
+                }
+            };
+        }
+
+        // split the string by ':' and convert the second part to u16
+        let (host, port_str) = try_opt!(s.rsplit_once(':'), "invalid socket address");
+        let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
+        (host, port).try_into()
+    }
+}
+
+impl TryFrom<(&str, u16)> for LookupHost {
+    type Error = io::Error;
+
+    fn try_from(v: (&str, u16)) -> io::Result<LookupHost> {
+        lookup(v.0, v.1)
+            .map_err(|_e| io::const_io_error!(io::ErrorKind::InvalidInput, &"DNS failure"))
+    }
+}
diff --git a/library/std/src/sys/pal/xous/net/mod.rs b/library/std/src/sys/pal/xous/net/mod.rs
new file mode 100644
index 0000000000000..b5a3da136a6b0
--- /dev/null
+++ b/library/std/src/sys/pal/xous/net/mod.rs
@@ -0,0 +1,84 @@
+mod dns;
+
+mod tcpstream;
+pub use tcpstream::*;
+
+mod tcplistener;
+pub use tcplistener::*;
+
+mod udp;
+pub use udp::*;
+
+// this structure needs to be synchronized with what's in net/src/api.rs
+#[repr(C)]
+#[derive(Debug)]
+enum NetError {
+    // Ok = 0,
+    Unaddressable = 1,
+    SocketInUse = 2,
+    // AccessDenied = 3,
+    Invalid = 4,
+    // Finished = 5,
+    LibraryError = 6,
+    // AlreadyUsed = 7,
+    TimedOut = 8,
+    WouldBlock = 9,
+}
+
+#[repr(C, align(4096))]
+struct ConnectRequest {
+    raw: [u8; 4096],
+}
+
+#[repr(C, align(4096))]
+struct SendData {
+    raw: [u8; 4096],
+}
+
+#[repr(C, align(4096))]
+pub struct ReceiveData {
+    raw: [u8; 4096],
+}
+
+#[repr(C, align(4096))]
+pub struct GetAddress {
+    raw: [u8; 4096],
+}
+
+pub use dns::LookupHost;
+
+#[allow(nonstandard_style)]
+pub mod netc {
+    pub const AF_INET: u8 = 0;
+    pub const AF_INET6: u8 = 1;
+    pub type sa_family_t = u8;
+
+    #[derive(Copy, Clone)]
+    pub struct in_addr {
+        pub s_addr: u32,
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct sockaddr_in {
+        pub sin_family: sa_family_t,
+        pub sin_port: u16,
+        pub sin_addr: in_addr,
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct in6_addr {
+        pub s6_addr: [u8; 16],
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct sockaddr_in6 {
+        pub sin6_family: sa_family_t,
+        pub sin6_port: u16,
+        pub sin6_addr: in6_addr,
+        pub sin6_flowinfo: u32,
+        pub sin6_scope_id: u32,
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct sockaddr {}
+}
diff --git a/library/std/src/sys/pal/xous/net/tcplistener.rs b/library/std/src/sys/pal/xous/net/tcplistener.rs
new file mode 100644
index 0000000000000..47305013083c8
--- /dev/null
+++ b/library/std/src/sys/pal/xous/net/tcplistener.rs
@@ -0,0 +1,247 @@
+use super::*;
+use crate::fmt;
+use crate::io;
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
+use crate::os::xous::services;
+use crate::sync::Arc;
+use core::convert::TryInto;
+use core::sync::atomic::{AtomicBool, AtomicU16, AtomicUsize, Ordering};
+
+macro_rules! unimpl {
+    () => {
+        return Err(io::const_io_error!(
+            io::ErrorKind::Unsupported,
+            &"This function is not yet implemented",
+        ));
+    };
+}
+
+#[derive(Clone)]
+pub struct TcpListener {
+    fd: Arc<AtomicU16>,
+    local: SocketAddr,
+    handle_count: Arc<AtomicUsize>,
+    nonblocking: Arc<AtomicBool>,
+}
+
+impl TcpListener {
+    pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
+        let mut addr = *socketaddr?;
+
+        let fd = TcpListener::bind_inner(&mut addr)?;
+        return Ok(TcpListener {
+            fd: Arc::new(AtomicU16::new(fd)),
+            local: addr,
+            handle_count: Arc::new(AtomicUsize::new(1)),
+            nonblocking: Arc::new(AtomicBool::new(false)),
+        });
+    }
+
+    /// This returns the raw fd of a Listener, so that it can also be used by the
+    /// accept routine to replenish the Listener object after its handle has been converted into
+    /// a TcpStream object.
+    fn bind_inner(addr: &mut SocketAddr) -> io::Result<u16> {
+        // Construct the request
+        let mut connect_request = ConnectRequest { raw: [0u8; 4096] };
+
+        // Serialize the StdUdpBind structure. This is done "manually" because we don't want to
+        // make an auto-serdes (like bincode or rkyv) crate a dependency of Xous.
+        let port_bytes = addr.port().to_le_bytes();
+        connect_request.raw[0] = port_bytes[0];
+        connect_request.raw[1] = port_bytes[1];
+        match addr.ip() {
+            IpAddr::V4(addr) => {
+                connect_request.raw[2] = 4;
+                for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
+                    *dest = src;
+                }
+            }
+            IpAddr::V6(addr) => {
+                connect_request.raw[2] = 6;
+                for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
+                    *dest = src;
+                }
+            }
+        }
+
+        let Ok((_, valid)) = crate::os::xous::ffi::lend_mut(
+            services::net_server(),
+            services::NetLendMut::StdTcpListen.into(),
+            &mut connect_request.raw,
+            0,
+            4096,
+        ) else {
+            return Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Invalid response"));
+        };
+
+        // The first four bytes should be zero upon success, and will be nonzero
+        // for an error.
+        let response = connect_request.raw;
+        if response[0] != 0 || valid == 0 {
+            let errcode = response[1];
+            if errcode == NetError::SocketInUse as u8 {
+                return Err(io::const_io_error!(io::ErrorKind::ResourceBusy, &"Socket in use"));
+            } else if errcode == NetError::Invalid as u8 {
+                return Err(io::const_io_error!(
+                    io::ErrorKind::AddrNotAvailable,
+                    &"Invalid address"
+                ));
+            } else if errcode == NetError::LibraryError as u8 {
+                return Err(io::const_io_error!(io::ErrorKind::Other, &"Library error"));
+            } else {
+                return Err(io::const_io_error!(
+                    io::ErrorKind::Other,
+                    &"Unable to connect or internal error"
+                ));
+            }
+        }
+        let fd = response[1] as usize;
+        if addr.port() == 0 {
+            // oddly enough, this is a valid port and it means "give me something valid, up to you what that is"
+            let assigned_port = u16::from_le_bytes(response[2..4].try_into().unwrap());
+            addr.set_port(assigned_port);
+        }
+        // println!("TcpListening with file handle of {}\r\n", fd);
+        Ok(fd.try_into().unwrap())
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        Ok(self.local)
+    }
+
+    pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
+        let mut receive_request = ReceiveData { raw: [0u8; 4096] };
+
+        if self.nonblocking.load(Ordering::Relaxed) {
+            // nonblocking
+            receive_request.raw[0] = 0;
+        } else {
+            // blocking
+            receive_request.raw[0] = 1;
+        }
+
+        if let Ok((_offset, _valid)) = crate::os::xous::ffi::lend_mut(
+            services::net_server(),
+            services::NetLendMut::StdTcpAccept(self.fd.load(Ordering::Relaxed)).into(),
+            &mut receive_request.raw,
+            0,
+            0,
+        ) {
+            if receive_request.raw[0] != 0 {
+                // error case
+                if receive_request.raw[1] == NetError::TimedOut as u8 {
+                    return Err(io::const_io_error!(io::ErrorKind::TimedOut, &"accept timed out",));
+                } else if receive_request.raw[1] == NetError::WouldBlock as u8 {
+                    return Err(io::const_io_error!(
+                        io::ErrorKind::WouldBlock,
+                        &"accept would block",
+                    ));
+                } else if receive_request.raw[1] == NetError::LibraryError as u8 {
+                    return Err(io::const_io_error!(io::ErrorKind::Other, &"Library error"));
+                } else {
+                    return Err(io::const_io_error!(io::ErrorKind::Other, &"library error",));
+                }
+            } else {
+                // accept successful
+                let rr = &receive_request.raw;
+                let stream_fd = u16::from_le_bytes(rr[1..3].try_into().unwrap());
+                let port = u16::from_le_bytes(rr[20..22].try_into().unwrap());
+                let addr = if rr[3] == 4 {
+                    SocketAddr::new(IpAddr::V4(Ipv4Addr::new(rr[4], rr[5], rr[6], rr[7])), port)
+                } else if rr[3] == 6 {
+                    SocketAddr::new(
+                        IpAddr::V6(Ipv6Addr::new(
+                            u16::from_be_bytes(rr[4..6].try_into().unwrap()),
+                            u16::from_be_bytes(rr[6..8].try_into().unwrap()),
+                            u16::from_be_bytes(rr[8..10].try_into().unwrap()),
+                            u16::from_be_bytes(rr[10..12].try_into().unwrap()),
+                            u16::from_be_bytes(rr[12..14].try_into().unwrap()),
+                            u16::from_be_bytes(rr[14..16].try_into().unwrap()),
+                            u16::from_be_bytes(rr[16..18].try_into().unwrap()),
+                            u16::from_be_bytes(rr[18..20].try_into().unwrap()),
+                        )),
+                        port,
+                    )
+                } else {
+                    return Err(io::const_io_error!(io::ErrorKind::Other, &"library error",));
+                };
+
+                // replenish the listener
+                let mut local_copy = self.local.clone(); // port is non-0 by this time, but the method signature needs a mut
+                let new_fd = TcpListener::bind_inner(&mut local_copy)?;
+                self.fd.store(new_fd, Ordering::Relaxed);
+
+                // now return a stream converted from the old stream's fd
+                Ok((TcpStream::from_listener(stream_fd, self.local.port(), port, addr), addr))
+            }
+        } else {
+            Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unable to accept"))
+        }
+    }
+
+    pub fn duplicate(&self) -> io::Result<TcpListener> {
+        self.handle_count.fetch_add(1, Ordering::Relaxed);
+        Ok(self.clone())
+    }
+
+    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+        if ttl > 255 {
+            return Err(io::Error::new(io::ErrorKind::InvalidInput, "TTL must be less than 256"));
+        }
+        crate::os::xous::ffi::blocking_scalar(
+            services::net_server(),
+            services::NetBlockingScalar::StdSetTtlTcp(self.fd.load(Ordering::Relaxed), ttl).into(),
+        )
+        .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value")))
+        .map(|_| ())
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        Ok(crate::os::xous::ffi::blocking_scalar(
+            services::net_server(),
+            services::NetBlockingScalar::StdGetTtlTcp(self.fd.load(Ordering::Relaxed)).into(),
+        )
+        .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value")))
+        .map(|res| res[0] as _)?)
+    }
+
+    pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
+        unimpl!();
+    }
+
+    pub fn only_v6(&self) -> io::Result<bool> {
+        unimpl!();
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        // this call doesn't have a meaning on our platform, but we can at least not panic if it's used.
+        Ok(None)
+    }
+
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        self.nonblocking.store(nonblocking, Ordering::Relaxed);
+        Ok(())
+    }
+}
+
+impl fmt::Debug for TcpListener {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "TCP listening on {:?}", self.local)
+    }
+}
+
+impl Drop for TcpListener {
+    fn drop(&mut self) {
+        if self.handle_count.fetch_sub(1, Ordering::Relaxed) == 1 {
+            // only drop if we're the last clone
+            crate::os::xous::ffi::blocking_scalar(
+                services::net_server(),
+                crate::os::xous::services::NetBlockingScalar::StdTcpClose(
+                    self.fd.load(Ordering::Relaxed),
+                )
+                .into(),
+            )
+            .unwrap();
+        }
+    }
+}
diff --git a/library/std/src/sys/pal/xous/net/tcpstream.rs b/library/std/src/sys/pal/xous/net/tcpstream.rs
new file mode 100644
index 0000000000000..7149678118ab6
--- /dev/null
+++ b/library/std/src/sys/pal/xous/net/tcpstream.rs
@@ -0,0 +1,435 @@
+use super::*;
+use crate::fmt;
+use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
+use crate::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6};
+use crate::os::xous::services;
+use crate::sync::Arc;
+use crate::time::Duration;
+use core::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering};
+
+macro_rules! unimpl {
+    () => {
+        return Err(io::const_io_error!(
+            io::ErrorKind::Unsupported,
+            &"This function is not yet implemented",
+        ));
+    };
+}
+
+enum ReadOrPeek {
+    Read,
+    Peek,
+}
+
+#[derive(Clone)]
+pub struct TcpStream {
+    fd: u16,
+    local_port: u16,
+    remote_port: u16,
+    peer_addr: SocketAddr,
+    // milliseconds
+    read_timeout: Arc<AtomicU32>,
+    // milliseconds
+    write_timeout: Arc<AtomicU32>,
+    handle_count: Arc<AtomicUsize>,
+    nonblocking: Arc<AtomicBool>,
+}
+
+fn sockaddr_to_buf(duration: Duration, addr: &SocketAddr, buf: &mut [u8]) {
+    // Construct the request.
+    let port_bytes = addr.port().to_le_bytes();
+    buf[0] = port_bytes[0];
+    buf[1] = port_bytes[1];
+    for (dest, src) in buf[2..].iter_mut().zip((duration.as_millis() as u64).to_le_bytes()) {
+        *dest = src;
+    }
+    match addr.ip() {
+        IpAddr::V4(addr) => {
+            buf[10] = 4;
+            for (dest, src) in buf[11..].iter_mut().zip(addr.octets()) {
+                *dest = src;
+            }
+        }
+        IpAddr::V6(addr) => {
+            buf[10] = 6;
+            for (dest, src) in buf[11..].iter_mut().zip(addr.octets()) {
+                *dest = src;
+            }
+        }
+    }
+}
+
+impl TcpStream {
+    pub(crate) fn from_listener(
+        fd: u16,
+        local_port: u16,
+        remote_port: u16,
+        peer_addr: SocketAddr,
+    ) -> TcpStream {
+        TcpStream {
+            fd,
+            local_port,
+            remote_port,
+            peer_addr,
+            read_timeout: Arc::new(AtomicU32::new(0)),
+            write_timeout: Arc::new(AtomicU32::new(0)),
+            handle_count: Arc::new(AtomicUsize::new(1)),
+            nonblocking: Arc::new(AtomicBool::new(false)),
+        }
+    }
+
+    pub fn connect(socketaddr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
+        Self::connect_timeout(socketaddr?, Duration::ZERO)
+    }
+
+    pub fn connect_timeout(addr: &SocketAddr, duration: Duration) -> io::Result<TcpStream> {
+        let mut connect_request = ConnectRequest { raw: [0u8; 4096] };
+
+        // Construct the request.
+        sockaddr_to_buf(duration, &addr, &mut connect_request.raw);
+
+        let Ok((_, valid)) = crate::os::xous::ffi::lend_mut(
+            services::net_server(),
+            services::NetLendMut::StdTcpConnect.into(),
+            &mut connect_request.raw,
+            0,
+            4096,
+        ) else {
+            return Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Invalid response"));
+        };
+
+        // The first four bytes should be zero upon success, and will be nonzero
+        // for an error.
+        let response = connect_request.raw;
+        if response[0] != 0 || valid == 0 {
+            // errcode is a u8 but stuck in a u16 where the upper byte is invalid. Mask & decode accordingly.
+            let errcode = response[0];
+            if errcode == NetError::SocketInUse as u8 {
+                return Err(io::const_io_error!(io::ErrorKind::ResourceBusy, &"Socket in use",));
+            } else if errcode == NetError::Unaddressable as u8 {
+                return Err(io::const_io_error!(
+                    io::ErrorKind::AddrNotAvailable,
+                    &"Invalid address",
+                ));
+            } else {
+                return Err(io::const_io_error!(
+                    io::ErrorKind::InvalidInput,
+                    &"Unable to connect or internal error",
+                ));
+            }
+        }
+        let fd = u16::from_le_bytes([response[2], response[3]]);
+        let local_port = u16::from_le_bytes([response[4], response[5]]);
+        let remote_port = u16::from_le_bytes([response[6], response[7]]);
+        // println!(
+        //     "Connected with local port of {}, remote port of {}, file handle of {}",
+        //     local_port, remote_port, fd
+        // );
+        Ok(TcpStream {
+            fd,
+            local_port,
+            remote_port,
+            peer_addr: *addr,
+            read_timeout: Arc::new(AtomicU32::new(0)),
+            write_timeout: Arc::new(AtomicU32::new(0)),
+            handle_count: Arc::new(AtomicUsize::new(1)),
+            nonblocking: Arc::new(AtomicBool::new(false)),
+        })
+    }
+
+    pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        if let Some(to) = timeout {
+            if to.is_zero() {
+                return Err(io::const_io_error!(
+                    io::ErrorKind::InvalidInput,
+                    &"Zero is an invalid timeout",
+                ));
+            }
+        }
+        self.read_timeout.store(
+            timeout.map(|t| t.as_millis().min(u32::MAX as u128) as u32).unwrap_or_default(),
+            Ordering::Relaxed,
+        );
+        Ok(())
+    }
+
+    pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        if let Some(to) = timeout {
+            if to.is_zero() {
+                return Err(io::const_io_error!(
+                    io::ErrorKind::InvalidInput,
+                    &"Zero is an invalid timeout",
+                ));
+            }
+        }
+        self.write_timeout.store(
+            timeout.map(|t| t.as_millis().min(u32::MAX as u128) as u32).unwrap_or_default(),
+            Ordering::Relaxed,
+        );
+        Ok(())
+    }
+
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.read_timeout.load(Ordering::Relaxed) {
+            0 => Ok(None),
+            t => Ok(Some(Duration::from_millis(t as u64))),
+        }
+    }
+
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.write_timeout.load(Ordering::Relaxed) {
+            0 => Ok(None),
+            t => Ok(Some(Duration::from_millis(t as u64))),
+        }
+    }
+
+    fn read_or_peek(&self, buf: &mut [u8], op: ReadOrPeek) -> io::Result<usize> {
+        let mut receive_request = ReceiveData { raw: [0u8; 4096] };
+        let data_to_read = buf.len().min(receive_request.raw.len());
+
+        let opcode = match op {
+            ReadOrPeek::Read => {
+                services::NetLendMut::StdTcpRx(self.fd, self.nonblocking.load(Ordering::Relaxed))
+            }
+            ReadOrPeek::Peek => {
+                services::NetLendMut::StdTcpPeek(self.fd, self.nonblocking.load(Ordering::Relaxed))
+            }
+        };
+
+        let Ok((offset, length)) = crate::os::xous::ffi::lend_mut(
+            services::net_server(),
+            opcode.into(),
+            &mut receive_request.raw,
+            // Reuse the `offset` as the read timeout
+            self.read_timeout.load(Ordering::Relaxed) as usize,
+            data_to_read,
+        ) else {
+            return Err(io::const_io_error!(
+                io::ErrorKind::InvalidInput,
+                &"Library failure: wrong message type or messaging error"
+            ));
+        };
+
+        if offset != 0 {
+            for (dest, src) in buf.iter_mut().zip(receive_request.raw[..length].iter()) {
+                *dest = *src;
+            }
+            Ok(length)
+        } else {
+            let result = receive_request.raw;
+            if result[0] != 0 {
+                if result[1] == 8 {
+                    // timed out
+                    return Err(io::const_io_error!(io::ErrorKind::TimedOut, &"Timeout",));
+                }
+                if result[1] == 9 {
+                    // would block
+                    return Err(io::const_io_error!(io::ErrorKind::WouldBlock, &"Would block",));
+                }
+            }
+            Err(io::const_io_error!(io::ErrorKind::Other, &"recv_slice failure"))
+        }
+    }
+
+    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.read_or_peek(buf, ReadOrPeek::Peek)
+    }
+
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.read_or_peek(buf, ReadOrPeek::Read)
+    }
+
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        crate::io::default_read_vectored(|b| self.read(b), bufs)
+    }
+
+    pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        crate::io::default_read_buf(|buf| self.read(buf), cursor)
+    }
+
+    pub fn is_read_vectored(&self) -> bool {
+        false
+    }
+
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        let mut send_request = SendData { raw: [0u8; 4096] };
+        for (dest, src) in send_request.raw.iter_mut().zip(buf) {
+            *dest = *src;
+        }
+        let buf_len = send_request.raw.len().min(buf.len());
+
+        let (_offset, _valid) = crate::os::xous::ffi::lend_mut(
+            services::net_server(),
+            services::NetLendMut::StdTcpTx(self.fd).into(),
+            &mut send_request.raw,
+            // Reuse the offset as the timeout
+            self.write_timeout.load(Ordering::Relaxed) as usize,
+            buf_len,
+        )
+        .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Internal error")))?;
+
+        if send_request.raw[0] != 0 {
+            if send_request.raw[4] == 8 {
+                // timed out
+                return Err(io::const_io_error!(
+                    io::ErrorKind::BrokenPipe,
+                    &"Timeout or connection closed",
+                ));
+            } else if send_request.raw[4] == 9 {
+                // would block
+                return Err(io::const_io_error!(io::ErrorKind::WouldBlock, &"Would block",));
+            } else {
+                return Err(io::const_io_error!(
+                    io::ErrorKind::InvalidInput,
+                    &"Error when sending",
+                ));
+            }
+        }
+        Ok(u32::from_le_bytes([
+            send_request.raw[4],
+            send_request.raw[5],
+            send_request.raw[6],
+            send_request.raw[7],
+        ]) as usize)
+    }
+
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        crate::io::default_write_vectored(|b| self.write(b), bufs)
+    }
+
+    pub fn is_write_vectored(&self) -> bool {
+        false
+    }
+
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        Ok(self.peer_addr)
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        let mut get_addr = GetAddress { raw: [0u8; 4096] };
+
+        let Ok((_offset, _valid)) = crate::os::xous::ffi::lend_mut(
+            services::net_server(),
+            services::NetLendMut::StdGetAddress(self.fd).into(),
+            &mut get_addr.raw,
+            0,
+            0,
+        ) else {
+            return Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Internal error"));
+        };
+        let mut i = get_addr.raw.iter();
+        match *i.next().unwrap() {
+            4 => Ok(SocketAddr::V4(SocketAddrV4::new(
+                Ipv4Addr::new(
+                    *i.next().unwrap(),
+                    *i.next().unwrap(),
+                    *i.next().unwrap(),
+                    *i.next().unwrap(),
+                ),
+                self.local_port,
+            ))),
+            6 => {
+                let mut new_addr = [0u8; 16];
+                for (src, octet) in i.zip(new_addr.iter_mut()) {
+                    *octet = *src;
+                }
+                Ok(SocketAddr::V6(SocketAddrV6::new(new_addr.into(), self.local_port, 0, 0)))
+            }
+            _ => Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Internal error")),
+        }
+    }
+
+    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
+        crate::os::xous::ffi::blocking_scalar(
+            services::net_server(),
+            services::NetBlockingScalar::StdTcpStreamShutdown(self.fd, how).into(),
+        )
+        .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value")))
+        .map(|_| ())
+    }
+
+    pub fn duplicate(&self) -> io::Result<TcpStream> {
+        self.handle_count.fetch_add(1, Ordering::Relaxed);
+        Ok(self.clone())
+    }
+
+    pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
+        unimpl!();
+    }
+
+    pub fn linger(&self) -> io::Result<Option<Duration>> {
+        unimpl!();
+    }
+
+    pub fn set_nodelay(&self, enabled: bool) -> io::Result<()> {
+        crate::os::xous::ffi::blocking_scalar(
+            services::net_server(),
+            services::NetBlockingScalar::StdSetNodelay(self.fd, enabled).into(),
+        )
+        .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value")))
+        .map(|_| ())
+    }
+
+    pub fn nodelay(&self) -> io::Result<bool> {
+        Ok(crate::os::xous::ffi::blocking_scalar(
+            services::net_server(),
+            services::NetBlockingScalar::StdGetNodelay(self.fd).into(),
+        )
+        .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value")))
+        .map(|res| res[0] != 0)?)
+    }
+
+    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+        if ttl > 255 {
+            return Err(io::Error::new(io::ErrorKind::InvalidInput, "TTL must be less than 256"));
+        }
+        crate::os::xous::ffi::blocking_scalar(
+            services::net_server(),
+            services::NetBlockingScalar::StdSetTtlTcp(self.fd, ttl).into(),
+        )
+        .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value")))
+        .map(|_| ())
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        Ok(crate::os::xous::ffi::blocking_scalar(
+            services::net_server(),
+            services::NetBlockingScalar::StdGetTtlTcp(self.fd).into(),
+        )
+        .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value")))
+        .map(|res| res[0] as _)?)
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        // this call doesn't have a meaning on our platform, but we can at least not panic if it's used.
+        Ok(None)
+    }
+
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        self.nonblocking.store(nonblocking, Ordering::SeqCst);
+        Ok(())
+    }
+}
+
+impl fmt::Debug for TcpStream {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "TCP connection to {:?} port {} to local port {}",
+            self.peer_addr, self.remote_port, self.local_port
+        )
+    }
+}
+
+impl Drop for TcpStream {
+    fn drop(&mut self) {
+        if self.handle_count.fetch_sub(1, Ordering::Relaxed) == 1 {
+            // only drop if we're the last clone
+            crate::os::xous::ffi::blocking_scalar(
+                services::net_server(),
+                services::NetBlockingScalar::StdTcpClose(self.fd).into(),
+            )
+            .unwrap();
+        }
+    }
+}
diff --git a/library/std/src/sys/pal/xous/net/udp.rs b/library/std/src/sys/pal/xous/net/udp.rs
new file mode 100644
index 0000000000000..cafa5b3bde829
--- /dev/null
+++ b/library/std/src/sys/pal/xous/net/udp.rs
@@ -0,0 +1,471 @@
+use super::*;
+use crate::cell::Cell;
+use crate::fmt;
+use crate::io;
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
+use crate::os::xous::services;
+use crate::sync::Arc;
+use crate::time::Duration;
+use core::convert::TryInto;
+use core::sync::atomic::{AtomicUsize, Ordering};
+
+macro_rules! unimpl {
+    () => {
+        return Err(io::const_io_error!(
+            io::ErrorKind::Unsupported,
+            &"This function is not yet implemented",
+        ));
+    };
+}
+
+#[derive(Clone)]
+pub struct UdpSocket {
+    fd: u16,
+    local: SocketAddr,
+    remote: Cell<Option<SocketAddr>>,
+    // in milliseconds. The setting applies only to `recv` calls after the timeout is set.
+    read_timeout: Cell<u64>,
+    // in milliseconds. The setting applies only to `send` calls after the timeout is set.
+    write_timeout: Cell<u64>,
+    handle_count: Arc<AtomicUsize>,
+    nonblocking: Cell<bool>,
+}
+
+impl UdpSocket {
+    pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
+        let addr = socketaddr?;
+        // Construct the request
+        let mut connect_request = ConnectRequest { raw: [0u8; 4096] };
+
+        // Serialize the StdUdpBind structure. This is done "manually" because we don't want to
+        // make an auto-serdes (like bincode or rkyv) crate a dependency of Xous.
+        let port_bytes = addr.port().to_le_bytes();
+        connect_request.raw[0] = port_bytes[0];
+        connect_request.raw[1] = port_bytes[1];
+        match addr.ip() {
+            IpAddr::V4(addr) => {
+                connect_request.raw[2] = 4;
+                for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
+                    *dest = src;
+                }
+            }
+            IpAddr::V6(addr) => {
+                connect_request.raw[2] = 6;
+                for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
+                    *dest = src;
+                }
+            }
+        }
+
+        let response = crate::os::xous::ffi::lend_mut(
+            services::net_server(),
+            services::NetLendMut::StdUdpBind.into(),
+            &mut connect_request.raw,
+            0,
+            4096,
+        );
+
+        if let Ok((_, valid)) = response {
+            // The first four bytes should be zero upon success, and will be nonzero
+            // for an error.
+            let response = connect_request.raw;
+            if response[0] != 0 || valid == 0 {
+                let errcode = response[1];
+                if errcode == NetError::SocketInUse as u8 {
+                    return Err(io::const_io_error!(io::ErrorKind::ResourceBusy, &"Socket in use"));
+                } else if errcode == NetError::Invalid as u8 {
+                    return Err(io::const_io_error!(
+                        io::ErrorKind::InvalidInput,
+                        &"Port can't be 0 or invalid address"
+                    ));
+                } else if errcode == NetError::LibraryError as u8 {
+                    return Err(io::const_io_error!(io::ErrorKind::Other, &"Library error"));
+                } else {
+                    return Err(io::const_io_error!(
+                        io::ErrorKind::Other,
+                        &"Unable to connect or internal error"
+                    ));
+                }
+            }
+            let fd = response[1] as u16;
+            return Ok(UdpSocket {
+                fd,
+                local: *addr,
+                remote: Cell::new(None),
+                read_timeout: Cell::new(0),
+                write_timeout: Cell::new(0),
+                handle_count: Arc::new(AtomicUsize::new(1)),
+                nonblocking: Cell::new(false),
+            });
+        }
+        Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Invalid response"))
+    }
+
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        match self.remote.get() {
+            Some(dest) => Ok(dest),
+            None => Err(io::const_io_error!(io::ErrorKind::NotConnected, &"No peer specified")),
+        }
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        Ok(self.local)
+    }
+
+    fn recv_inner(&self, buf: &mut [u8], do_peek: bool) -> io::Result<(usize, SocketAddr)> {
+        let mut receive_request = ReceiveData { raw: [0u8; 4096] };
+
+        if self.nonblocking.get() {
+            // nonblocking
+            receive_request.raw[0] = 0;
+        } else {
+            // blocking
+            receive_request.raw[0] = 1;
+            for (&s, d) in self
+                .read_timeout
+                .get()
+                .to_le_bytes()
+                .iter()
+                .zip(receive_request.raw[1..9].iter_mut())
+            {
+                *d = s;
+            }
+        }
+        if let Ok((_offset, _valid)) = crate::os::xous::ffi::lend_mut(
+            services::net_server(),
+            services::NetLendMut::StdUdpRx(self.fd).into(),
+            &mut receive_request.raw,
+            if do_peek { 1 } else { 0 },
+            0,
+        ) {
+            if receive_request.raw[0] != 0 {
+                // error case
+                if receive_request.raw[1] == NetError::TimedOut as u8 {
+                    return Err(io::const_io_error!(io::ErrorKind::TimedOut, &"recv timed out",));
+                } else if receive_request.raw[1] == NetError::WouldBlock as u8 {
+                    return Err(io::const_io_error!(
+                        io::ErrorKind::WouldBlock,
+                        &"recv would block",
+                    ));
+                } else if receive_request.raw[1] == NetError::LibraryError as u8 {
+                    return Err(io::const_io_error!(io::ErrorKind::Other, &"Library error"));
+                } else {
+                    return Err(io::const_io_error!(io::ErrorKind::Other, &"library error",));
+                }
+            } else {
+                let rr = &receive_request.raw;
+                let rxlen = u16::from_le_bytes(rr[1..3].try_into().unwrap());
+                let port = u16::from_le_bytes(rr[20..22].try_into().unwrap());
+                let addr = if rr[3] == 4 {
+                    SocketAddr::new(IpAddr::V4(Ipv4Addr::new(rr[4], rr[5], rr[6], rr[7])), port)
+                } else if rr[3] == 6 {
+                    SocketAddr::new(
+                        IpAddr::V6(Ipv6Addr::new(
+                            u16::from_be_bytes(rr[4..6].try_into().unwrap()),
+                            u16::from_be_bytes(rr[6..8].try_into().unwrap()),
+                            u16::from_be_bytes(rr[8..10].try_into().unwrap()),
+                            u16::from_be_bytes(rr[10..12].try_into().unwrap()),
+                            u16::from_be_bytes(rr[12..14].try_into().unwrap()),
+                            u16::from_be_bytes(rr[14..16].try_into().unwrap()),
+                            u16::from_be_bytes(rr[16..18].try_into().unwrap()),
+                            u16::from_be_bytes(rr[18..20].try_into().unwrap()),
+                        )),
+                        port,
+                    )
+                } else {
+                    return Err(io::const_io_error!(io::ErrorKind::Other, &"library error",));
+                };
+                for (&s, d) in rr[22..22 + rxlen as usize].iter().zip(buf.iter_mut()) {
+                    *d = s;
+                }
+                Ok((rxlen as usize, addr))
+            }
+        } else {
+            Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unable to recv"))
+        }
+    }
+
+    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.recv_inner(buf, false)
+    }
+
+    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.recv_from(buf).map(|(len, _addr)| len)
+    }
+
+    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.recv_inner(buf, true)
+    }
+
+    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.peek_from(buf).map(|(len, _addr)| len)
+    }
+
+    pub fn connect(&self, maybe_addr: io::Result<&SocketAddr>) -> io::Result<()> {
+        let addr = maybe_addr?;
+        self.remote.set(Some(*addr));
+        Ok(())
+    }
+
+    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
+        if let Some(addr) = self.remote.get() {
+            self.send_to(buf, &addr)
+        } else {
+            Err(io::const_io_error!(io::ErrorKind::NotConnected, &"No remote specified"))
+        }
+    }
+
+    pub fn send_to(&self, buf: &[u8], addr: &SocketAddr) -> io::Result<usize> {
+        let mut tx_req = SendData { raw: [0u8; 4096] };
+
+        // Construct the request.
+        let port_bytes = addr.port().to_le_bytes();
+        tx_req.raw[0] = port_bytes[0];
+        tx_req.raw[1] = port_bytes[1];
+        match addr.ip() {
+            IpAddr::V4(addr) => {
+                tx_req.raw[2] = 4;
+                for (dest, src) in tx_req.raw[3..].iter_mut().zip(addr.octets()) {
+                    *dest = src;
+                }
+            }
+            IpAddr::V6(addr) => {
+                tx_req.raw[2] = 6;
+                for (dest, src) in tx_req.raw[3..].iter_mut().zip(addr.octets()) {
+                    *dest = src;
+                }
+            }
+        }
+        let len = buf.len() as u16;
+        let len_bytes = len.to_le_bytes();
+        tx_req.raw[19] = len_bytes[0];
+        tx_req.raw[20] = len_bytes[1];
+        for (&s, d) in buf.iter().zip(tx_req.raw[21..].iter_mut()) {
+            *d = s;
+        }
+
+        // let buf = unsafe {
+        //     xous::MemoryRange::new(
+        //         &mut tx_req as *mut SendData as usize,
+        //         core::mem::size_of::<SendData>(),
+        //     )
+        //     .unwrap()
+        // };
+
+        // write time-outs are implemented on the caller side. Basically, if the Net crate server
+        // is too busy to take the call immediately: retry, until the timeout is reached.
+        let now = crate::time::Instant::now();
+        let write_timeout = if self.nonblocking.get() {
+            // nonblocking
+            core::time::Duration::ZERO
+        } else {
+            // blocking
+            if self.write_timeout.get() == 0 {
+                // forever
+                core::time::Duration::from_millis(u64::MAX)
+            } else {
+                // or this amount of time
+                core::time::Duration::from_millis(self.write_timeout.get())
+            }
+        };
+        loop {
+            let response = crate::os::xous::ffi::try_lend_mut(
+                services::net_server(),
+                services::NetLendMut::StdUdpTx(self.fd).into(),
+                &mut tx_req.raw,
+                0,
+                4096,
+            );
+            match response {
+                Ok((_, valid)) => {
+                    let response = &tx_req.raw;
+                    if response[0] != 0 || valid == 0 {
+                        let errcode = response[1];
+                        if errcode == NetError::SocketInUse as u8 {
+                            return Err(io::const_io_error!(
+                                io::ErrorKind::ResourceBusy,
+                                &"Socket in use"
+                            ));
+                        } else if errcode == NetError::Invalid as u8 {
+                            return Err(io::const_io_error!(
+                                io::ErrorKind::InvalidInput,
+                                &"Socket not valid"
+                            ));
+                        } else if errcode == NetError::LibraryError as u8 {
+                            return Err(io::const_io_error!(
+                                io::ErrorKind::Other,
+                                &"Library error"
+                            ));
+                        } else {
+                            return Err(io::const_io_error!(
+                                io::ErrorKind::Other,
+                                &"Unable to connect"
+                            ));
+                        }
+                    } else {
+                        // no error
+                        return Ok(len as usize);
+                    }
+                }
+                Err(crate::os::xous::ffi::Error::ServerQueueFull) => {
+                    if now.elapsed() >= write_timeout {
+                        return Err(io::const_io_error!(
+                            io::ErrorKind::WouldBlock,
+                            &"Write timed out"
+                        ));
+                    } else {
+                        // question: do we want to do something a bit more gentle than immediately retrying?
+                        crate::thread::yield_now();
+                    }
+                }
+                _ => return Err(io::const_io_error!(io::ErrorKind::Other, &"Library error")),
+            }
+        }
+    }
+
+    pub fn duplicate(&self) -> io::Result<UdpSocket> {
+        self.handle_count.fetch_add(1, Ordering::Relaxed);
+        Ok(self.clone())
+    }
+
+    pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        if let Some(d) = timeout {
+            if d.is_zero() {
+                return Err(io::const_io_error!(
+                    io::ErrorKind::InvalidInput,
+                    &"Zero duration is invalid"
+                ));
+            }
+        }
+        self.read_timeout
+            .set(timeout.map(|t| t.as_millis().min(u64::MAX as u128) as u64).unwrap_or_default());
+        Ok(())
+    }
+
+    pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        if let Some(d) = timeout {
+            if d.is_zero() {
+                return Err(io::const_io_error!(
+                    io::ErrorKind::InvalidInput,
+                    &"Zero duration is invalid"
+                ));
+            }
+        }
+        self.write_timeout
+            .set(timeout.map(|t| t.as_millis().min(u64::MAX as u128) as u64).unwrap_or_default());
+        Ok(())
+    }
+
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.read_timeout.get() {
+            0 => Ok(None),
+            t => Ok(Some(Duration::from_millis(t as u64))),
+        }
+    }
+
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.write_timeout.get() {
+            0 => Ok(None),
+            t => Ok(Some(Duration::from_millis(t as u64))),
+        }
+    }
+
+    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+        if ttl > 255 {
+            return Err(io::Error::new(io::ErrorKind::InvalidInput, "TTL must be less than 256"));
+        }
+        crate::os::xous::ffi::blocking_scalar(
+            services::net_server(),
+            services::NetBlockingScalar::StdSetTtlUdp(self.fd, ttl).into(),
+        )
+        .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value")))
+        .map(|_| ())
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        Ok(crate::os::xous::ffi::blocking_scalar(
+            services::net_server(),
+            services::NetBlockingScalar::StdGetTtlUdp(self.fd).into(),
+        )
+        .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value")))
+        .map(|res| res[0] as _)?)
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        // this call doesn't have a meaning on our platform, but we can at least not panic if it's used.
+        Ok(None)
+    }
+
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        self.nonblocking.set(nonblocking);
+        Ok(())
+    }
+
+    // ------------- smoltcp base stack does not have multicast or broadcast support ---------------
+    pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
+        unimpl!();
+    }
+
+    pub fn broadcast(&self) -> io::Result<bool> {
+        unimpl!();
+    }
+
+    pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
+        unimpl!();
+    }
+
+    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
+        unimpl!();
+    }
+
+    pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
+        unimpl!();
+    }
+
+    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
+        unimpl!();
+    }
+
+    pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
+        unimpl!();
+    }
+
+    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
+        unimpl!();
+    }
+
+    pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
+        unimpl!();
+    }
+
+    pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
+        unimpl!();
+    }
+
+    pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
+        unimpl!();
+    }
+
+    pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
+        unimpl!();
+    }
+}
+
+impl fmt::Debug for UdpSocket {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "UDP listening on {:?} to {:?}", self.local, self.remote.get(),)
+    }
+}
+
+impl Drop for UdpSocket {
+    fn drop(&mut self) {
+        if self.handle_count.fetch_sub(1, Ordering::Relaxed) == 1 {
+            // only drop if we're the last clone
+            crate::os::xous::ffi::blocking_scalar(
+                services::net_server(),
+                services::NetBlockingScalar::StdUdpClose(self.fd).into(),
+            )
+            .unwrap();
+        }
+    }
+}
diff --git a/library/std/src/sys/pal/xous/stdio.rs b/library/std/src/sys/pal/xous/stdio.rs
index 2ac694641ba94..11608964b52e6 100644
--- a/library/std/src/sys/pal/xous/stdio.rs
+++ b/library/std/src/sys/pal/xous/stdio.rs
@@ -5,7 +5,7 @@ pub struct Stdout {}
 pub struct Stderr;
 
 use crate::os::xous::ffi::{lend, try_lend, try_scalar, Connection};
-use crate::os::xous::services::{log_server, try_connect, LogScalar};
+use crate::os::xous::services::{log_server, try_connect, LogLend, LogScalar};
 
 impl Stdin {
     pub const fn new() -> Stdin {
@@ -27,7 +27,7 @@ impl Stdout {
 
 impl io::Write for Stdout {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        #[repr(align(4096))]
+        #[repr(C, align(4096))]
         struct LendBuffer([u8; 4096]);
         let mut lend_buffer = LendBuffer([0u8; 4096]);
         let connection = log_server();
@@ -35,7 +35,8 @@ impl io::Write for Stdout {
             for (dest, src) in lend_buffer.0.iter_mut().zip(chunk) {
                 *dest = *src;
             }
-            lend(connection, 1, &lend_buffer.0, 0, chunk.len()).unwrap();
+            lend(connection, LogLend::StandardOutput.into(), &lend_buffer.0, 0, chunk.len())
+                .unwrap();
         }
         Ok(buf.len())
     }
@@ -53,7 +54,7 @@ impl Stderr {
 
 impl io::Write for Stderr {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        #[repr(align(4096))]
+        #[repr(C, align(4096))]
         struct LendBuffer([u8; 4096]);
         let mut lend_buffer = LendBuffer([0u8; 4096]);
         let connection = log_server();
@@ -61,7 +62,8 @@ impl io::Write for Stderr {
             for (dest, src) in lend_buffer.0.iter_mut().zip(chunk) {
                 *dest = *src;
             }
-            lend(connection, 1, &lend_buffer.0, 0, chunk.len()).unwrap();
+            lend(connection, LogLend::StandardError.into(), &lend_buffer.0, 0, chunk.len())
+                .unwrap();
         }
         Ok(buf.len())
     }
diff --git a/library/std/src/sys/pal/xous/thread.rs b/library/std/src/sys/pal/xous/thread.rs
index 78c68de7bf38d..0f452e07a5c58 100644
--- a/library/std/src/sys/pal/xous/thread.rs
+++ b/library/std/src/sys/pal/xous/thread.rs
@@ -68,14 +68,18 @@ impl Thread {
         )
         .map_err(|code| io::Error::from_raw_os_error(code as i32))?;
 
-        extern "C" fn thread_start(main: *mut usize, guard_page_pre: usize, stack_size: usize) {
+        extern "C" fn thread_start(
+            main: *mut usize,
+            guard_page_pre: usize,
+            stack_size: usize,
+        ) -> ! {
             unsafe {
-                // Finally, let's run some code.
+                // Run the contents of the new thread.
                 Box::from_raw(main as *mut Box<dyn FnOnce()>)();
             }
 
             // Destroy TLS, which will free the TLS page and call the destructor for
-            // any thread local storage.
+            // any thread local storage (if any).
             unsafe {
                 crate::sys::thread_local_key::destroy_tls();
             }
diff --git a/library/std/src/sys/pal/xous/thread_local_key.rs b/library/std/src/sys/pal/xous/thread_local_key.rs
index 3771ea6570084..59a668c3df6ff 100644
--- a/library/std/src/sys/pal/xous/thread_local_key.rs
+++ b/library/std/src/sys/pal/xous/thread_local_key.rs
@@ -23,10 +23,25 @@ pub type Dtor = unsafe extern "C" fn(*mut u8);
 
 const TLS_MEMORY_SIZE: usize = 4096;
 
-/// TLS keys start at `1` to mimic POSIX.
+/// TLS keys start at `1`. Index `0` is unused
+#[cfg(not(test))]
+#[export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key13TLS_KEY_INDEXE"]
 static TLS_KEY_INDEX: AtomicUsize = AtomicUsize::new(1);
 
-fn tls_ptr_addr() -> *mut usize {
+#[cfg(not(test))]
+#[export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key9DTORSE"]
+static DTORS: AtomicPtr<Node> = AtomicPtr::new(ptr::null_mut());
+
+#[cfg(test)]
+extern "Rust" {
+    #[link_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key13TLS_KEY_INDEXE"]
+    static TLS_KEY_INDEX: AtomicUsize;
+
+    #[link_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key9DTORSE"]
+    static DTORS: AtomicPtr<Node>;
+}
+
+fn tls_ptr_addr() -> *mut *mut u8 {
     let mut tp: usize;
     unsafe {
         asm!(
@@ -34,50 +49,50 @@ fn tls_ptr_addr() -> *mut usize {
             out(reg) tp,
         );
     }
-    core::ptr::from_exposed_addr_mut::<usize>(tp)
+    core::ptr::from_exposed_addr_mut::<*mut u8>(tp)
 }
 
 /// Create an area of memory that's unique per thread. This area will
 /// contain all thread local pointers.
-fn tls_ptr() -> *mut usize {
-    let mut tp = tls_ptr_addr();
+fn tls_table() -> &'static mut [*mut u8] {
+    let tp = tls_ptr_addr();
 
+    if !tp.is_null() {
+        return unsafe {
+            core::slice::from_raw_parts_mut(tp, TLS_MEMORY_SIZE / core::mem::size_of::<*mut u8>())
+        };
+    }
     // If the TP register is `0`, then this thread hasn't initialized
     // its TLS yet. Allocate a new page to store this memory.
-    if tp.is_null() {
-        tp = unsafe {
-            map_memory(
-                None,
-                None,
-                TLS_MEMORY_SIZE / core::mem::size_of::<usize>(),
-                MemoryFlags::R | MemoryFlags::W,
-            )
-        }
+    let tp = unsafe {
+        map_memory(
+            None,
+            None,
+            TLS_MEMORY_SIZE / core::mem::size_of::<*mut u8>(),
+            MemoryFlags::R | MemoryFlags::W,
+        )
         .expect("Unable to allocate memory for thread local storage")
-        .as_mut_ptr();
+    };
 
-        unsafe {
-            // Key #0 is currently unused.
-            (tp).write_volatile(0);
+    for val in tp.iter() {
+        assert!(*val as usize == 0);
+    }
 
-            // Set the thread's `$tp` register
-            asm!(
-                "mv tp, {}",
-                in(reg) tp as usize,
-            );
-        }
+    unsafe {
+        // Set the thread's `$tp` register
+        asm!(
+            "mv tp, {}",
+            in(reg) tp.as_mut_ptr() as usize,
+        );
     }
     tp
 }
 
-/// Allocate a new TLS key. These keys are shared among all threads.
-fn tls_alloc() -> usize {
-    TLS_KEY_INDEX.fetch_add(1, SeqCst)
-}
-
 #[inline]
 pub unsafe fn create(dtor: Option<Dtor>) -> Key {
-    let key = tls_alloc();
+    // Allocate a new TLS key. These keys are shared among all threads.
+    #[allow(unused_unsafe)]
+    let key = unsafe { TLS_KEY_INDEX.fetch_add(1, SeqCst) };
     if let Some(f) = dtor {
         unsafe { register_dtor(key, f) };
     }
@@ -87,18 +102,20 @@ pub unsafe fn create(dtor: Option<Dtor>) -> Key {
 #[inline]
 pub unsafe fn set(key: Key, value: *mut u8) {
     assert!((key < 1022) && (key >= 1));
-    unsafe { tls_ptr().add(key).write_volatile(value as usize) };
+    let table = tls_table();
+    table[key] = value;
 }
 
 #[inline]
 pub unsafe fn get(key: Key) -> *mut u8 {
     assert!((key < 1022) && (key >= 1));
-    core::ptr::from_exposed_addr_mut::<u8>(unsafe { tls_ptr().add(key).read_volatile() })
+    tls_table()[key]
 }
 
 #[inline]
 pub unsafe fn destroy(_key: Key) {
-    panic!("can't destroy keys on Xous");
+    // Just leak the key. Probably not great on long-running systems that create
+    // lots of TLS variables, but in practice that's not an issue.
 }
 
 // -------------------------------------------------------------------------
@@ -127,8 +144,6 @@ pub unsafe fn destroy(_key: Key) {
 // key but also a slot for the destructor queue on windows. An optimization for
 // another day!
 
-static DTORS: AtomicPtr<Node> = AtomicPtr::new(ptr::null_mut());
-
 struct Node {
     dtor: Dtor,
     key: Key,
@@ -138,10 +153,12 @@ struct Node {
 unsafe fn register_dtor(key: Key, dtor: Dtor) {
     let mut node = ManuallyDrop::new(Box::new(Node { key, dtor, next: ptr::null_mut() }));
 
-    let mut head = DTORS.load(SeqCst);
+    #[allow(unused_unsafe)]
+    let mut head = unsafe { DTORS.load(SeqCst) };
     loop {
         node.next = head;
-        match DTORS.compare_exchange(head, &mut **node, SeqCst, SeqCst) {
+        #[allow(unused_unsafe)]
+        match unsafe { DTORS.compare_exchange(head, &mut **node, SeqCst, SeqCst) } {
             Ok(_) => return, // nothing to drop, we successfully added the node to the list
             Err(cur) => head = cur,
         }
@@ -155,6 +172,7 @@ pub unsafe fn destroy_tls() {
     if tp.is_null() {
         return;
     }
+
     unsafe { run_dtors() };
 
     // Finally, free the TLS array
@@ -169,12 +187,19 @@ pub unsafe fn destroy_tls() {
 
 unsafe fn run_dtors() {
     let mut any_run = true;
+
+    // Run the destructor "some" number of times. This is 5x on Windows,
+    // so we copy it here. This allows TLS variables to create new
+    // TLS variables upon destruction that will also get destroyed.
+    // Keep going until we run out of tries or until we have nothing
+    // left to destroy.
     for _ in 0..5 {
         if !any_run {
             break;
         }
         any_run = false;
-        let mut cur = DTORS.load(SeqCst);
+        #[allow(unused_unsafe)]
+        let mut cur = unsafe { DTORS.load(SeqCst) };
         while !cur.is_null() {
             let ptr = unsafe { get((*cur).key) };
 
diff --git a/library/std/src/sys/pal/xous/thread_parking.rs b/library/std/src/sys/pal/xous/thread_parking.rs
index aa39c6d27185f..0bd0462d77d35 100644
--- a/library/std/src/sys/pal/xous/thread_parking.rs
+++ b/library/std/src/sys/pal/xous/thread_parking.rs
@@ -29,31 +29,40 @@ impl Parker {
         // Change NOTIFIED to EMPTY and EMPTY to PARKED.
         let state = self.state.fetch_sub(1, Acquire);
         if state == NOTIFIED {
+            // The state has gone from NOTIFIED (1) to EMPTY (0)
             return;
         }
+        // The state has gone from EMPTY (0) to PARKED (-1)
+        assert!(state == EMPTY);
 
-        // The state was set to PARKED. Wait until the `unpark` wakes us up.
+        // The state is now PARKED (-1). Wait until the `unpark` wakes us up.
         blocking_scalar(
             ticktimer_server(),
             TicktimerScalar::WaitForCondition(self.index(), 0).into(),
         )
         .expect("failed to send WaitForCondition command");
 
-        self.state.swap(EMPTY, Acquire);
+        let state = self.state.swap(EMPTY, Acquire);
+        assert!(state == NOTIFIED || state == PARKED);
     }
 
     pub unsafe fn park_timeout(self: Pin<&Self>, timeout: Duration) {
         // Change NOTIFIED to EMPTY and EMPTY to PARKED.
         let state = self.state.fetch_sub(1, Acquire);
         if state == NOTIFIED {
+            // The state has gone from NOTIFIED (1) to EMPTY (0)
             return;
         }
+        // The state has gone from EMPTY (0) to PARKED (-1)
+        assert!(state == EMPTY);
 
         // A value of zero indicates an indefinite wait. Clamp the number of
         // milliseconds to the allowed range.
         let millis = usize::max(timeout.as_millis().try_into().unwrap_or(usize::MAX), 1);
 
-        let was_timeout = blocking_scalar(
+        // The state is now PARKED (-1). Wait until the `unpark` wakes us up,
+        // or things time out.
+        let _was_timeout = blocking_scalar(
             ticktimer_server(),
             TicktimerScalar::WaitForCondition(self.index(), millis).into(),
         )
@@ -61,28 +70,37 @@ impl Parker {
             != 0;
 
         let state = self.state.swap(EMPTY, Acquire);
-        if was_timeout && state == NOTIFIED {
-            // The state was set to NOTIFIED after we returned from the wait
-            // but before we reset the state. Therefore, a wakeup is on its
-            // way, which we need to consume here.
-            // NOTICE: this is a priority hole.
-            blocking_scalar(
-                ticktimer_server(),
-                TicktimerScalar::WaitForCondition(self.index(), 0).into(),
-            )
-            .expect("failed to send WaitForCondition command");
-        }
+        assert!(state == PARKED || state == NOTIFIED);
     }
 
     pub fn unpark(self: Pin<&Self>) {
-        let state = self.state.swap(NOTIFIED, Release);
-        if state == PARKED {
-            // The thread is parked, wake it up.
-            blocking_scalar(
-                ticktimer_server(),
-                TicktimerScalar::NotifyCondition(self.index(), 1).into(),
-            )
-            .expect("failed to send NotifyCondition command");
+        // If the state is already `NOTIFIED`, then another thread has
+        // indicated it wants to wake up the target thread.
+        //
+        // If the state is `EMPTY` then there is nothing to wake up, and
+        // the target thread will immediately exit from `park()` the
+        // next time that function is called.
+        if self.state.swap(NOTIFIED, Release) != PARKED {
+            return;
+        }
+
+        // The thread is parked, wake it up. Keep trying until we wake something up.
+        // This will happen when the `NotifyCondition` call returns the fact that
+        // 1 condition was notified.
+        // Alternately, keep going until the state is seen as `EMPTY`, indicating
+        // the thread woke up and kept going. This can happen when the Park
+        // times out before we can send the NotifyCondition message.
+        while blocking_scalar(
+            ticktimer_server(),
+            TicktimerScalar::NotifyCondition(self.index(), 1).into(),
+        )
+        .expect("failed to send NotifyCondition command")[0]
+            == 0
+            && self.state.load(Acquire) != EMPTY
+        {
+            // The target thread hasn't yet hit the `WaitForCondition` call.
+            // Yield to let the target thread run some more.
+            crate::thread::yield_now();
         }
     }
 }
diff --git a/library/std/src/sys_common/once/mod.rs b/library/std/src/sys_common/once/mod.rs
index 359697d831317..ec57568c54c4f 100644
--- a/library/std/src/sys_common/once/mod.rs
+++ b/library/std/src/sys_common/once/mod.rs
@@ -25,6 +25,7 @@ cfg_if::cfg_if! {
         target_family = "unix",
         all(target_vendor = "fortanix", target_env = "sgx"),
         target_os = "solid_asp3",
+        target_os = "xous",
     ))] {
         mod queue;
         pub use queue::{Once, OnceState};
diff --git a/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md b/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md
index 13349ff6b8f41..424f1128e3b5c 100644
--- a/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md
+++ b/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md
@@ -20,5 +20,5 @@ This flag accepts a comma-separated list of values and may be specified multiple
 ```sh
 # This would produce an absolute path to main.rs in build outputs of
 # "./main.rs".
-rustc --remap-path-prefix=$(PWD)=/remapped -Zremap-path-prefix=object main.rs
+rustc --remap-path-prefix=$(PWD)=/remapped -Zremap-path-scope=object main.rs
 ```
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 124a2d9cba957..f69f8dfff2f9b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -15,6 +15,7 @@ use rustc_ast::token::{Token, TokenKind};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry};
+use rustc_errors::{codes::*, struct_span_code_err, FatalError};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
@@ -2271,7 +2272,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
         ty::Placeholder(..) => panic!("Placeholder"),
         ty::CoroutineWitness(..) => panic!("CoroutineWitness"),
         ty::Infer(..) => panic!("Infer"),
-        ty::Error(_) => rustc_errors::FatalError.raise(),
+        ty::Error(_) => FatalError.raise(),
     }
 }
 
@@ -2995,7 +2996,7 @@ fn clean_use_statement_inner<'tcx>(
         visibility.is_accessible_from(parent_mod, cx.tcx) && !current_mod.is_top_level_module();
 
     if pub_underscore && let Some(ref inline) = inline_attr {
-        rustc_errors::struct_span_code_err!(
+        struct_span_code_err!(
             cx.tcx.dcx(),
             inline.span(),
             E0780,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 8bb1ed6d476d4..867b8e71474c7 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::emitter::{DynEmitter, HumanEmitter};
 use rustc_errors::json::JsonEmitter;
-use rustc_errors::TerminalUrl;
+use rustc_errors::{codes::*, TerminalUrl};
 use rustc_feature::UnstableFeatures;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml
index 76c2e330b2100..f4dac6e947e32 100644
--- a/src/tools/error_index_generator/Cargo.toml
+++ b/src/tools/error_index_generator/Cargo.toml
@@ -5,7 +5,6 @@ edition = "2021"
 
 [dependencies]
 mdbook = { version = "0.4", default-features = false, features = ["search"] }
-rustc_error_codes = { version = "0.0.0", path = "../../../compiler/rustc_error_codes" }
 
 [[bin]]
 name = "error_index_generator"
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs
index 865d7172cd3e6..2de2d959a95d7 100644
--- a/src/tools/error_index_generator/main.rs
+++ b/src/tools/error_index_generator/main.rs
@@ -4,13 +4,15 @@ extern crate rustc_driver;
 extern crate rustc_log;
 extern crate rustc_session;
 
+extern crate rustc_errors;
+use rustc_errors::codes::DIAGNOSTICS;
+
 use std::env;
 use std::error::Error;
 use std::fs::{self, File};
 use std::io::Write;
 use std::path::Path;
 use std::path::PathBuf;
-
 use std::str::FromStr;
 
 use mdbook::book::{parse_summary, BookItem, Chapter};
@@ -38,7 +40,7 @@ fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
 
     write!(output_file, "# Rust Compiler Error Index\n")?;
 
-    for (err_code, description) in rustc_error_codes::DIAGNOSTICS.iter() {
+    for (err_code, description) in DIAGNOSTICS.iter() {
         write!(output_file, "## {}\n{}\n", err_code, description)?
     }
 
@@ -85,7 +87,7 @@ This page lists all the error codes emitted by the Rust compiler.
 "
     );
 
-    let err_codes = rustc_error_codes::DIAGNOSTICS;
+    let err_codes = DIAGNOSTICS;
     let mut chapters = Vec::with_capacity(err_codes.len());
 
     for (err_code, explanation) in err_codes.iter() {
diff --git a/src/tools/remote-test-client/src/main.rs b/src/tools/remote-test-client/src/main.rs
index bcda930d093c5..590c735596ed9 100644
--- a/src/tools/remote-test-client/src/main.rs
+++ b/src/tools/remote-test-client/src/main.rs
@@ -300,7 +300,7 @@ fn run(support_lib_count: usize, exe: String, all_args: Vec<String>) {
 
     // Ok now it's time to read all the output. We're receiving "frames"
     // representing stdout/stderr, so we decode all that here.
-    let mut header = [0; 5];
+    let mut header = [0; 9];
     let mut stderr_done = false;
     let mut stdout_done = false;
     let mut client = t!(client.into_inner());
@@ -308,10 +308,8 @@ fn run(support_lib_count: usize, exe: String, all_args: Vec<String>) {
     let mut stderr = io::stderr();
     while !stdout_done || !stderr_done {
         t!(client.read_exact(&mut header));
-        let amt = ((header[1] as u64) << 24)
-            | ((header[2] as u64) << 16)
-            | ((header[3] as u64) << 8)
-            | ((header[4] as u64) << 0);
+        let amt = u64::from_be_bytes(header[1..9].try_into().unwrap());
+
         if header[0] == 0 {
             if amt == 0 {
                 stdout_done = true;
@@ -349,7 +347,8 @@ fn send(path: &Path, dst: &mut dyn Write) {
     t!(dst.write_all(&[0]));
     let mut file = t!(File::open(&path));
     let amt = t!(file.metadata()).len();
-    t!(dst.write_all(&[(amt >> 24) as u8, (amt >> 16) as u8, (amt >> 8) as u8, (amt >> 0) as u8,]));
+
+    t!(dst.write_all(&amt.to_be_bytes()));
     t!(io::copy(&mut file, dst));
 }
 
diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs
index 3d61a0675590c..68d7aa56c438b 100644
--- a/src/tools/remote-test-server/src/main.rs
+++ b/src/tools/remote-test-server/src/main.rs
@@ -347,7 +347,7 @@ fn recv<B: BufRead>(dir: &Path, io: &mut B) -> PathBuf {
     // the filesystem limits.
     let len = cmp::min(filename.len() - 1, 50);
     let dst = dir.join(t!(str::from_utf8(&filename[..len])));
-    let amt = read_u32(io) as u64;
+    let amt = read_u64(io);
     t!(io::copy(&mut io.take(amt), &mut t!(File::create(&dst))));
     set_permissions(&dst);
     dst
@@ -365,7 +365,7 @@ fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
     loop {
         let n = t!(src.read(&mut b));
         let mut dst = dst.lock().unwrap();
-        t!(dst.write_all(&create_header(which, n as u32)));
+        t!(dst.write_all(&create_header(which, n as u64)));
         if n > 0 {
             t!(dst.write_all(&b[..n]));
         } else {
@@ -377,7 +377,7 @@ fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
 fn batch_copy(buf: &[u8], which: u8, dst: &Mutex<dyn Write>) {
     let n = buf.len();
     let mut dst = dst.lock().unwrap();
-    t!(dst.write_all(&create_header(which, n as u32)));
+    t!(dst.write_all(&create_header(which, n as u64)));
     if n > 0 {
         t!(dst.write_all(buf));
         // Marking buf finished
@@ -385,13 +385,13 @@ fn batch_copy(buf: &[u8], which: u8, dst: &Mutex<dyn Write>) {
     }
 }
 
-const fn create_header(which: u8, n: u32) -> [u8; 5] {
+const fn create_header(which: u8, n: u64) -> [u8; 9] {
     let bytes = n.to_be_bytes();
-    [which, bytes[0], bytes[1], bytes[2], bytes[3]]
+    [which, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]]
 }
 
-fn read_u32(r: &mut dyn Read) -> u32 {
-    let mut len = [0; 4];
+fn read_u64(r: &mut dyn Read) -> u64 {
+    let mut len = [0; 8];
     t!(r.read_exact(&mut len));
-    u32::from_be_bytes(len)
+    u64::from_be_bytes(len)
 }
diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs
index 094efa981d3e3..6fc65e56901a7 100644
--- a/src/tools/tidy/src/error_codes.rs
+++ b/src/tools/tidy/src/error_codes.rs
@@ -2,7 +2,7 @@
 //!
 //! Overview of check:
 //!
-//! 1. We create a list of error codes used by the compiler. Error codes are extracted from `compiler/rustc_error_codes/src/error_codes.rs`.
+//! 1. We create a list of error codes used by the compiler. Error codes are extracted from `compiler/rustc_error_codes/src/lib.rs`.
 //!
 //! 2. We check that the error code has a long-form explanation in `compiler/rustc_error_codes/src/error_codes/`.
 //!   - The explanation is expected to contain a `doctest` that fails with the correct error code. (`EXEMPT_FROM_DOCTEST` *currently* bypasses this check)
@@ -22,7 +22,7 @@ use regex::Regex;
 
 use crate::walk::{filter_dirs, walk, walk_many};
 
-const ERROR_CODES_PATH: &str = "compiler/rustc_error_codes/src/error_codes.rs";
+const ERROR_CODES_PATH: &str = "compiler/rustc_error_codes/src/lib.rs";
 const ERROR_DOCS_PATH: &str = "compiler/rustc_error_codes/src/error_codes/";
 const ERROR_TESTS_PATH: &str = "tests/ui/error-codes/";
 
@@ -80,13 +80,14 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
         if line.starts_with('E') {
             let split_line = line.split_once(':');
 
-            // Extract the error code from the line, emitting a fatal error if it is not in a correct format.
+            // Extract the error code from the line. Emit a fatal error if it is not in the correct
+            // format.
             let err_code = if let Some(err_code) = split_line {
                 err_code.0.to_owned()
             } else {
                 errors.push(format!(
-                    "Expected a line with the format `Exxxx: include_str!(\"..\")`, but got \"{}\" \
-                    without a `:` delimiter",
+                    "Expected a line with the format `Eabcd: abcd, \
+                    but got \"{}\" without a `:` delimiter",
                     line,
                 ));
                 continue;
@@ -98,12 +99,16 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
                 continue;
             }
 
+            let mut chars = err_code.chars();
+            chars.next();
+            let error_num_as_str = chars.as_str();
+
             // Ensure that the line references the correct markdown file.
-            let expected_filename = format!(" include_str!(\"./error_codes/{}.md\"),", err_code);
+            let expected_filename = format!(" {},", error_num_as_str);
             if expected_filename != split_line.unwrap().1 {
                 errors.push(format!(
-                    "Error code `{}` expected to reference docs with `{}` but instead found `{}` in \
-                    `compiler/rustc_error_codes/src/error_codes.rs`",
+                    "`{}:` should be followed by `{}` but instead found `{}` in \
+                    `compiler/rustc_error_codes/src/lib.rs`",
                     err_code,
                     expected_filename,
                     split_line.unwrap().1,
@@ -311,13 +316,8 @@ fn check_error_codes_used(
     no_longer_emitted: &[String],
     verbose: bool,
 ) {
-    // We want error codes which match the following cases:
-    //
-    // * foo(a, E0111, a)
-    // * foo(a, E0111)
-    // * foo(E0111, a)
-    // * #[error = "E0111"]
-    let regex = Regex::new(r#"[(,"\s](E\d{4})[,)"]"#).unwrap();
+    // Search for error codes in the form `E0123`.
+    let regex = Regex::new(r#"\bE\d{4}\b"#).unwrap();
 
     let mut found_codes = Vec::new();
 
@@ -336,12 +336,12 @@ fn check_error_codes_used(
             }
 
             for cap in regex.captures_iter(line) {
-                if let Some(error_code) = cap.get(1) {
+                if let Some(error_code) = cap.get(0) {
                     let error_code = error_code.as_str().to_owned();
 
                     if !error_codes.contains(&error_code) {
                         // This error code isn't properly defined, we must error.
-                        errors.push(format!("Error code `{}` is used in the compiler but not defined and documented in `compiler/rustc_error_codes/src/error_codes.rs`.", error_code));
+                        errors.push(format!("Error code `{}` is used in the compiler but not defined and documented in `compiler/rustc_error_codes/src/lib.rs`.", error_code));
                         continue;
                     }
 
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index f553aa96505ec..d3cfd28082d61 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -25,22 +25,26 @@ extern crate rustc_middle;
 use rustc_middle::ty::Ty;
 
 extern crate rustc_errors;
-use rustc_errors::{Applicability, DiagnosticMessage, MultiSpan, SubdiagnosticMessage};
+use rustc_errors::{Applicability, DiagnosticMessage, ErrCode, MultiSpan, SubdiagnosticMessage};
 
 extern crate rustc_session;
 
 rustc_fluent_macro::fluent_messages! { "./example.ftl" }
 
+// E0123 and E0456 are no longer used, so we define our own constants here just for this test.
+const E0123: ErrCode = ErrCode::from_u32(0123);
+const E0456: ErrCode = ErrCode::from_u32(0456);
+
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct Hello {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct HelloWarn {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 //~^ ERROR unsupported type attribute for diagnostic derive enum
 enum DiagnosticOnEnum {
     Foo,
@@ -50,53 +54,53 @@ enum DiagnosticOnEnum {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[diag = "E0123"]
 //~^ ERROR failed to resolve: maybe a missing crate `core`
 struct WrongStructAttrStyle {}
 
 #[derive(Diagnostic)]
-#[nonsense(no_crate_example, code = "E0123")]
+#[nonsense(no_crate_example, code = E0123)]
 //~^ ERROR `#[nonsense(...)]` is not a valid attribute
 //~^^ ERROR diagnostic slug not specified
 //~^^^ ERROR cannot find attribute `nonsense` in this scope
 struct InvalidStructAttr {}
 
 #[derive(Diagnostic)]
-#[diag("E0123")]
+#[diag(code = E0123)]
 //~^ ERROR diagnostic slug not specified
 struct InvalidLitNestedAttr {}
 
 #[derive(Diagnostic)]
-#[diag(nonsense, code = "E0123")]
+#[diag(nonsense, code = E0123)]
 //~^ ERROR cannot find value `nonsense` in module `crate::fluent_generated`
 struct InvalidNestedStructAttr {}
 
 #[derive(Diagnostic)]
-#[diag(nonsense("foo"), code = "E0123", slug = "foo")]
+#[diag(nonsense("foo"), code = E0123, slug = "foo")]
 //~^ ERROR diagnostic slug must be the first argument
 //~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr1 {}
 
 #[derive(Diagnostic)]
-#[diag(nonsense = "...", code = "E0123", slug = "foo")]
+#[diag(nonsense = "...", code = E0123, slug = "foo")]
 //~^ ERROR unknown argument
 //~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr2 {}
 
 #[derive(Diagnostic)]
-#[diag(nonsense = 4, code = "E0123", slug = "foo")]
+#[diag(nonsense = 4, code = E0123, slug = "foo")]
 //~^ ERROR unknown argument
 //~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr3 {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123", slug = "foo")]
+#[diag(no_crate_example, code = E0123, slug = "foo")]
 //~^ ERROR unknown argument
 struct InvalidNestedStructAttr4 {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct WrongPlaceField {
     #[suggestion = "bar"]
     //~^ ERROR `#[suggestion = ...]` is not a valid attribute
@@ -104,19 +108,19 @@ struct WrongPlaceField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
-#[diag(no_crate_example, code = "E0456")]
+#[diag(no_crate_example, code = E0123)]
+#[diag(no_crate_example, code = E0456)]
 //~^ ERROR specified multiple times
 //~^^ ERROR specified multiple times
 struct DiagSpecifiedTwice {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0456", code = "E0457")]
+#[diag(no_crate_example, code = E0123, code = E0456)]
 //~^ ERROR specified multiple times
 struct CodeSpecifiedTwice {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, no_crate::example, code = "E0456")]
+#[diag(no_crate_example, no_crate::example, code = E0123)]
 //~^ ERROR diagnostic slug must be the first argument
 struct SlugSpecifiedTwice {}
 
@@ -124,7 +128,7 @@ struct SlugSpecifiedTwice {}
 struct KindNotProvided {} //~ ERROR diagnostic slug not specified
 
 #[derive(Diagnostic)]
-#[diag(code = "E0456")]
+#[diag(code = E0123)]
 //~^ ERROR diagnostic slug not specified
 struct SlugNotProvided {}
 
@@ -133,7 +137,7 @@ struct SlugNotProvided {}
 struct CodeNotProvided {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct MessageWrongType {
     #[primary_span]
     //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -141,7 +145,7 @@ struct MessageWrongType {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct InvalidPathFieldAttr {
     #[nonsense]
     //~^ ERROR `#[nonsense]` is not a valid attribute
@@ -150,7 +154,7 @@ struct InvalidPathFieldAttr {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithField {
     name: String,
     #[label(no_crate_label)]
@@ -158,7 +162,7 @@ struct ErrorWithField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithMessageAppliedToField {
     #[label(no_crate_label)]
     //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -166,7 +170,7 @@ struct ErrorWithMessageAppliedToField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithNonexistentField {
     #[suggestion(no_crate_suggestion, code = "{name}")]
     //~^ ERROR `name` doesn't refer to a field on this type
@@ -175,7 +179,7 @@ struct ErrorWithNonexistentField {
 
 #[derive(Diagnostic)]
 //~^ ERROR invalid format string: expected `'}'`
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorMissingClosingBrace {
     #[suggestion(no_crate_suggestion, code = "{name")]
     suggestion: (Span, Applicability),
@@ -185,7 +189,7 @@ struct ErrorMissingClosingBrace {
 
 #[derive(Diagnostic)]
 //~^ ERROR invalid format string: unmatched `}`
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorMissingOpeningBrace {
     #[suggestion(no_crate_suggestion, code = "name}")]
     suggestion: (Span, Applicability),
@@ -194,14 +198,14 @@ struct ErrorMissingOpeningBrace {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct LabelOnSpan {
     #[label(no_crate_label)]
     sp: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct LabelOnNonSpan {
     #[label(no_crate_label)]
     //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -209,7 +213,7 @@ struct LabelOnNonSpan {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct Suggest {
     #[suggestion(no_crate_suggestion, code = "This is the suggested code")]
     #[suggestion(no_crate_suggestion, code = "This is the suggested code", style = "normal")]
@@ -220,7 +224,7 @@ struct Suggest {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithoutCode {
     #[suggestion(no_crate_suggestion)]
     //~^ ERROR suggestion without `code = "..."`
@@ -228,7 +232,7 @@ struct SuggestWithoutCode {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithBadKey {
     #[suggestion(nonsense = "bar")]
     //~^ ERROR invalid nested attribute
@@ -237,7 +241,7 @@ struct SuggestWithBadKey {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithShorthandMsg {
     #[suggestion(msg = "bar")]
     //~^ ERROR invalid nested attribute
@@ -246,21 +250,21 @@ struct SuggestWithShorthandMsg {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithoutMsg {
     #[suggestion(code = "bar")]
     suggestion: (Span, Applicability),
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithTypesSwapped {
     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
     suggestion: (Applicability, Span),
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithWrongTypeApplicabilityOnly {
     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
     //~^ ERROR wrong field type for suggestion
@@ -268,14 +272,14 @@ struct SuggestWithWrongTypeApplicabilityOnly {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithSpanOnly {
     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
     suggestion: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithDuplicateSpanAndApplicability {
     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
     suggestion: (Span, Span, Applicability),
@@ -283,7 +287,7 @@ struct SuggestWithDuplicateSpanAndApplicability {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithDuplicateApplicabilityAndSpan {
     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
     suggestion: (Applicability, Applicability, Span),
@@ -291,7 +295,7 @@ struct SuggestWithDuplicateApplicabilityAndSpan {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct WrongKindOfAnnotation {
     #[label = "bar"]
     //~^ ERROR `#[label = ...]` is not a valid attribute
@@ -299,7 +303,7 @@ struct WrongKindOfAnnotation {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct OptionsInErrors {
     #[label(no_crate_label)]
     label: Option<Span>,
@@ -308,7 +312,7 @@ struct OptionsInErrors {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0456")]
+#[diag(no_crate_example, code = E0123)]
 struct MoveOutOfBorrowError<'tcx> {
     name: Ident,
     ty: Ty<'tcx>,
@@ -322,7 +326,7 @@ struct MoveOutOfBorrowError<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithLifetime<'a> {
     #[label(no_crate_label)]
     span: Span,
@@ -330,7 +334,7 @@ struct ErrorWithLifetime<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithDefaultLabelAttr<'a> {
     #[label]
     span: Span,
@@ -338,7 +342,7 @@ struct ErrorWithDefaultLabelAttr<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ArgFieldWithoutSkip {
     #[primary_span]
     span: Span,
@@ -347,7 +351,7 @@ struct ArgFieldWithoutSkip {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ArgFieldWithSkip {
     #[primary_span]
     span: Span,
@@ -358,56 +362,56 @@ struct ArgFieldWithSkip {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithSpannedNote {
     #[note]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithSpannedNoteCustom {
     #[note(no_crate_note)]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[note]
 struct ErrorWithNote {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[note(no_crate_note)]
 struct ErrorWithNoteCustom {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithSpannedHelp {
     #[help]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithSpannedHelpCustom {
     #[help(no_crate_help)]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[help]
 struct ErrorWithHelp {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[help(no_crate_help)]
 struct ErrorWithHelpCustom {
     val: String,
@@ -415,34 +419,34 @@ struct ErrorWithHelpCustom {
 
 #[derive(Diagnostic)]
 #[help]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithHelpWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
 #[help(no_crate_help)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithHelpCustomWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
 #[note]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithNoteWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
 #[note(no_crate_note)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithNoteCustomWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ApplicabilityInBoth {
     #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
     //~^ ERROR specified multiple times
@@ -450,7 +454,7 @@ struct ApplicabilityInBoth {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct InvalidApplicability {
     #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")]
     //~^ ERROR invalid applicability
@@ -458,14 +462,14 @@ struct InvalidApplicability {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ValidApplicability {
     #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
     suggestion: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct NoApplicability {
     #[suggestion(no_crate_suggestion, code = "...")]
     suggestion: Span,
@@ -483,7 +487,7 @@ struct Subdiagnostic {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct VecField {
     #[primary_span]
     #[label]
@@ -491,7 +495,7 @@ struct VecField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct UnitField {
     #[primary_span]
     spans: Span,
@@ -502,7 +506,7 @@ struct UnitField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct OptUnitField {
     #[primary_span]
     spans: Span,
@@ -526,7 +530,7 @@ struct BoolField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct LabelWithTrailingPath {
     #[label(no_crate_label, foo)]
     //~^ ERROR a diagnostic slug must be the first argument to the attribute
@@ -534,7 +538,7 @@ struct LabelWithTrailingPath {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct LabelWithTrailingNameValue {
     #[label(no_crate_label, foo = "...")]
     //~^ ERROR only `no_span` is a valid nested attribute
@@ -542,7 +546,7 @@ struct LabelWithTrailingNameValue {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct LabelWithTrailingList {
     #[label(no_crate_label, foo("..."))]
     //~^ ERROR only `no_span` is a valid nested attribute
@@ -562,42 +566,42 @@ struct PrimarySpanOnLint {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithMultiSpan {
     #[primary_span]
     span: MultiSpan,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[warning]
 struct ErrorWithWarn {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[error(no_crate_example, code = "E0123")]
+#[error(no_crate_example, code = E0123)]
 //~^ ERROR `#[error(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
 //~| ERROR cannot find attribute `error` in this scope
 struct ErrorAttribute {}
 
 #[derive(Diagnostic)]
-#[warn_(no_crate_example, code = "E0123")]
+#[warn_(no_crate_example, code = E0123)]
 //~^ ERROR `#[warn_(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
 //~| ERROR cannot find attribute `warn_` in this scope
 struct WarnAttribute {}
 
 #[derive(Diagnostic)]
-#[lint(no_crate_example, code = "E0123")]
+#[lint(no_crate_example, code = E0123)]
 //~^ ERROR `#[lint(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
 //~| ERROR cannot find attribute `lint` in this scope
 struct LintAttributeOnSessionDiag {}
 
 #[derive(LintDiagnostic)]
-#[lint(no_crate_example, code = "E0123")]
+#[lint(no_crate_example, code = E0123)]
 //~^ ERROR `#[lint(...)]` is not a valid attribute
 //~| ERROR `#[lint(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
@@ -605,7 +609,7 @@ struct LintAttributeOnSessionDiag {}
 struct LintAttributeOnLintDiag {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct DuplicatedSuggestionCode {
     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
     //~^ ERROR specified multiple times
@@ -613,7 +617,7 @@ struct DuplicatedSuggestionCode {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct InvalidTypeInSuggestionTuple {
     #[suggestion(no_crate_suggestion, code = "...")]
     suggestion: (Span, usize),
@@ -621,7 +625,7 @@ struct InvalidTypeInSuggestionTuple {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct MissingApplicabilityInSuggestionTuple {
     #[suggestion(no_crate_suggestion, code = "...")]
     suggestion: (Span,),
@@ -629,7 +633,7 @@ struct MissingApplicabilityInSuggestionTuple {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct MissingCodeInSuggestion {
     #[suggestion(no_crate_suggestion)]
     //~^ ERROR suggestion without `code = "..."`
@@ -637,7 +641,7 @@ struct MissingCodeInSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[multipart_suggestion(no_crate_suggestion)]
 //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
 //~| ERROR cannot find attribute `multipart_suggestion` in this scope
@@ -652,7 +656,7 @@ struct MultipartSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[suggestion(no_crate_suggestion, code = "...")]
 //~^ ERROR `#[suggestion(...)]` is not a valid attribute
 struct SuggestionOnStruct {
@@ -661,7 +665,7 @@ struct SuggestionOnStruct {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[label]
 //~^ ERROR `#[label]` is not a valid attribute
 struct LabelOnStruct {
@@ -688,7 +692,7 @@ enum ExampleEnum {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct RawIdentDiagnosticArg {
     pub r#type: String,
 }
@@ -762,7 +766,7 @@ struct SubdiagnosticEagerSuggestion {
 
 /// with a doc comment on the type..
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct WithDocComment {
     /// ..and the field
     #[primary_span]
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index f376c034587fa..67257c28b6eb0 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -1,11 +1,11 @@
 error: unsupported type attribute for diagnostic derive enum
-  --> $DIR/diagnostic-derive.rs:43:1
+  --> $DIR/diagnostic-derive.rs:47:1
    |
-LL | #[diag(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:46:5
+  --> $DIR/diagnostic-derive.rs:50:5
    |
 LL |     Foo,
    |     ^^^
@@ -13,7 +13,7 @@ LL |     Foo,
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:48:5
+  --> $DIR/diagnostic-derive.rs:52:5
    |
 LL |     Bar,
    |     ^^^
@@ -21,15 +21,15 @@ LL |     Bar,
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[nonsense(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:59:1
+  --> $DIR/diagnostic-derive.rs:63:1
    |
-LL | #[nonsense(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[nonsense(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:59:1
+  --> $DIR/diagnostic-derive.rs:63:1
    |
-LL | / #[nonsense(no_crate_example, code = "E0123")]
+LL | / #[nonsense(no_crate_example, code = E0123)]
 LL | |
 LL | |
 LL | |
@@ -39,9 +39,9 @@ LL | | struct InvalidStructAttr {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:66:1
+  --> $DIR/diagnostic-derive.rs:70:1
    |
-LL | / #[diag("E0123")]
+LL | / #[diag(code = E0123)]
 LL | |
 LL | | struct InvalidLitNestedAttr {}
    | |______________________________^
@@ -49,15 +49,15 @@ LL | | struct InvalidLitNestedAttr {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug must be the first argument
-  --> $DIR/diagnostic-derive.rs:76:16
+  --> $DIR/diagnostic-derive.rs:80:16
    |
-LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
+LL | #[diag(nonsense("foo"), code = E0123, slug = "foo")]
    |                ^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:76:1
+  --> $DIR/diagnostic-derive.rs:80:1
    |
-LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense("foo"), code = E0123, slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr1 {}
@@ -66,17 +66,17 @@ LL | | struct InvalidNestedStructAttr1 {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: unknown argument
-  --> $DIR/diagnostic-derive.rs:82:8
+  --> $DIR/diagnostic-derive.rs:86:8
    |
-LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
+LL | #[diag(nonsense = "...", code = E0123, slug = "foo")]
    |        ^^^^^^^^
    |
    = note: only the `code` parameter is valid after the slug
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:82:1
+  --> $DIR/diagnostic-derive.rs:86:1
    |
-LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense = "...", code = E0123, slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr2 {}
@@ -85,17 +85,17 @@ LL | | struct InvalidNestedStructAttr2 {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: unknown argument
-  --> $DIR/diagnostic-derive.rs:88:8
+  --> $DIR/diagnostic-derive.rs:92:8
    |
-LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
+LL | #[diag(nonsense = 4, code = E0123, slug = "foo")]
    |        ^^^^^^^^
    |
    = note: only the `code` parameter is valid after the slug
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:88:1
+  --> $DIR/diagnostic-derive.rs:92:1
    |
-LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense = 4, code = E0123, slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr3 {}
@@ -104,63 +104,63 @@ LL | | struct InvalidNestedStructAttr3 {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: unknown argument
-  --> $DIR/diagnostic-derive.rs:94:42
+  --> $DIR/diagnostic-derive.rs:98:40
    |
-LL | #[diag(no_crate_example, code = "E0123", slug = "foo")]
-   |                                          ^^^^
+LL | #[diag(no_crate_example, code = E0123, slug = "foo")]
+   |                                        ^^^^
    |
    = note: only the `code` parameter is valid after the slug
 
 error: `#[suggestion = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:101:5
+  --> $DIR/diagnostic-derive.rs:105:5
    |
 LL |     #[suggestion = "bar"]
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:108:8
+  --> $DIR/diagnostic-derive.rs:112:8
    |
-LL | #[diag(no_crate_example, code = "E0456")]
+LL | #[diag(no_crate_example, code = E0456)]
    |        ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:107:8
+  --> $DIR/diagnostic-derive.rs:111:8
    |
-LL | #[diag(no_crate_example, code = "E0123")]
+LL | #[diag(no_crate_example, code = E0123)]
    |        ^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:108:26
+  --> $DIR/diagnostic-derive.rs:112:26
    |
-LL | #[diag(no_crate_example, code = "E0456")]
+LL | #[diag(no_crate_example, code = E0456)]
    |                          ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:107:26
+  --> $DIR/diagnostic-derive.rs:111:26
    |
-LL | #[diag(no_crate_example, code = "E0123")]
+LL | #[diag(no_crate_example, code = E0123)]
    |                          ^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:114:42
+  --> $DIR/diagnostic-derive.rs:118:40
    |
-LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
-   |                                          ^^^^
+LL | #[diag(no_crate_example, code = E0123, code = E0456)]
+   |                                        ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:114:26
+  --> $DIR/diagnostic-derive.rs:118:26
    |
-LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
+LL | #[diag(no_crate_example, code = E0123, code = E0456)]
    |                          ^^^^
 
 error: diagnostic slug must be the first argument
-  --> $DIR/diagnostic-derive.rs:119:43
+  --> $DIR/diagnostic-derive.rs:123:43
    |
-LL | #[diag(no_crate_example, no_crate::example, code = "E0456")]
+LL | #[diag(no_crate_example, no_crate::example, code = E0123)]
    |                                           ^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:124:1
+  --> $DIR/diagnostic-derive.rs:128:1
    |
 LL | struct KindNotProvided {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -168,9 +168,9 @@ LL | struct KindNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:127:1
+  --> $DIR/diagnostic-derive.rs:131:1
    |
-LL | / #[diag(code = "E0456")]
+LL | / #[diag(code = E0123)]
 LL | |
 LL | | struct SlugNotProvided {}
    | |_________________________^
@@ -178,31 +178,31 @@ LL | | struct SlugNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:138:5
+  --> $DIR/diagnostic-derive.rs:142:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: `#[nonsense]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:146:5
+  --> $DIR/diagnostic-derive.rs:150:5
    |
 LL |     #[nonsense]
    |     ^^^^^^^^^^^
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:163:5
+  --> $DIR/diagnostic-derive.rs:167:5
    |
 LL |     #[label(no_crate_label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `name` doesn't refer to a field on this type
-  --> $DIR/diagnostic-derive.rs:171:46
+  --> $DIR/diagnostic-derive.rs:175:46
    |
 LL |     #[suggestion(no_crate_suggestion, code = "{name}")]
    |                                              ^^^^^^^^
 
 error: invalid format string: expected `'}'` but string was terminated
-  --> $DIR/diagnostic-derive.rs:176:10
+  --> $DIR/diagnostic-derive.rs:180:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ expected `'}'` in format string
@@ -211,7 +211,7 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: invalid format string: unmatched `}` found
-  --> $DIR/diagnostic-derive.rs:186:10
+  --> $DIR/diagnostic-derive.rs:190:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ unmatched `}` in format string
@@ -220,19 +220,19 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:206:5
+  --> $DIR/diagnostic-derive.rs:210:5
    |
 LL |     #[label(no_crate_label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:225:5
+  --> $DIR/diagnostic-derive.rs:229:5
    |
 LL |     #[suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid nested attribute
-  --> $DIR/diagnostic-derive.rs:233:18
+  --> $DIR/diagnostic-derive.rs:237:18
    |
 LL |     #[suggestion(nonsense = "bar")]
    |                  ^^^^^^^^
@@ -240,13 +240,13 @@ LL |     #[suggestion(nonsense = "bar")]
    = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:233:5
+  --> $DIR/diagnostic-derive.rs:237:5
    |
 LL |     #[suggestion(nonsense = "bar")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid nested attribute
-  --> $DIR/diagnostic-derive.rs:242:18
+  --> $DIR/diagnostic-derive.rs:246:18
    |
 LL |     #[suggestion(msg = "bar")]
    |                  ^^^
@@ -254,13 +254,13 @@ LL |     #[suggestion(msg = "bar")]
    = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:242:5
+  --> $DIR/diagnostic-derive.rs:246:5
    |
 LL |     #[suggestion(msg = "bar")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: wrong field type for suggestion
-  --> $DIR/diagnostic-derive.rs:265:5
+  --> $DIR/diagnostic-derive.rs:269:5
    |
 LL | /     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
 LL | |
@@ -270,79 +270,79 @@ LL | |     suggestion: Applicability,
    = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:281:24
+  --> $DIR/diagnostic-derive.rs:285:24
    |
 LL |     suggestion: (Span, Span, Applicability),
    |                        ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:281:18
+  --> $DIR/diagnostic-derive.rs:285:18
    |
 LL |     suggestion: (Span, Span, Applicability),
    |                  ^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:289:33
+  --> $DIR/diagnostic-derive.rs:293:33
    |
 LL |     suggestion: (Applicability, Applicability, Span),
    |                                 ^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:289:18
+  --> $DIR/diagnostic-derive.rs:293:18
    |
 LL |     suggestion: (Applicability, Applicability, Span),
    |                  ^^^^^^^^^^^^^
 
 error: `#[label = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:296:5
+  --> $DIR/diagnostic-derive.rs:300:5
    |
 LL |     #[label = "bar"]
    |     ^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:447:5
+  --> $DIR/diagnostic-derive.rs:451:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:449:24
+  --> $DIR/diagnostic-derive.rs:453:24
    |
 LL |     suggestion: (Span, Applicability),
    |                        ^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/diagnostic-derive.rs:455:69
+  --> $DIR/diagnostic-derive.rs:459:69
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")]
    |                                                                     ^^^^^^^^
 
 error: the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()`
-  --> $DIR/diagnostic-derive.rs:522:5
+  --> $DIR/diagnostic-derive.rs:526:5
    |
 LL |     #[help(no_crate_help)]
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: a diagnostic slug must be the first argument to the attribute
-  --> $DIR/diagnostic-derive.rs:531:32
+  --> $DIR/diagnostic-derive.rs:535:32
    |
 LL |     #[label(no_crate_label, foo)]
    |                                ^
 
 error: only `no_span` is a valid nested attribute
-  --> $DIR/diagnostic-derive.rs:539:29
+  --> $DIR/diagnostic-derive.rs:543:29
    |
 LL |     #[label(no_crate_label, foo = "...")]
    |                             ^^^
 
 error: only `no_span` is a valid nested attribute
-  --> $DIR/diagnostic-derive.rs:547:29
+  --> $DIR/diagnostic-derive.rs:551:29
    |
 LL |     #[label(no_crate_label, foo("..."))]
    |                             ^^^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:559:5
+  --> $DIR/diagnostic-derive.rs:563:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -350,15 +350,15 @@ LL |     #[primary_span]
    = help: the `primary_span` field attribute is not valid for lint diagnostics
 
 error: `#[error(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:579:1
+  --> $DIR/diagnostic-derive.rs:583:1
    |
-LL | #[error(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[error(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:579:1
+  --> $DIR/diagnostic-derive.rs:583:1
    |
-LL | / #[error(no_crate_example, code = "E0123")]
+LL | / #[error(no_crate_example, code = E0123)]
 LL | |
 LL | |
 LL | |
@@ -368,15 +368,15 @@ LL | | struct ErrorAttribute {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[warn_(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:586:1
+  --> $DIR/diagnostic-derive.rs:590:1
    |
-LL | #[warn_(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[warn_(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:586:1
+  --> $DIR/diagnostic-derive.rs:590:1
    |
-LL | / #[warn_(no_crate_example, code = "E0123")]
+LL | / #[warn_(no_crate_example, code = E0123)]
 LL | |
 LL | |
 LL | |
@@ -386,15 +386,15 @@ LL | | struct WarnAttribute {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:593:1
+  --> $DIR/diagnostic-derive.rs:597:1
    |
-LL | #[lint(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:593:1
+  --> $DIR/diagnostic-derive.rs:597:1
    |
-LL | / #[lint(no_crate_example, code = "E0123")]
+LL | / #[lint(no_crate_example, code = E0123)]
 LL | |
 LL | |
 LL | |
@@ -404,23 +404,23 @@ LL | | struct LintAttributeOnSessionDiag {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:600:1
+  --> $DIR/diagnostic-derive.rs:604:1
    |
-LL | #[lint(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:600:1
+  --> $DIR/diagnostic-derive.rs:604:1
    |
-LL | #[lint(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:600:1
+  --> $DIR/diagnostic-derive.rs:604:1
    |
-LL | / #[lint(no_crate_example, code = "E0123")]
+LL | / #[lint(no_crate_example, code = E0123)]
 LL | |
 LL | |
 LL | |
@@ -431,19 +431,19 @@ LL | | struct LintAttributeOnLintDiag {}
    = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:610:53
+  --> $DIR/diagnostic-derive.rs:614:53
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
    |                                                     ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:610:39
+  --> $DIR/diagnostic-derive.rs:614:39
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
    |                                       ^^^^
 
 error: wrong types for suggestion
-  --> $DIR/diagnostic-derive.rs:619:24
+  --> $DIR/diagnostic-derive.rs:623:24
    |
 LL |     suggestion: (Span, usize),
    |                        ^^^^^
@@ -451,7 +451,7 @@ LL |     suggestion: (Span, usize),
    = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
 
 error: wrong types for suggestion
-  --> $DIR/diagnostic-derive.rs:627:17
+  --> $DIR/diagnostic-derive.rs:631:17
    |
 LL |     suggestion: (Span,),
    |                 ^^^^^^^
@@ -459,13 +459,13 @@ LL |     suggestion: (Span,),
    = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:634:5
+  --> $DIR/diagnostic-derive.rs:638:5
    |
 LL |     #[suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:641:1
+  --> $DIR/diagnostic-derive.rs:645:1
    |
 LL | #[multipart_suggestion(no_crate_suggestion)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -473,7 +473,7 @@ LL | #[multipart_suggestion(no_crate_suggestion)]
    = help: consider creating a `Subdiagnostic` instead
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:644:1
+  --> $DIR/diagnostic-derive.rs:648:1
    |
 LL | #[multipart_suggestion()]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -481,7 +481,7 @@ LL | #[multipart_suggestion()]
    = help: consider creating a `Subdiagnostic` instead
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:648:5
+  --> $DIR/diagnostic-derive.rs:652:5
    |
 LL |     #[multipart_suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -489,7 +489,7 @@ LL |     #[multipart_suggestion(no_crate_suggestion)]
    = help: consider creating a `Subdiagnostic` instead
 
 error: `#[suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:656:1
+  --> $DIR/diagnostic-derive.rs:660:1
    |
 LL | #[suggestion(no_crate_suggestion, code = "...")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -497,7 +497,7 @@ LL | #[suggestion(no_crate_suggestion, code = "...")]
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
 error: `#[label]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:665:1
+  --> $DIR/diagnostic-derive.rs:669:1
    |
 LL | #[label]
    | ^^^^^^^^
@@ -505,31 +505,31 @@ LL | #[label]
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
 error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:699:7
+  --> $DIR/diagnostic-derive.rs:703:7
    |
 LL |     #[subdiagnostic(bad)]
    |       ^^^^^^^^^^^^^^^^^^
 
 error: `#[subdiagnostic = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:707:5
+  --> $DIR/diagnostic-derive.rs:711:5
    |
 LL |     #[subdiagnostic = "bad"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:715:7
+  --> $DIR/diagnostic-derive.rs:719:7
    |
 LL |     #[subdiagnostic(bad, bad)]
    |       ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:723:7
+  --> $DIR/diagnostic-derive.rs:727:7
    |
 LL |     #[subdiagnostic("bad")]
    |       ^^^^^^^^^^^^^^^^^^^^
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:731:5
+  --> $DIR/diagnostic-derive.rs:735:5
    |
 LL |     #[subdiagnostic(eager)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -537,19 +537,19 @@ LL |     #[subdiagnostic(eager)]
    = help: eager subdiagnostics are not supported on lints
 
 error: expected at least one string literal for `code(...)`
-  --> $DIR/diagnostic-derive.rs:789:23
+  --> $DIR/diagnostic-derive.rs:793:23
    |
 LL |     #[suggestion(code())]
    |                       ^
 
 error: `code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:797:23
+  --> $DIR/diagnostic-derive.rs:801:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
 error: `#[suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:821:5
+  --> $DIR/diagnostic-derive.rs:825:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -559,85 +559,85 @@ LL |     #[suggestion(no_crate_suggestion, code = "")]
    = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]`
 
 error[E0433]: failed to resolve: maybe a missing crate `core`?
-  --> $DIR/diagnostic-derive.rs:54:8
+  --> $DIR/diagnostic-derive.rs:58:8
    |
 LL | #[diag = "E0123"]
    |        ^ maybe a missing crate `core`?
 
 error[E0433]: failed to resolve: maybe a missing crate `core`?
-  --> $DIR/diagnostic-derive.rs:797:23
+  --> $DIR/diagnostic-derive.rs:801:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^ maybe a missing crate `core`?
 
 error[E0433]: failed to resolve: maybe a missing crate `core`?
-  --> $DIR/diagnostic-derive.rs:806:25
+  --> $DIR/diagnostic-derive.rs:810:25
    |
 LL |     #[suggestion(code = 3)]
    |                         ^ maybe a missing crate `core`?
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:59:3
+  --> $DIR/diagnostic-derive.rs:63:3
    |
-LL | #[nonsense(no_crate_example, code = "E0123")]
+LL | #[nonsense(no_crate_example, code = E0123)]
    |   ^^^^^^^^
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:146:7
+  --> $DIR/diagnostic-derive.rs:150:7
    |
 LL |     #[nonsense]
    |       ^^^^^^^^
 
 error: cannot find attribute `error` in this scope
-  --> $DIR/diagnostic-derive.rs:579:3
+  --> $DIR/diagnostic-derive.rs:583:3
    |
-LL | #[error(no_crate_example, code = "E0123")]
+LL | #[error(no_crate_example, code = E0123)]
    |   ^^^^^
 
 error: cannot find attribute `warn_` in this scope
-  --> $DIR/diagnostic-derive.rs:586:3
+  --> $DIR/diagnostic-derive.rs:590:3
    |
-LL | #[warn_(no_crate_example, code = "E0123")]
+LL | #[warn_(no_crate_example, code = E0123)]
    |   ^^^^^ help: a built-in attribute with a similar name exists: `warn`
 
 error: cannot find attribute `lint` in this scope
-  --> $DIR/diagnostic-derive.rs:593:3
+  --> $DIR/diagnostic-derive.rs:597:3
    |
-LL | #[lint(no_crate_example, code = "E0123")]
+LL | #[lint(no_crate_example, code = E0123)]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `lint` in this scope
-  --> $DIR/diagnostic-derive.rs:600:3
+  --> $DIR/diagnostic-derive.rs:604:3
    |
-LL | #[lint(no_crate_example, code = "E0123")]
+LL | #[lint(no_crate_example, code = E0123)]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:641:3
+  --> $DIR/diagnostic-derive.rs:645:3
    |
 LL | #[multipart_suggestion(no_crate_suggestion)]
    |   ^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:644:3
+  --> $DIR/diagnostic-derive.rs:648:3
    |
 LL | #[multipart_suggestion()]
    |   ^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:648:7
+  --> $DIR/diagnostic-derive.rs:652:7
    |
 LL |     #[multipart_suggestion(no_crate_suggestion)]
    |       ^^^^^^^^^^^^^^^^^^^^
 
 error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated`
-  --> $DIR/diagnostic-derive.rs:71:8
+  --> $DIR/diagnostic-derive.rs:75:8
    |
-LL | #[diag(nonsense, code = "E0123")]
+LL | #[diag(nonsense, code = E0123)]
    |        ^^^^^^^^ not found in `crate::fluent_generated`
 
 error[E0425]: cannot find value `__code_34` in this scope
-  --> $DIR/diagnostic-derive.rs:803:10
+  --> $DIR/diagnostic-derive.rs:807:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ not found in this scope
@@ -645,7 +645,7 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-  --> $DIR/diagnostic-derive.rs:345:12
+  --> $DIR/diagnostic-derive.rs:349:12
    |
 LL | #[derive(Diagnostic)]
    |          ---------- required by a bound introduced by this call
diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs
index a0a8114e0c5c5..785da11b9b2e3 100644
--- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs
+++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs
@@ -19,6 +19,6 @@ use rustc_errors::{Applicability, MultiSpan};
 extern crate rustc_session;
 
 #[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(compiletest_example, code = 0123)]
 //~^ ERROR diagnostic slug and crate name do not match
 struct Hello {}
diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr
index 4cdc24e6a6bc9..eda24a555f848 100644
--- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr
@@ -1,7 +1,7 @@
 error: diagnostic slug and crate name do not match
   --> $DIR/enforce_slug_naming.rs:22:8
    |
-LL | #[diag(compiletest_example, code = "E0123")]
+LL | #[diag(compiletest_example, code = 0123)]
    |        ^^^^^^^^^^^^^^^^^^^
    |
    = note: slug is `compiletest_example` but the crate name is `rustc_dummy`
diff --git a/tests/ui/associated-type-bounds/return-type-notation/issue-120208-higher-ranked-const.rs b/tests/ui/associated-type-bounds/return-type-notation/issue-120208-higher-ranked-const.rs
new file mode 100644
index 0000000000000..3b350e14fd937
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/issue-120208-higher-ranked-const.rs
@@ -0,0 +1,17 @@
+// edition: 2021
+
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait HealthCheck {
+    async fn check<const N: usize>() -> bool;
+}
+
+async fn do_health_check_par<HC>(hc: HC)
+where
+    HC: HealthCheck<check(): Send> + Send + 'static,
+    //~^ ERROR return type notation is not allowed for functions that have const parameters
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/issue-120208-higher-ranked-const.stderr b/tests/ui/associated-type-bounds/return-type-notation/issue-120208-higher-ranked-const.stderr
new file mode 100644
index 0000000000000..8a3f037d00321
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/issue-120208-higher-ranked-const.stderr
@@ -0,0 +1,20 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-120208-higher-ranked-const.rs:3:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: return type notation is not allowed for functions that have const parameters
+  --> $DIR/issue-120208-higher-ranked-const.rs:12:21
+   |
+LL |     async fn check<const N: usize>() -> bool;
+   |                    -------------- const parameter declared here
+...
+LL |     HC: HealthCheck<check(): Send> + Send + 'static,
+   |                     ^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error; 1 warning emitted
+
diff --git a/tests/ui/extern/auxiliary/issue-80074-macro-2.rs b/tests/ui/extern/auxiliary/issue-80074-macro-2.rs
new file mode 100644
index 0000000000000..bc87a2b543478
--- /dev/null
+++ b/tests/ui/extern/auxiliary/issue-80074-macro-2.rs
@@ -0,0 +1,3 @@
+// edition:2018
+
+macro_rules! m { () => {}; }
diff --git a/tests/ui/extern/auxiliary/issue-80074-macro.rs b/tests/ui/extern/auxiliary/issue-80074-macro.rs
index 30e0f19ab8d84..3e912d977159a 100644
--- a/tests/ui/extern/auxiliary/issue-80074-macro.rs
+++ b/tests/ui/extern/auxiliary/issue-80074-macro.rs
@@ -2,3 +2,5 @@
 
 macro_rules! foo_ { () => {}; }
 use foo_ as foo;
+
+macro_rules! bar { () => {}; }
diff --git a/tests/ui/extern/issue-80074.rs b/tests/ui/extern/issue-80074.rs
index f83027d4abfd2..6e4f176de8201 100644
--- a/tests/ui/extern/issue-80074.rs
+++ b/tests/ui/extern/issue-80074.rs
@@ -1,10 +1,20 @@
 // edition:2018
-// build-pass
 // aux-crate:issue_80074=issue-80074-macro.rs
+// aux-crate:issue_80074_2=issue-80074-macro-2.rs
 
 #[macro_use]
 extern crate issue_80074;
 
+#[macro_use(m)]
+extern crate issue_80074_2;
+//~^^ ERROR: imported macro not found
+
 fn main() {
     foo!();
+    //~^ WARN: macro `foo` is private
+    //~| WARN: it will become a hard error in a future release!
+    bar!();
+    //~^ ERROR: cannot find macro `bar` in this scope
+    m!();
+    //~^ ERROR: cannot find macro `m` in this scope
 }
diff --git a/tests/ui/extern/issue-80074.stderr b/tests/ui/extern/issue-80074.stderr
new file mode 100644
index 0000000000000..b30b761593e88
--- /dev/null
+++ b/tests/ui/extern/issue-80074.stderr
@@ -0,0 +1,31 @@
+error[E0469]: imported macro not found
+  --> $DIR/issue-80074.rs:8:13
+   |
+LL | #[macro_use(m)]
+   |             ^
+
+error: cannot find macro `bar` in this scope
+  --> $DIR/issue-80074.rs:16:5
+   |
+LL |     bar!();
+   |     ^^^
+
+error: cannot find macro `m` in this scope
+  --> $DIR/issue-80074.rs:18:5
+   |
+LL |     m!();
+   |     ^
+
+warning: macro `foo` is private
+  --> $DIR/issue-80074.rs:13:5
+   |
+LL |     foo!();
+   |     ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120192 <https://github.com/rust-lang/rust/issues/120192>
+   = note: `#[warn(private_macro_use)]` on by default
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0469`.
diff --git a/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr b/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
index d05971fb0529d..5e3d34aa9f3ed 100644
--- a/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
+++ b/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
@@ -7,6 +7,7 @@ LL |         0 .. 3 => {}
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
index e2fab14ffc235..cf3bde9705b6b 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
@@ -21,6 +21,7 @@ LL |         if let n @ 2..3|4 = x {
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
 
 error[E0658]: exclusive range pattern syntax is experimental
   --> $DIR/range_pat_interactions1.rs:14:23
@@ -31,6 +32,7 @@ LL |         } else if let 2..3 | 4 = x {
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr
index fe233496261c1..51cc22e7d5602 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr
@@ -17,6 +17,7 @@ LL |             1 | -3..0 => first_or.push(x),
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
 
 error[E0658]: exclusive range pattern syntax is experimental
   --> $DIR/range_pat_interactions3.rs:12:18
@@ -27,6 +28,7 @@ LL |             y @ (0..5 | 6) => or_two.push(y),
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
 
 error[E0658]: exclusive range pattern syntax is experimental
   --> $DIR/range_pat_interactions3.rs:14:17
@@ -37,6 +39,7 @@ LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
 
 error[E0658]: exclusive range pattern syntax is experimental
   --> $DIR/range_pat_interactions3.rs:18:17
@@ -47,6 +50,7 @@ LL |             y @ ..-7 => assert_eq!(y, -8),
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr
index 5edd877bee03e..be8f3aa5051e3 100644
--- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr
+++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr
@@ -17,6 +17,7 @@ LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
 
 error[E0658]: exclusive range pattern syntax is experimental
   --> $DIR/slice_pattern_syntax_problem1.rs:4:32
@@ -27,6 +28,7 @@ LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/imports/auxiliary/issue-119369-extern.rs b/tests/ui/imports/auxiliary/issue-119369-extern.rs
new file mode 100644
index 0000000000000..278cbfa1e3e54
--- /dev/null
+++ b/tests/ui/imports/auxiliary/issue-119369-extern.rs
@@ -0,0 +1,2 @@
+use std::vec;
+use std::hash::Hash;
diff --git a/tests/ui/imports/issue-119369.rs b/tests/ui/imports/issue-119369.rs
new file mode 100644
index 0000000000000..0b4dc3f4654bd
--- /dev/null
+++ b/tests/ui/imports/issue-119369.rs
@@ -0,0 +1,14 @@
+// check-pass
+// aux-build: issue-119369-extern.rs
+
+// https://github.com/rust-lang/rust/pull/119369#issuecomment-1874905662
+
+#[macro_use]
+extern crate issue_119369_extern;
+
+#[derive(Hash)]
+struct A;
+
+fn main() {
+    let _: Vec<i32> = vec![];
+}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr
index e17859eb40f27..d9d7e297f8e97 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr
@@ -97,6 +97,7 @@ error: call to function `sse2` with `#[target_feature]` is unsafe and requires u
 LL |     sse2();
    |     ^^^^^^ call to function with `#[target_feature]`
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = help: in order for the call to be safe, the context requires the following additional target feature: sse2
    = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
 note: an unsafe function restricts its caller, but its body is safe by default
diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr
index 1187c2d80f388..2eb1754392e1a 100644
--- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr
+++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr
@@ -4,6 +4,7 @@ warning: call to unsafe function `unsf` is unsafe and requires unsafe block (err
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: consult the function's documentation for information on how to avoid undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
   --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:9:1
diff --git a/tests/ui/unsafe/auxiliary/external_unsafe_macro.rs b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/auxiliary/external_unsafe_macro.rs
similarity index 100%
rename from tests/ui/unsafe/auxiliary/external_unsafe_macro.rs
rename to tests/ui/unsafe/unsafe_op_in_unsafe_fn/auxiliary/external_unsafe_macro.rs
diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.rs b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.rs
new file mode 100644
index 0000000000000..4196b1cae249d
--- /dev/null
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.rs
@@ -0,0 +1,20 @@
+// edition: 2024
+// compile-flags: -Zunstable-options
+// check-pass
+
+// Tests that `unsafe_op_in_unsafe_fn` is warn-by-default in edition 2024 and that the
+// `unused_unsafe` lint does not consider the inner unsafe block to be unused.
+#![crate_type = "lib"]
+#![deny(unused_unsafe)]
+
+unsafe fn unsf() {}
+
+unsafe fn foo() {
+    unsf();
+    //~^ WARN
+
+    // no unused_unsafe
+    unsafe {
+        unsf();
+    }
+}
diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr
new file mode 100644
index 0000000000000..e6d1d4e5cc780
--- /dev/null
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr
@@ -0,0 +1,17 @@
+warning: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/edition_2024_default.rs:13:5
+   |
+LL |     unsf();
+   |     ^^^^^^ call to unsafe function
+   |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/edition_2024_default.rs:12:1
+   |
+LL | unsafe fn foo() {
+   | ^^^^^^^^^^^^^^^
+   = note: `#[warn(unsafe_op_in_unsafe_fn)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.rs b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.rs
new file mode 100644
index 0000000000000..ec04bf8d63143
--- /dev/null
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.rs
@@ -0,0 +1,9 @@
+#![deny(rust_2024_compatibility)]
+#![crate_type = "lib"]
+
+unsafe fn unsf() {}
+
+unsafe fn foo() {
+    unsf();
+    //~^ ERROR call to unsafe function `unsf` is unsafe and requires unsafe block
+}
diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr
new file mode 100644
index 0000000000000..5092c1e689d67
--- /dev/null
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr
@@ -0,0 +1,22 @@
+error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/in_2024_compatibility.rs:7:5
+   |
+LL |     unsf();
+   |     ^^^^^^ call to unsafe function
+   |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/in_2024_compatibility.rs:6:1
+   |
+LL | unsafe fn foo() {
+   | ^^^^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/in_2024_compatibility.rs:1:9
+   |
+LL | #![deny(rust_2024_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(rust_2024_compatibility)]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.rs
similarity index 100%
rename from tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs
rename to tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.rs
diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr
similarity index 87%
rename from tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr
rename to tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr
index ea0659b2e104d..4bc604a110ea1 100644
--- a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr
@@ -4,6 +4,7 @@ error: call to unsafe function `unsf` is unsafe and requires unsafe block (error
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: consult the function's documentation for information on how to avoid undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:8:1
@@ -22,6 +23,7 @@ error: dereference of raw pointer is unsafe and requires unsafe block (error E01
 LL |     *PTR;
    |     ^^^^ dereference of raw pointer
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
 error: use of mutable static is unsafe and requires unsafe block (error E0133)
@@ -30,6 +32,7 @@ error: use of mutable static is unsafe and requires unsafe block (error E0133)
 LL |     VOID = ();
    |     ^^^^ use of mutable static
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
 error: unnecessary `unsafe` block
@@ -50,6 +53,7 @@ error: call to unsafe function `unsf` is unsafe and requires unsafe block (error
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: consult the function's documentation for information on how to avoid undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:23:1
@@ -69,6 +73,7 @@ error: dereference of raw pointer is unsafe and requires unsafe block (error E01
 LL |     *PTR;
    |     ^^^^ dereference of raw pointer
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
 error: use of mutable static is unsafe and requires unsafe block (error E0133)
@@ -77,6 +82,7 @@ error: use of mutable static is unsafe and requires unsafe block (error E0133)
 LL |     VOID = ();
    |     ^^^^ use of mutable static
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
 error: unnecessary `unsafe` block
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.fixed
similarity index 56%
rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed
rename to tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.fixed
index 20f4fe847daca..8f5cc014a3bab 100644
--- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.fixed
@@ -11,50 +11,60 @@ unsafe fn unsf() {}
 pub unsafe fn foo() { unsafe {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
     unsf(); //~ ERROR call to unsafe function `unsf` is unsafe
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE call to unsafe function
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE consult the function's documentation
     unsf(); //~ ERROR call to unsafe function `unsf` is unsafe
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE call to unsafe function
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE consult the function's documentation
 }}
 
 pub unsafe fn bar(x: *const i32) -> i32 { unsafe {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
     let y = *x; //~ ERROR dereference of raw pointer is unsafe and requires unsafe block
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE dereference of raw pointer
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE raw pointers may be null
     y + *x //~ ERROR dereference of raw pointer is unsafe and requires unsafe block
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE dereference of raw pointer
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE raw pointers may be null
 }}
 
 static mut BAZ: i32 = 0;
 pub unsafe fn baz() -> i32 { unsafe {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
     let y = BAZ; //~ ERROR use of mutable static is unsafe and requires unsafe block
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE use of mutable static
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE mutable statics can be mutated by multiple threads
     y + BAZ //~ ERROR use of mutable static is unsafe and requires unsafe block
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE use of mutable static
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE mutable statics can be mutated by multiple threads
 }}
 
 macro_rules! unsafe_macro { () => (unsf()) }
 //~^ ERROR call to unsafe function `unsf` is unsafe
-//~| NOTE
-//~| NOTE
+//~| NOTE call to unsafe function
+//~| NOTE for more information, see issue #71668
+//~| NOTE consult the function's documentation
 //~| ERROR call to unsafe function `unsf` is unsafe
-//~| NOTE
-//~| NOTE
+//~| NOTE call to unsafe function
+//~| NOTE for more information, see issue #71668
+//~| NOTE consult the function's documentation
 
 pub unsafe fn unsafe_in_macro() { unsafe {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
     unsafe_macro!();
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE in this expansion
+    //~| NOTE in this expansion
+    //~| NOTE in this expansion
     unsafe_macro!();
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE in this expansion
+    //~| NOTE in this expansion
+    //~| NOTE in this expansion
 }}
 
 pub unsafe fn unsafe_in_external_macro() {
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.rs
similarity index 56%
rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.rs
rename to tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.rs
index 13a446d2d2480..90c9e28239693 100644
--- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.rs
@@ -11,50 +11,60 @@ unsafe fn unsf() {}
 pub unsafe fn foo() {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
     unsf(); //~ ERROR call to unsafe function `unsf` is unsafe
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE call to unsafe function
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE consult the function's documentation
     unsf(); //~ ERROR call to unsafe function `unsf` is unsafe
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE call to unsafe function
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE consult the function's documentation
 }
 
 pub unsafe fn bar(x: *const i32) -> i32 {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
     let y = *x; //~ ERROR dereference of raw pointer is unsafe and requires unsafe block
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE dereference of raw pointer
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE raw pointers may be null
     y + *x //~ ERROR dereference of raw pointer is unsafe and requires unsafe block
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE dereference of raw pointer
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE raw pointers may be null
 }
 
 static mut BAZ: i32 = 0;
 pub unsafe fn baz() -> i32 {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
     let y = BAZ; //~ ERROR use of mutable static is unsafe and requires unsafe block
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE use of mutable static
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE mutable statics can be mutated by multiple threads
     y + BAZ //~ ERROR use of mutable static is unsafe and requires unsafe block
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE use of mutable static
+    //~| NOTE for more information, see issue #71668
+    //~| NOTE mutable statics can be mutated by multiple threads
 }
 
 macro_rules! unsafe_macro { () => (unsf()) }
 //~^ ERROR call to unsafe function `unsf` is unsafe
-//~| NOTE
-//~| NOTE
+//~| NOTE call to unsafe function
+//~| NOTE for more information, see issue #71668
+//~| NOTE consult the function's documentation
 //~| ERROR call to unsafe function `unsf` is unsafe
-//~| NOTE
-//~| NOTE
+//~| NOTE call to unsafe function
+//~| NOTE for more information, see issue #71668
+//~| NOTE consult the function's documentation
 
 pub unsafe fn unsafe_in_macro() {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
     unsafe_macro!();
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE in this expansion
+    //~| NOTE in this expansion
+    //~| NOTE in this expansion
     unsafe_macro!();
-    //~^ NOTE
-    //~| NOTE
+    //~^ NOTE in this expansion
+    //~| NOTE in this expansion
+    //~| NOTE in this expansion
 }
 
 pub unsafe fn unsafe_in_external_macro() {
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr
similarity index 74%
rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr
rename to tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr
index 84b58bc028858..b9f5969474d00 100644
--- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr
@@ -4,6 +4,7 @@ error: call to unsafe function `unsf` is unsafe and requires unsafe block (error
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: consult the function's documentation for information on how to avoid undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
   --> $DIR/wrapping-unsafe-block-sugg.rs:11:1
@@ -17,57 +18,62 @@ LL | #![deny(unsafe_op_in_unsafe_fn)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:16:5
+  --> $DIR/wrapping-unsafe-block-sugg.rs:17:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:23:13
+  --> $DIR/wrapping-unsafe-block-sugg.rs:25:13
    |
 LL |     let y = *x;
    |             ^^ dereference of raw pointer
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/wrapping-unsafe-block-sugg.rs:21:1
+  --> $DIR/wrapping-unsafe-block-sugg.rs:23:1
    |
 LL | pub unsafe fn bar(x: *const i32) -> i32 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:26:9
+  --> $DIR/wrapping-unsafe-block-sugg.rs:29:9
    |
 LL |     y + *x
    |         ^^ dereference of raw pointer
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
 error: use of mutable static is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:34:13
+  --> $DIR/wrapping-unsafe-block-sugg.rs:38:13
    |
 LL |     let y = BAZ;
    |             ^^^ use of mutable static
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/wrapping-unsafe-block-sugg.rs:32:1
+  --> $DIR/wrapping-unsafe-block-sugg.rs:36:1
    |
 LL | pub unsafe fn baz() -> i32 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of mutable static is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:37:9
+  --> $DIR/wrapping-unsafe-block-sugg.rs:42:9
    |
 LL |     y + BAZ
    |         ^^^ use of mutable static
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
 error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:42:36
+  --> $DIR/wrapping-unsafe-block-sugg.rs:48:36
    |
 LL | macro_rules! unsafe_macro { () => (unsf()) }
    |                                    ^^^^^^ call to unsafe function
@@ -75,16 +81,17 @@ LL | macro_rules! unsafe_macro { () => (unsf()) }
 LL |     unsafe_macro!();
    |     --------------- in this macro invocation
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: consult the function's documentation for information on how to avoid undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/wrapping-unsafe-block-sugg.rs:50:1
+  --> $DIR/wrapping-unsafe-block-sugg.rs:58:1
    |
 LL | pub unsafe fn unsafe_in_macro() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:42:36
+  --> $DIR/wrapping-unsafe-block-sugg.rs:48:36
    |
 LL | macro_rules! unsafe_macro { () => (unsf()) }
    |                                    ^^^^^^ call to unsafe function
@@ -92,6 +99,7 @@ LL | macro_rules! unsafe_macro { () => (unsf()) }
 LL |     unsafe_macro!();
    |     --------------- in this macro invocation
    |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: consult the function's documentation for information on how to avoid undefined behavior
    = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/triagebot.toml b/triagebot.toml
index a9ddd1b99c72a..57d58fee2893a 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -476,7 +476,7 @@ of `ObligationCtxt`.
 """
 cc = ["@lcnr", "@compiler-errors"]
 
-[mentions."compiler/rustc_error_codes/src/error_codes.rs"]
+[mentions."compiler/rustc_error_codes/src/lib.rs"]
 message = "Some changes occurred in diagnostic error codes"
 cc = ["@GuillaumeGomez"]