about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl2
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs9
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/util.rs6
-rw-r--r--compiler/rustc_expand/src/config.rs15
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs26
-rw-r--r--compiler/rustc_interface/src/util.rs27
-rw-r--r--compiler/rustc_lint/messages.ftl14
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs137
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs56
-rw-r--r--compiler/rustc_metadata/messages.ftl2
-rw-r--r--compiler/rustc_metadata/src/creader.rs25
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs32
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs15
-rw-r--r--compiler/rustc_resolve/src/imports.rs9
-rw-r--r--compiler/rustc_resolve/src/late.rs9
-rw-r--r--compiler/rustc_resolve/src/lib.rs10
-rw-r--r--compiler/rustc_resolve/src/macros.rs47
-rw-r--r--compiler/rustc_session/src/parse.rs17
20 files changed, 295 insertions, 173 deletions
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 0f158990319..a3d6a1c7360 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -247,5 +247,3 @@ builtin_macros_unexpected_lit = expected path to a trait, found literal
     .label = not a trait
     .str_lit = try using `#[derive({$sym})]`
     .other = for example, write `#[derive(Debug)]` for `Debug`
-
-builtin_macros_unnameable_test_items = cannot test inner items
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 49b1b8cf992..bf2a5813af6 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -1,6 +1,7 @@
 use crate::errors;
 use crate::util::expr_to_spanned_string;
 use ast::token::IdentIsRaw;
+use lint::BuiltinLintDiag;
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter};
@@ -509,19 +510,19 @@ fn expand_preparsed_asm(
             };
 
             if template_str.contains(".intel_syntax") {
-                ecx.psess().buffer_lint(
+                ecx.psess().buffer_lint_with_diagnostic(
                     lint::builtin::BAD_ASM_STYLE,
                     find_span(".intel_syntax"),
                     ecx.current_expansion.lint_node_id,
-                    "avoid using `.intel_syntax`, Intel syntax is the default",
+                    BuiltinLintDiag::AvoidUsingIntelSyntax,
                 );
             }
             if template_str.contains(".att_syntax") {
-                ecx.psess().buffer_lint(
+                ecx.psess().buffer_lint_with_diagnostic(
                     lint::builtin::BAD_ASM_STYLE,
                     find_span(".att_syntax"),
                     ecx.current_expansion.lint_node_id,
-                    "avoid using `.att_syntax`, prefer using `options(att_syntax)` instead",
+                    BuiltinLintDiag::AvoidUsingAttSyntax,
                 );
             }
         }
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index 47b2ee975ca..15d2546ba86 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -11,6 +11,7 @@ use rustc_expand::base::{
     resolve_path, DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult,
 };
 use rustc_expand::module::DirOwnership;
+use rustc_lint_defs::BuiltinLintDiag;
 use rustc_parse::new_parser_from_file;
 use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
@@ -143,11 +144,11 @@ pub(crate) fn expand_include<'cx>(
         fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<P<ast::Expr>> {
             let expr = parse_expr(&mut self.p).ok()?;
             if self.p.token != token::Eof {
-                self.p.psess.buffer_lint(
+                self.p.psess.buffer_lint_with_diagnostic(
                     INCOMPLETE_INCLUDE,
                     self.p.token.span,
                     self.node_id,
-                    "include macro expected single expression in source",
+                    BuiltinLintDiag::IncompleteInclude,
                 );
             }
             Some(expr)
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 8cf431482ff..f6c35a75228 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -9,6 +9,7 @@ use rustc_ast::{attr, ModKind};
 use rustc_expand::base::{ExtCtxt, ResolverExpand};
 use rustc_expand::expand::{AstFragment, ExpansionConfig};
 use rustc_feature::Features;
+use rustc_lint_defs::BuiltinLintDiag;
 use rustc_session::lint::builtin::UNNAMEABLE_TEST_ITEMS;
 use rustc_session::Session;
 use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency};
@@ -159,11 +160,11 @@ struct InnerItemLinter<'a> {
 impl<'a> Visitor<'a> for InnerItemLinter<'_> {
     fn visit_item(&mut self, i: &'a ast::Item) {
         if let Some(attr) = attr::find_by_name(&i.attrs, sym::rustc_test_marker) {
-            self.sess.psess.buffer_lint(
+            self.sess.psess.buffer_lint_with_diagnostic(
                 UNNAMEABLE_TEST_ITEMS,
                 attr.span,
                 i.id,
-                crate::fluent_generated::builtin_macros_unnameable_test_items,
+                BuiltinLintDiag::UnnameableTestItems,
             );
         }
     }
diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs
index 8dc7bc14ec3..f08238ad460 100644
--- a/compiler/rustc_builtin_macros/src/util.rs
+++ b/compiler/rustc_builtin_macros/src/util.rs
@@ -5,7 +5,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt};
 use rustc_expand::expand::AstFragment;
 use rustc_feature::AttributeTemplate;
-use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
+use rustc_lint_defs::{builtin::DUPLICATE_MACRO_ATTRIBUTES, BuiltinLintDiag};
 use rustc_parse::{parser, validate_attr};
 use rustc_session::errors::report_lit_error;
 use rustc_span::{BytePos, Span, Symbol};
@@ -42,11 +42,11 @@ pub(crate) fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable,
     };
     if let Some(attrs) = attrs {
         if let Some(attr) = attr::find_by_name(attrs, name) {
-            ecx.psess().buffer_lint(
+            ecx.psess().buffer_lint_with_diagnostic(
                 DUPLICATE_MACRO_ATTRIBUTES,
                 attr.span,
                 ecx.current_expansion.lint_node_id,
-                "duplicated attribute",
+                BuiltinLintDiag::DuplicateMacroAttribute,
             );
         }
     }
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 35f0d8abffc..45d87d5e5a5 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -14,6 +14,7 @@ use rustc_attr as attr;
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_feature::Features;
 use rustc_feature::{ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES};
+use rustc_lint_defs::BuiltinLintDiag;
 use rustc_parse::validate_attr;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
@@ -248,7 +249,6 @@ impl<'a> StripUnconfigured<'a> {
     /// Gives a compiler warning when the `cfg_attr` contains no attributes and
     /// is in the original source file. Gives a compiler error if the syntax of
     /// the attribute is incorrect.
-    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     pub(crate) fn expand_cfg_attr(&self, attr: &Attribute, recursive: bool) -> Vec<Attribute> {
         let Some((cfg_predicate, expanded_attrs)) =
             rustc_parse::parse_cfg_attr(attr, &self.sess.psess)
@@ -258,11 +258,11 @@ impl<'a> StripUnconfigured<'a> {
 
         // Lint on zero attributes in source.
         if expanded_attrs.is_empty() {
-            self.sess.psess.buffer_lint(
+            self.sess.psess.buffer_lint_with_diagnostic(
                 rustc_lint_defs::builtin::UNUSED_ATTRIBUTES,
                 attr.span,
                 ast::CRATE_NODE_ID,
-                "`#[cfg_attr]` does not expand to any attributes",
+                BuiltinLintDiag::CfgAttrNoAttributes,
             );
         }
 
@@ -283,7 +283,6 @@ impl<'a> StripUnconfigured<'a> {
         }
     }
 
-    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn expand_cfg_attr_item(
         &self,
         attr: &Attribute,
@@ -342,19 +341,19 @@ impl<'a> StripUnconfigured<'a> {
             item_span,
         );
         if attr.has_name(sym::crate_type) {
-            self.sess.psess.buffer_lint(
+            self.sess.psess.buffer_lint_with_diagnostic(
                 rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
                 attr.span,
                 ast::CRATE_NODE_ID,
-                "`crate_type` within an `#![cfg_attr] attribute is deprecated`",
+                BuiltinLintDiag::CrateTypeInCfgAttr,
             );
         }
         if attr.has_name(sym::crate_name) {
-            self.sess.psess.buffer_lint(
+            self.sess.psess.buffer_lint_with_diagnostic(
                 rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
                 attr.span,
                 ast::CRATE_NODE_ID,
-                "`crate_name` within an `#![cfg_attr] attribute is deprecated`",
+                BuiltinLintDiag::CrateNameInCfgAttr,
             );
         }
         attr
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index dce8e0c36ed..63eeefa314c 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -110,7 +110,8 @@ use crate::mbe::{KleeneToken, TokenTree};
 use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind};
 use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{DiagMessage, MultiSpan};
+use rustc_errors::MultiSpan;
+use rustc_lint_defs::BuiltinLintDiag;
 use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::kw;
@@ -252,7 +253,7 @@ fn check_binders(
                 // 1. The meta-variable is already bound in the current LHS: This is an error.
                 let mut span = MultiSpan::from_span(span);
                 span.push_span_label(prev_info.span, "previous declaration");
-                buffer_lint(psess, span, node_id, "duplicate matcher binding");
+                buffer_lint(psess, span, node_id, BuiltinLintDiag::DuplicateMatcherBinding);
             } else if get_binder_info(macros, binders, name).is_none() {
                 // 2. The meta-variable is free: This is a binder.
                 binders.insert(name, BinderInfo { span, ops: ops.into() });
@@ -267,11 +268,11 @@ fn check_binders(
                 // FIXME: Report this as a hard error eventually and remove equivalent errors from
                 // `parse_tt_inner` and `nameize`. Until then the error may be reported twice, once
                 // as a hard error and then once as a buffered lint.
-                psess.buffer_lint(
+                psess.buffer_lint_with_diagnostic(
                     MISSING_FRAGMENT_SPECIFIER,
                     span,
                     node_id,
-                    "missing fragment specifier",
+                    BuiltinLintDiag::MissingFragmentSpecifier,
                 );
             }
             if !macros.is_empty() {
@@ -595,7 +596,7 @@ fn check_ops_is_prefix(
             return;
         }
     }
-    buffer_lint(psess, span.into(), node_id, format!("unknown macro variable `{name}`"));
+    buffer_lint(psess, span.into(), node_id, BuiltinLintDiag::UnknownMacroVariable(name));
 }
 
 /// Returns whether `binder_ops` is a prefix of `occurrence_ops`.
@@ -628,8 +629,7 @@ fn ops_is_prefix(
         if i >= occurrence_ops.len() {
             let mut span = MultiSpan::from_span(span);
             span.push_span_label(binder.span, "expected repetition");
-            let message = format!("variable '{name}' is still repeating at this depth");
-            buffer_lint(psess, span, node_id, message);
+            buffer_lint(psess, span, node_id, BuiltinLintDiag::MetaVariableStillRepeating(name));
             return;
         }
         let occurrence = &occurrence_ops[i];
@@ -637,21 +637,15 @@ fn ops_is_prefix(
             let mut span = MultiSpan::from_span(span);
             span.push_span_label(binder.span, "expected repetition");
             span.push_span_label(occurrence.span, "conflicting repetition");
-            let message = "meta-variable repeats with different Kleene operator";
-            buffer_lint(psess, span, node_id, message);
+            buffer_lint(psess, span, node_id, BuiltinLintDiag::MetaVariableWrongOperator);
             return;
         }
     }
 }
 
-fn buffer_lint(
-    psess: &ParseSess,
-    span: MultiSpan,
-    node_id: NodeId,
-    message: impl Into<DiagMessage>,
-) {
+fn buffer_lint(psess: &ParseSess, span: MultiSpan, node_id: NodeId, diag: BuiltinLintDiag) {
     // Macros loaded from other crates have dummy node ids.
     if node_id != DUMMY_NODE_ID {
-        psess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, message);
+        psess.buffer_lint_with_diagnostic(META_VARIABLE_MISUSE, span, node_id, diag);
     }
 }
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index de7005a541b..cb25bcac368 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -399,30 +399,17 @@ pub(crate) fn check_attr_crate_type(
 
                 if let ast::MetaItemKind::NameValue(spanned) = a.meta_kind().unwrap() {
                     let span = spanned.span;
-                    let lev_candidate = find_best_match_for_name(
+                    let candidate = find_best_match_for_name(
                         &CRATE_TYPES.iter().map(|(k, _)| *k).collect::<Vec<_>>(),
                         n,
                         None,
                     );
-                    if let Some(candidate) = lev_candidate {
-                        lint_buffer.buffer_lint_with_diagnostic(
-                            lint::builtin::UNKNOWN_CRATE_TYPES,
-                            ast::CRATE_NODE_ID,
-                            span,
-                            BuiltinLintDiag::UnknownCrateTypes(
-                                span,
-                                "did you mean".to_string(),
-                                format!("\"{candidate}\""),
-                            ),
-                        );
-                    } else {
-                        lint_buffer.buffer_lint(
-                            lint::builtin::UNKNOWN_CRATE_TYPES,
-                            ast::CRATE_NODE_ID,
-                            span,
-                            "invalid `crate_type` value",
-                        );
-                    }
+                    lint_buffer.buffer_lint_with_diagnostic(
+                        lint::builtin::UNKNOWN_CRATE_TYPES,
+                        ast::CRATE_NODE_ID,
+                        span,
+                        BuiltinLintDiag::UnknownCrateTypes { span, candidate },
+                    );
                 }
             } else {
                 // This is here mainly to check for using a macro, such as
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index e1b0aec6c96..7abba3bb5c4 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -156,6 +156,9 @@ lint_builtin_unused_doc_comment = unused doc comment
 lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
     .suggestion = use `loop`
 
+lint_cfg_attr_no_attributes =
+    `#[cfg_attr]` does not expand to any attributes
+
 lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
 
 lint_command_line_source = `forbid` lint level was set on command line
@@ -164,6 +167,12 @@ lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as i
     .current_use = this identifier can be confused with `{$existing_sym}`
     .other_use = other identifier used here
 
+lint_crate_name_in_cfg_attr_deprecated =
+    `crate_name` within an `#![cfg_attr] attribute is deprecated`
+
+lint_crate_type_in_cfg_attr_deprecated =
+    `crate_type` within an `#![cfg_attr] attribute is deprecated`
+
 lint_cstring_ptr = getting the inner pointer of a temporary `CString`
     .as_ptr_label = this pointer will be invalid
     .unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
@@ -662,6 +671,8 @@ lint_unknown_lint =
 lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
     .help = add `#![register_tool({$tool_name})]` to the crate root
 
+lint_unnameable_test_items = cannot test inner items
+
 lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
 
 lint_untranslatable_diag = diagnostics should be created using translatable messages
@@ -701,3 +712,6 @@ lint_unused_result = unused result of type `{$ty}`
 
 lint_variant_size_differences =
     enum variant is more than three times larger ({$largest} bytes) than the next largest
+
+lint_wasm_c_abi =
+    older versions of the `wasm-bindgen` crate will be incompatible with future versions of Rust; please update to `wasm-bindgen` v0.2.88
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 70aa14a565d..f298ed98d98 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -11,8 +11,13 @@ use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::Session;
 use rustc_span::BytePos;
 
+use std::fmt::Write;
+
 mod check_cfg;
 
+#[cfg(test)]
+mod tests;
+
 pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) {
     match diagnostic {
         BuiltinLintDiag::UnicodeTextFlow(span, content) => {
@@ -52,7 +57,6 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
                 );
             }
         }
-        BuiltinLintDiag::Normal(_) => (),
         BuiltinLintDiag::AbsPathWithModule(span) => {
             let (sugg, app) = match sess.source_map().span_to_snippet(span) {
                 Ok(ref s) => {
@@ -87,8 +91,15 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
                 ),
             );
         }
-        BuiltinLintDiag::UnknownCrateTypes(span, note, sugg) => {
-            diag.span_suggestion(span, note, sugg, Applicability::MaybeIncorrect);
+        BuiltinLintDiag::UnknownCrateTypes { span, candidate } => {
+            if let Some(candidate) = candidate {
+                diag.span_suggestion(
+                    span,
+                    "did you mean",
+                    format!(r#""{candidate}""#),
+                    Applicability::MaybeIncorrect,
+                );
+            }
         }
         BuiltinLintDiag::UnusedImports { fix_msg, fixes, test_module_span, .. } => {
             if !fixes.is_empty() {
@@ -361,20 +372,46 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
                 "reduce the glob import's visibility or increase visibility of imported items",
             );
         }
-        BuiltinLintDiag::MaybeTypo { span, name } => {
-            diag.span_suggestion_verbose(
-                span,
-                "an attribute with a similar name exists",
-                name,
-                Applicability::MachineApplicable,
-            );
+        BuiltinLintDiag::UnknownDiagnosticAttribute { span, typo_name } => {
+            if let Some(typo_name) = typo_name {
+                diag.span_suggestion_verbose(
+                    span,
+                    "an attribute with a similar name exists",
+                    typo_name,
+                    Applicability::MachineApplicable,
+                );
+            }
         }
+        BuiltinLintDiag::MacroUseDeprecated
+        | BuiltinLintDiag::UnusedMacroUse
+        | BuiltinLintDiag::PrivateExternCrateReexport(_)
+        | BuiltinLintDiag::UnusedLabel
+        | BuiltinLintDiag::MacroIsPrivate(_)
+        | BuiltinLintDiag::UnusedMacroDefinition(_)
+        | BuiltinLintDiag::MacroRuleNeverUsed(_, _)
+        | BuiltinLintDiag::UnstableFeature(_)
+        | BuiltinLintDiag::AvoidUsingIntelSyntax
+        | BuiltinLintDiag::AvoidUsingAttSyntax
+        | BuiltinLintDiag::IncompleteInclude
+        | BuiltinLintDiag::UnnameableTestItems
+        | BuiltinLintDiag::DuplicateMacroAttribute
+        | BuiltinLintDiag::CfgAttrNoAttributes
+        | BuiltinLintDiag::CrateTypeInCfgAttr
+        | BuiltinLintDiag::CrateNameInCfgAttr
+        | BuiltinLintDiag::MissingFragmentSpecifier
+        | BuiltinLintDiag::MetaVariableStillRepeating(_)
+        | BuiltinLintDiag::MetaVariableWrongOperator
+        | BuiltinLintDiag::DuplicateMatcherBinding
+        | BuiltinLintDiag::UnknownMacroVariable(_)
+        | BuiltinLintDiag::UnusedExternCrate2 { .. }
+        | BuiltinLintDiag::WasmCAbi
+        | BuiltinLintDiag::IllFormedAttributeInput { .. }
+        | BuiltinLintDiag::InnerAttributeUnstable { .. } => {}
     }
 }
 
 pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage {
     match diagnostic {
-        BuiltinLintDiag::Normal(msg) => msg.clone(),
         BuiltinLintDiag::AbsPathWithModule(_) => {
             "absolute paths must start with `self`, `super`, `crate`, or an \
                 external crate name in the 2018 edition"
@@ -391,7 +428,7 @@ pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage {
         BuiltinLintDiag::ElidedLifetimesInPaths(_, _, _, _) => {
             "hidden lifetime parameters in types are deprecated".into()
         }
-        BuiltinLintDiag::UnknownCrateTypes(_, _, _) => "invalid `crate_type` value".into(),
+        BuiltinLintDiag::UnknownCrateTypes { .. } => "invalid `crate_type` value".into(),
         BuiltinLintDiag::UnusedImports { span_snippets, .. } => format!(
             "unused import{}{}",
             pluralize!(span_snippets.len()),
@@ -490,5 +527,81 @@ pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage {
             import_vis
         )
         .into(),
+        BuiltinLintDiag::MacroUseDeprecated => "deprecated `#[macro_use]` attribute used to \
+                                import macros should be replaced at use sites \
+                                with a `use` item to import the macro \
+                                instead"
+            .into(),
+        BuiltinLintDiag::UnusedMacroUse => "unused `#[macro_use]` import".into(),
+        BuiltinLintDiag::PrivateExternCrateReexport(ident) => format!(
+            "extern crate `{ident}` is private, and cannot be \
+                                   re-exported (error E0365), consider declaring with \
+                                   `pub`"
+        )
+        .into(),
+        BuiltinLintDiag::UnusedLabel => "unused label".into(),
+        BuiltinLintDiag::MacroIsPrivate(ident) => format!("macro `{ident}` is private").into(),
+        BuiltinLintDiag::UnusedMacroDefinition(name) => {
+            format!("unused macro definition: `{}`", name).into()
+        }
+        BuiltinLintDiag::MacroRuleNeverUsed(n, name) => {
+            format!("rule #{} of macro `{}` is never used", n + 1, name).into()
+        }
+        BuiltinLintDiag::UnstableFeature(msg) => msg.clone().into(),
+        BuiltinLintDiag::AvoidUsingIntelSyntax => {
+            "avoid using `.intel_syntax`, Intel syntax is the default".into()
+        }
+        BuiltinLintDiag::AvoidUsingAttSyntax => {
+            "avoid using `.att_syntax`, prefer using `options(att_syntax)` instead".into()
+        }
+        BuiltinLintDiag::IncompleteInclude => {
+            "include macro expected single expression in source".into()
+        }
+        BuiltinLintDiag::UnnameableTestItems => crate::fluent_generated::lint_unnameable_test_items,
+        BuiltinLintDiag::DuplicateMacroAttribute => "duplicated attribute".into(),
+        BuiltinLintDiag::CfgAttrNoAttributes => {
+            crate::fluent_generated::lint_cfg_attr_no_attributes
+        }
+        BuiltinLintDiag::CrateTypeInCfgAttr => {
+            crate::fluent_generated::lint_crate_type_in_cfg_attr_deprecated
+        }
+        BuiltinLintDiag::CrateNameInCfgAttr => {
+            crate::fluent_generated::lint_crate_name_in_cfg_attr_deprecated
+        }
+        BuiltinLintDiag::MissingFragmentSpecifier => "missing fragment specifier".into(),
+        BuiltinLintDiag::MetaVariableStillRepeating(name) => {
+            format!("variable '{name}' is still repeating at this depth").into()
+        }
+        BuiltinLintDiag::MetaVariableWrongOperator => {
+            "meta-variable repeats with different Kleene operator".into()
+        }
+        BuiltinLintDiag::DuplicateMatcherBinding => "duplicate matcher binding".into(),
+        BuiltinLintDiag::UnknownMacroVariable(name) => {
+            format!("unknown macro variable `{name}`").into()
+        }
+        BuiltinLintDiag::UnusedExternCrate2 { extern_crate, local_crate } => format!(
+            "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
+            extern_crate, local_crate, extern_crate
+        )
+        .into(),
+        BuiltinLintDiag::WasmCAbi => crate::fluent_generated::lint_wasm_c_abi,
+        BuiltinLintDiag::IllFormedAttributeInput { suggestions } => suggestions
+            .iter()
+            .enumerate()
+            .fold("attribute must be of the form ".to_string(), |mut acc, (i, sugg)| {
+                if i != 0 {
+                    write!(acc, " or ").unwrap();
+                }
+                write!(acc, "`{sugg}`").unwrap();
+                acc
+            })
+            .into(),
+        BuiltinLintDiag::InnerAttributeUnstable { is_macro } => if *is_macro {
+            "inner macro attributes are unstable"
+        } else {
+            "custom inner attributes are unstable"
+        }
+        .into(),
+        BuiltinLintDiag::UnknownDiagnosticAttribute { .. } => "unknown diagnostic attribute".into(),
     }
 }
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 53238ed9629..4dacafaaea6 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -5,12 +5,13 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::stable_hasher::{
     HashStable, StableCompare, StableHasher, ToStableHashKey,
 };
-use rustc_error_messages::{DiagMessage, MultiSpan};
+use rustc_error_messages::MultiSpan;
 use rustc_hir::def::Namespace;
 use rustc_hir::HashStableContext;
 use rustc_hir::HirId;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::edition::Edition;
+use rustc_span::symbol::MacroRulesNormalizedIdent;
 use rustc_span::{sym, symbol::Ident, Span, Symbol};
 use rustc_target::spec::abi::Abi;
 
@@ -577,7 +578,6 @@ pub enum DeprecatedSinceKind {
 // becomes hacky (and it gets allocated).
 #[derive(Debug)]
 pub enum BuiltinLintDiag {
-    Normal(DiagMessage),
     AbsPathWithModule(Span),
     ProcMacroDeriveResolutionFallback {
         span: Span,
@@ -586,7 +586,10 @@ pub enum BuiltinLintDiag {
     },
     MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
     ElidedLifetimesInPaths(usize, Span, bool, Span),
-    UnknownCrateTypes(Span, String, String),
+    UnknownCrateTypes {
+        span: Span,
+        candidate: Option<Symbol>,
+    },
     UnusedImports {
         fix_msg: String,
         fixes: Vec<(Span, String)>,
@@ -694,9 +697,42 @@ pub enum BuiltinLintDiag {
         max_vis: String,
         import_vis: String,
     },
-    MaybeTypo {
+    UnknownDiagnosticAttribute {
         span: Span,
-        name: Symbol,
+        typo_name: Option<Symbol>,
+    },
+    MacroUseDeprecated,
+    UnusedMacroUse,
+    PrivateExternCrateReexport(Ident),
+    UnusedLabel,
+    MacroIsPrivate(Ident),
+    UnusedMacroDefinition(Symbol),
+    MacroRuleNeverUsed(usize, Symbol),
+    UnstableFeature(String),
+    AvoidUsingIntelSyntax,
+    AvoidUsingAttSyntax,
+    IncompleteInclude,
+    UnnameableTestItems,
+    DuplicateMacroAttribute,
+    CfgAttrNoAttributes,
+    CrateTypeInCfgAttr,
+    CrateNameInCfgAttr,
+    MissingFragmentSpecifier,
+    MetaVariableStillRepeating(MacroRulesNormalizedIdent),
+    MetaVariableWrongOperator,
+    DuplicateMatcherBinding,
+    UnknownMacroVariable(MacroRulesNormalizedIdent),
+    // FIXME: combine with UnusedExternCrate?
+    UnusedExternCrate2 {
+        extern_crate: Symbol,
+        local_crate: Symbol,
+    },
+    WasmCAbi,
+    IllFormedAttributeInput {
+        suggestions: Vec<String>,
+    },
+    InnerAttributeUnstable {
+        is_macro: bool,
     },
 }
 
@@ -745,16 +781,6 @@ impl LintBuffer {
         self.map.swap_remove(&id).unwrap_or_default()
     }
 
-    pub fn buffer_lint(
-        &mut self,
-        lint: &'static Lint,
-        id: NodeId,
-        sp: impl Into<MultiSpan>,
-        msg: impl Into<DiagMessage>,
-    ) {
-        self.add_lint(lint, id, sp.into(), BuiltinLintDiag::Normal(msg.into()))
-    }
-
     pub fn buffer_lint_with_diagnostic(
         &mut self,
         lint: &'static Lint,
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 3d0846ae6de..2f5dfad265c 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -284,8 +284,6 @@ metadata_unsupported_abi =
 metadata_unsupported_abi_i686 =
     ABI not supported by `#[link(kind = "raw-dylib")]` on i686
 
-metadata_wasm_c_abi =
-    older versions of the `wasm-bindgen` crate will be incompatible with future versions of Rust; please update to `wasm-bindgen` v0.2.88
 metadata_wasm_import_form =
     wasm import module must be of the form `wasm_import_module = "string"`
 
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index e3205fc1d30..394222cdb35 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -20,7 +20,7 @@ use rustc_middle::bug;
 use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
 use rustc_session::config::{self, CrateType, ExternLocation};
 use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource};
-use rustc_session::lint;
+use rustc_session::lint::{self, BuiltinLintDiag};
 use rustc_session::output::validate_crate_name;
 use rustc_session::search_paths::PathKind;
 use rustc_span::edition::Edition;
@@ -974,16 +974,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
                 continue;
             }
 
-            self.sess.psess.buffer_lint(
-                    lint::builtin::UNUSED_CRATE_DEPENDENCIES,
-                    span,
-                    ast::CRATE_NODE_ID,
-                    format!(
-                        "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
-                        name,
-                        self.tcx.crate_name(LOCAL_CRATE),
-                        name),
-                );
+            self.sess.psess.buffer_lint_with_diagnostic(
+                lint::builtin::UNUSED_CRATE_DEPENDENCIES,
+                span,
+                ast::CRATE_NODE_ID,
+                BuiltinLintDiag::UnusedExternCrate2 {
+                    extern_crate: name_interned,
+                    local_crate: self.tcx.crate_name(LOCAL_CRATE),
+                },
+            );
         }
     }
 
@@ -1016,11 +1015,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
             // Make a point span rather than covering the whole file
             let span = krate.spans.inner_span.shrink_to_lo();
 
-            self.sess.psess.buffer_lint(
+            self.sess.psess.buffer_lint_with_diagnostic(
                 lint::builtin::WASM_C_ABI,
                 span,
                 ast::CRATE_NODE_ID,
-                crate::fluent_generated::metadata_wasm_c_abi,
+                BuiltinLintDiag::WasmCAbi,
             );
         }
     }
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index f88edf29dce..3cfc68507d5 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -10,6 +10,7 @@ use rustc_errors::{Applicability, FatalError, PResult};
 use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_session::errors::report_lit_error;
 use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
+use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::parse::ParseSess;
 use rustc_span::{sym, Span, Symbol};
 
@@ -176,37 +177,26 @@ fn emit_malformed_attribute(
     };
 
     let error_msg = format!("malformed `{name}` attribute input");
-    let mut msg = "attribute must be of the form ".to_owned();
     let mut suggestions = vec![];
-    let mut first = true;
     let inner = if style == ast::AttrStyle::Inner { "!" } else { "" };
     if template.word {
-        first = false;
-        let code = format!("#{inner}[{name}]");
-        msg.push_str(&format!("`{code}`"));
-        suggestions.push(code);
+        suggestions.push(format!("#{inner}[{name}]"));
     }
     if let Some(descr) = template.list {
-        if !first {
-            msg.push_str(" or ");
-        }
-        first = false;
-        let code = format!("#{inner}[{name}({descr})]");
-        msg.push_str(&format!("`{code}`"));
-        suggestions.push(code);
+        suggestions.push(format!("#{inner}[{name}({descr})]"));
     }
     if let Some(descr) = template.name_value_str {
-        if !first {
-            msg.push_str(" or ");
-        }
-        let code = format!("#{inner}[{name} = \"{descr}\"]");
-        msg.push_str(&format!("`{code}`"));
-        suggestions.push(code);
+        suggestions.push(format!("#{inner}[{name} = \"{descr}\"]"));
     }
-    suggestions.sort();
     if should_warn(name) {
-        psess.buffer_lint(ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, msg);
+        psess.buffer_lint_with_diagnostic(
+            ILL_FORMED_ATTRIBUTE_INPUT,
+            span,
+            ast::CRATE_NODE_ID,
+            BuiltinLintDiag::IllFormedAttributeInput { suggestions: suggestions.clone() },
+        );
     } else {
+        suggestions.sort();
         psess
             .dcx
             .struct_span_err(span, error_msg)
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 2a8eb940ccf..55b2d91260e 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -388,14 +388,11 @@ impl Resolver<'_, '_> {
                 {
                     if let ImportKind::MacroUse { .. } = import.kind {
                         if !import.span.is_dummy() {
-                            self.lint_buffer.buffer_lint(
+                            self.lint_buffer.buffer_lint_with_diagnostic(
                                 MACRO_USE_EXTERN_CRATE,
                                 import.root_id,
                                 import.span,
-                                "deprecated `#[macro_use]` attribute used to \
-                                import macros should be replaced at use sites \
-                                with a `use` item to import the macro \
-                                instead",
+                                BuiltinLintDiag::MacroUseDeprecated,
                             );
                         }
                     }
@@ -412,8 +409,12 @@ impl Resolver<'_, '_> {
                     }
                 }
                 ImportKind::MacroUse { .. } => {
-                    let msg = "unused `#[macro_use]` import";
-                    self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.root_id, import.span, msg);
+                    self.lint_buffer.buffer_lint_with_diagnostic(
+                        UNUSED_IMPORTS,
+                        import.root_id,
+                        import.span,
+                        BuiltinLintDiag::UnusedMacroUse,
+                    );
                 }
                 _ => {}
             }
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 55a0382a8e8..fb734895049 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -1246,16 +1246,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         if !any_successful_reexport {
             let (ns, binding) = reexport_error.unwrap();
             if pub_use_of_private_extern_crate_hack(import, binding) {
-                let msg = format!(
-                    "extern crate `{ident}` is private, and cannot be \
-                                   re-exported (error E0365), consider declaring with \
-                                   `pub`"
-                );
-                self.lint_buffer.buffer_lint(
+                self.lint_buffer.buffer_lint_with_diagnostic(
                     PUB_USE_OF_PRIVATE_EXTERN_CRATE,
                     import_id,
                     import.span,
-                    msg,
+                    BuiltinLintDiag::PrivateExternCrateReexport(ident),
                 );
             } else {
                 if ns == TypeNS {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 9442741b6cc..359e96775f8 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -24,7 +24,7 @@ use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::ty::DelegationFnSig;
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CrateType, ResolveDocLinks};
-use rustc_session::lint;
+use rustc_session::lint::{self, BuiltinLintDiag};
 use rustc_session::parse::feature_err;
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -4815,7 +4815,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
         visit::walk_crate(&mut late_resolution_visitor, krate);
         for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() {
-            self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");
+            self.lint_buffer.buffer_lint_with_diagnostic(
+                lint::builtin::UNUSED_LABELS,
+                *id,
+                *span,
+                BuiltinLintDiag::UnusedLabel,
+            );
         }
     }
 }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 01bcfec4bdc..dda31f82d2f 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -51,7 +51,7 @@ use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTo
 use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
-use rustc_session::lint::LintBuffer;
+use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -1860,8 +1860,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
         if let NameBindingKind::Import { import, binding } = 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);
+                self.lint_buffer().buffer_lint_with_diagnostic(
+                    PRIVATE_MACRO_USE,
+                    import.root_id,
+                    ident.span,
+                    BuiltinLintDiag::MacroIsPrivate(ident),
+                );
             }
             // 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.
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 63461d5744b..74f55d0a19c 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -311,11 +311,11 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
 
     fn check_unused_macros(&mut self) {
         for (_, &(node_id, ident)) in self.unused_macros.iter() {
-            self.lint_buffer.buffer_lint(
+            self.lint_buffer.buffer_lint_with_diagnostic(
                 UNUSED_MACROS,
                 node_id,
                 ident.span,
-                format!("unused macro definition: `{}`", ident.name),
+                BuiltinLintDiag::UnusedMacroDefinition(ident.name),
             );
         }
         for (&(def_id, arm_i), &(ident, rule_span)) in self.unused_macro_rules.iter() {
@@ -324,11 +324,11 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
                 continue;
             }
             let node_id = self.def_id_to_node_id[def_id];
-            self.lint_buffer.buffer_lint(
+            self.lint_buffer.buffer_lint_with_diagnostic(
                 UNUSED_MACRO_RULES,
                 node_id,
                 rule_span,
-                format!("rule #{} of macro `{}` is never used", arm_i + 1, ident.name),
+                BuiltinLintDiag::MacroRuleNeverUsed(arm_i, ident.name),
             );
         }
     }
@@ -552,14 +552,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         // We are trying to avoid reporting this error if other related errors were reported.
         if res != Res::Err && inner_attr && !self.tcx.features().custom_inner_attributes {
-            let msg = match res {
-                Res::Def(..) => "inner macro attributes are unstable",
-                Res::NonMacroAttr(..) => "custom inner attributes are unstable",
+            let is_macro = match res {
+                Res::Def(..) => true,
+                Res::NonMacroAttr(..) => false,
                 _ => unreachable!(),
             };
             if soft_custom_inner_attributes_gate {
-                self.tcx.sess.psess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg);
+                self.tcx.sess.psess.buffer_lint_with_diagnostic(
+                    SOFT_UNSTABLE,
+                    path.span,
+                    node_id,
+                    BuiltinLintDiag::InnerAttributeUnstable { is_macro },
+                );
             } else {
+                // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::InnerAttributeUnstable`)
+                let msg = if is_macro {
+                    "inner macro attributes are unstable"
+                } else {
+                    "custom inner attributes are unstable"
+                };
                 feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit();
             }
         }
@@ -572,17 +583,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             let distance =
                 edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);
 
-            let help = if distance.is_some() {
-                BuiltinLintDiag::MaybeTypo { span: attribute.span(), name: sym::on_unimplemented }
-            } else {
-                BuiltinLintDiag::Normal
-            };
+            let typo_name = distance.map(|_| sym::on_unimplemented);
+
             self.tcx.sess.psess.buffer_lint_with_diagnostic(
                 UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
                 attribute.span(),
                 node_id,
-                "unknown diagnostic attribute",
-                help,
+                BuiltinLintDiag::UnknownDiagnosticAttribute { span: attribute.span(), typo_name },
             );
         }
 
@@ -835,8 +842,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
                 if !is_allowed(feature) && !allowed_by_implication {
                     let lint_buffer = &mut self.lint_buffer;
-                    let soft_handler =
-                        |lint, span, msg: String| lint_buffer.buffer_lint(lint, node_id, span, msg);
+                    let soft_handler = |lint, span, msg: String| {
+                        lint_buffer.buffer_lint_with_diagnostic(
+                            lint,
+                            node_id,
+                            span,
+                            BuiltinLintDiag::UnstableFeature(msg),
+                        )
+                    };
                     stability::report_unstable(
                         self.tcx.sess,
                         feature,
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 59281f96126..3db586622e5 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -300,23 +300,6 @@ impl ParseSess {
         self.source_map.clone()
     }
 
-    pub fn buffer_lint(
-        &self,
-        lint: &'static Lint,
-        span: impl Into<MultiSpan>,
-        node_id: NodeId,
-        msg: impl Into<DiagMessage>,
-    ) {
-        self.buffered_lints.with_lock(|buffered_lints| {
-            buffered_lints.push(BufferedEarlyLint {
-                span: span.into(),
-                node_id,
-                lint_id: LintId::of(lint),
-                diagnostic: BuiltinLintDiag::Normal(msg.into()),
-            });
-        });
-    }
-
     pub fn buffer_lint_with_diagnostic(
         &self,
         lint: &'static Lint,