Update to new lint API

This commit is contained in:
Guillaume Gomez 2025-12-06 21:29:35 +01:00
parent 8d4f59bed7
commit 2340f8054c
9 changed files with 301 additions and 234 deletions

View file

@ -17,9 +17,6 @@ attr_parsing_deprecated_item_suggestion =
attr_parsing_doc_alias_bad_char =
{$char_} character isn't allowed in {$attr_str}
attr_parsing_doc_alias_duplicated = doc alias is duplicated
.label = first defined here
attr_parsing_doc_alias_empty =
{$attr_str} attribute cannot have empty value
@ -33,69 +30,10 @@ attr_parsing_doc_attribute_not_attribute =
nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = "...")]`
.help = only existing builtin attributes are allowed in core/std
attr_parsing_doc_auto_cfg_expects_hide_or_show =
only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]`
attr_parsing_doc_auto_cfg_hide_show_expects_list =
`#![doc(auto_cfg({$attr_name}(...)))]` expects a list of items
attr_parsing_doc_auto_cfg_hide_show_unexpected_item =
`#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or key/value items
attr_parsing_doc_auto_cfg_wrong_literal =
expected boolean for `#[doc(auto_cfg = ...)]`
attr_parsing_doc_invalid =
invalid `doc` attribute
attr_parsing_doc_keyword_not_keyword =
nonexistent keyword `{$keyword}` used in `#[doc(keyword = "...")]`
.help = only existing keywords are allowed in core/std
attr_parsing_doc_test_literal = `#![doc(test(...)]` does not take a literal
attr_parsing_doc_test_takes_list =
`#[doc(test(...)]` takes a list of attributes
attr_parsing_doc_test_unknown =
unknown `doc(test)` attribute `{$name}`
attr_parsing_doc_unknown_any =
unknown `doc` attribute `{$name}`
attr_parsing_doc_unknown_include =
unknown `doc` attribute `include`
.suggestion = use `doc = include_str!` instead
attr_parsing_doc_unknown_passes =
unknown `doc` attribute `{$name}`
.note = `doc` attribute `{$name}` no longer functions; see issue #44136 <https://github.com/rust-lang/rust/issues/44136>
.label = no longer functions
.no_op_note = `doc({$name})` is now a no-op
attr_parsing_doc_unknown_plugins =
unknown `doc` attribute `plugins`
.note = `doc` attribute `plugins` no longer functions; see issue #44136 <https://github.com/rust-lang/rust/issues/44136> and CVE-2018-1000622 <https://nvd.nist.gov/vuln/detail/CVE-2018-1000622>
.label = no longer functions
.no_op_note = `doc(plugins)` is now a no-op
attr_parsing_doc_unknown_spotlight =
unknown `doc` attribute `spotlight`
.note = `doc(spotlight)` was renamed to `doc(notable_trait)`
.suggestion = use `notable_trait` instead
.no_op_note = `doc(spotlight)` is now a no-op
attr_parsing_empty_attribute =
unused attribute
.suggestion = {$valid_without_list ->
[true] remove these parentheses
*[other] remove this attribute
}
.note = {$valid_without_list ->
[true] using `{$attr_path}` with an empty list is equivalent to not using a list at all
*[other] using `{$attr_path}` with an empty list has no effect
}
attr_parsing_empty_confusables =
expected at least one confusable name
@ -317,8 +255,5 @@ attr_parsing_unused_multiple =
.suggestion = remove this attribute
.note = attribute also specified here
attr_parsing_doc_alias_duplicated = doc alias is duplicated
.label = first defined here
attr_parsing_whole_archive_needs_static =
linking modifier `whole-archive` is only compatible with `static` linking kind

View file

@ -116,10 +116,18 @@ impl DocParser {
}
}
Some(name) => {
cx.emit_lint(AttributeLintKind::DocTestUnknown { name }, path.span());
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocTestUnknown { name },
path.span(),
);
}
None => {
cx.emit_lint(AttributeLintKind::DocTestLiteral, path.span());
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocTestLiteral,
path.span(),
);
}
}
}
@ -151,7 +159,11 @@ impl DocParser {
}
if let Some(first_definition) = self.attribute.aliases.get(&alias).copied() {
cx.emit_lint(AttributeLintKind::DuplicateDocAlias { first_definition }, span);
cx.emit_lint(
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
AttributeLintKind::DuplicateDocAlias { first_definition },
span,
);
}
self.attribute.aliases.insert(alias, span);
@ -239,7 +251,11 @@ impl DocParser {
ArgParser::List(list) => {
for meta in list.mixed() {
let MetaItemOrLitParser::MetaItemParser(item) = meta else {
cx.emit_lint(AttributeLintKind::DocAutoCfgExpectsHideOrShow, meta.span());
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocAutoCfgExpectsHideOrShow,
meta.span(),
);
continue;
};
let (kind, attr_name) = match item.path().word_sym() {
@ -247,6 +263,7 @@ impl DocParser {
Some(sym::show) => (HideOrShow::Show, sym::show),
_ => {
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocAutoCfgExpectsHideOrShow,
item.span(),
);
@ -255,6 +272,7 @@ impl DocParser {
};
let ArgParser::List(list) = item.args() else {
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name },
item.span(),
);
@ -266,6 +284,7 @@ impl DocParser {
for item in list.mixed() {
let MetaItemOrLitParser::MetaItemParser(sub_item) = item else {
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name },
item.span(),
);
@ -291,6 +310,7 @@ impl DocParser {
}
_ => {
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocAutoCfgHideShowUnexpectedItem {
attr_name,
},
@ -306,7 +326,11 @@ impl DocParser {
ArgParser::NameValue(nv) => {
let MetaItemLit { kind: LitKind::Bool(bool_value), span, .. } = nv.value_as_lit()
else {
cx.emit_lint(AttributeLintKind::DocAutoCfgWrongLiteral, nv.value_span);
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocAutoCfgWrongLiteral,
nv.value_span,
);
return;
};
self.attribute.auto_cfg_change.push((*bool_value, *span));
@ -397,6 +421,7 @@ impl DocParser {
Some(sym::test) => {
let Some(list) = args.list() else {
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocTestTakesList,
args.span().unwrap_or(path.span()),
);
@ -418,7 +443,11 @@ impl DocParser {
}
}
Some(sym::spotlight) => {
cx.emit_lint(AttributeLintKind::DocUnknownSpotlight, path.span());
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocUnknownSpotlight { span: path.span() },
path.span(),
);
}
Some(sym::include) if let Some(nv) = args.name_value() => {
let inner = match cx.attr_style {
@ -426,23 +455,41 @@ impl DocParser {
AttrStyle::Inner => "!",
};
cx.emit_lint(
AttributeLintKind::DocUnknownInclude { inner, value: nv.value_as_lit().symbol },
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocUnknownInclude {
inner,
value: nv.value_as_lit().symbol,
span: path.span(),
},
path.span(),
);
}
Some(name @ (sym::passes | sym::no_default_passes)) => {
cx.emit_lint(AttributeLintKind::DocUnknownPasses { name }, path.span());
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocUnknownPasses { name, span: path.span() },
path.span(),
);
}
Some(sym::plugins) => {
cx.emit_lint(AttributeLintKind::DocUnknownPlugins, path.span());
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocUnknownPlugins { span: path.span() },
path.span(),
);
}
Some(name) => {
cx.emit_lint(AttributeLintKind::DocUnknownAny { name }, path.span());
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocUnknownAny { name },
path.span(),
);
}
None => {
let full_name =
path.segments().map(|s| s.as_str()).intersperse("::").collect::<String>();
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::DocUnknownAny { name: Symbol::intern(&full_name) },
path.span(),
);
@ -459,7 +506,11 @@ impl DocParser {
ArgParser::NoArgs => {
let suggestions = cx.suggestions();
let span = cx.attr_span;
cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span);
cx.emit_lint(
rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT,
AttributeLintKind::IllFormedAttributeInput { suggestions, docs: None },
span,
);
}
ArgParser::List(items) => {
for i in items.mixed() {

View file

@ -581,13 +581,6 @@ pub(crate) struct NakedFunctionIncompatibleAttribute {
pub attr: String,
}
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_alias_duplicated)]
pub(crate) struct DocAliasDuplicated {
#[label]
pub first_defn: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_link_ordinal_out_of_range)]
#[note]
@ -995,87 +988,6 @@ pub(crate) struct CfgAttrBadDelim {
pub sugg: MetaBadDelimSugg,
}
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_auto_cfg_expects_hide_or_show)]
pub(crate) struct DocAutoCfgExpectsHideOrShow;
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_auto_cfg_hide_show_unexpected_item)]
pub(crate) struct DocAutoCfgHideShowUnexpectedItem {
pub attr_name: Symbol,
}
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_auto_cfg_hide_show_expects_list)]
pub(crate) struct DocAutoCfgHideShowExpectsList {
pub attr_name: Symbol,
}
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_invalid)]
pub(crate) struct DocInvalid;
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_unknown_include)]
pub(crate) struct DocUnknownInclude {
pub inner: &'static str,
pub value: Symbol,
#[suggestion(code = "#{inner}[doc = include_str!(\"{value}\")]")]
pub sugg: (Span, Applicability),
}
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_unknown_spotlight)]
#[note]
#[note(attr_parsing_no_op_note)]
pub(crate) struct DocUnknownSpotlight {
#[suggestion(style = "short", applicability = "machine-applicable", code = "notable_trait")]
pub sugg_span: Span,
}
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_unknown_passes)]
#[note]
#[note(attr_parsing_no_op_note)]
pub(crate) struct DocUnknownPasses {
pub name: Symbol,
#[label]
pub note_span: Span,
}
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_unknown_plugins)]
#[note]
#[note(attr_parsing_no_op_note)]
pub(crate) struct DocUnknownPlugins {
#[label]
pub label_span: Span,
}
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_unknown_any)]
pub(crate) struct DocUnknownAny {
pub name: Symbol,
}
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_auto_cfg_wrong_literal)]
pub(crate) struct DocAutoCfgWrongLiteral;
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_test_takes_list)]
pub(crate) struct DocTestTakesList;
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_test_unknown)]
pub(crate) struct DocTestUnknown {
pub name: Symbol,
}
#[derive(LintDiagnostic)]
#[diag(attr_parsing_doc_test_literal)]
pub(crate) struct DocTestLiteral;
#[derive(Diagnostic)]
#[diag(attr_parsing_doc_alias_malformed)]
pub(crate) struct DocAliasMalformed {

View file

@ -2,7 +2,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
pub use rustc_lint_defs::AttributeLintKind;
use rustc_lint_defs::LintId;
use rustc_macros::HashStable_Generic;
use rustc_span::{Span, Symbol};
use rustc_span::Span;
use crate::HirId;
@ -31,71 +31,3 @@ pub struct AttributeLint<Id> {
pub span: Span,
pub kind: AttributeLintKind,
}
#[derive(Debug, HashStable_Generic)]
pub enum AttributeLintKind {
/// Copy of `IllFormedAttributeInput`
/// specifically for the `invalid_macro_export_arguments` lint until that is removed,
/// see <https://github.com/rust-lang/rust/pull/143857#issuecomment-3079175663>
InvalidMacroExportArguments {
suggestions: Vec<String>,
},
UnusedDuplicate {
this: Span,
other: Span,
warning: bool,
},
IllFormedAttributeInput {
suggestions: Vec<String>,
},
EmptyAttribute {
first_span: Span,
attr_path: AttrPath,
valid_without_list: bool,
},
InvalidTarget {
name: AttrPath,
target: Target,
applied: Vec<String>,
only: &'static str,
},
InvalidStyle {
name: AttrPath,
is_used_as_inner: bool,
target: Target,
target_span: Span,
},
UnsafeAttrOutsideUnsafe {
attribute_name_span: Span,
sugg_spans: (Span, Span),
},
DuplicateDocAlias {
first_definition: Span,
},
DocAutoCfgExpectsHideOrShow,
DocAutoCfgHideShowUnexpectedItem {
attr_name: Symbol,
},
DocAutoCfgHideShowExpectsList {
attr_name: Symbol,
},
DocInvalid,
DocUnknownInclude {
inner: &'static str,
value: Symbol,
},
DocUnknownSpotlight,
DocUnknownPasses {
name: Symbol,
},
DocUnknownPlugins,
DocUnknownAny {
name: Symbol,
},
DocAutoCfgWrongLiteral,
DocTestTakesList,
DocTestUnknown {
name: Symbol,
},
DocTestLiteral,
}

View file

@ -233,6 +233,58 @@ lint_deprecated_where_clause_location = where clause not allowed here
lint_diag_out_of_impl =
diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
lint_doc_alias_duplicated = doc alias is duplicated
.label = first defined here
lint_doc_auto_cfg_expects_hide_or_show =
only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]`
lint_doc_auto_cfg_hide_show_expects_list =
`#![doc(auto_cfg({$attr_name}(...)))]` expects a list of items
lint_doc_auto_cfg_hide_show_unexpected_item =
`#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or key/value items
lint_doc_auto_cfg_wrong_literal =
expected boolean for `#[doc(auto_cfg = ...)]`
lint_doc_invalid =
invalid `doc` attribute
lint_doc_test_literal = `#![doc(test(...)]` does not take a literal
lint_doc_test_takes_list =
`#[doc(test(...)]` takes a list of attributes
lint_doc_test_unknown =
unknown `doc(test)` attribute `{$name}`
lint_doc_unknown_any =
unknown `doc` attribute `{$name}`
lint_doc_unknown_include =
unknown `doc` attribute `include`
.suggestion = use `doc = include_str!` instead
lint_doc_unknown_passes =
unknown `doc` attribute `{$name}`
.note = `doc` attribute `{$name}` no longer functions; see issue #44136 <https://github.com/rust-lang/rust/issues/44136>
.label = no longer functions
.no_op_note = `doc({$name})` is now a no-op
lint_doc_unknown_plugins =
unknown `doc` attribute `plugins`
.note = `doc` attribute `plugins` no longer functions; see issue #44136 <https://github.com/rust-lang/rust/issues/44136> and CVE-2018-1000622 <https://nvd.nist.gov/vuln/detail/CVE-2018-1000622>
.label = no longer functions
.no_op_note = `doc(plugins)` is now a no-op
lint_doc_unknown_spotlight =
unknown `doc` attribute `spotlight`
.note = `doc(spotlight)` was renamed to `doc(notable_trait)`
.suggestion = use `notable_trait` instead
.no_op_note = `doc(spotlight)` is now a no-op
lint_drop_glue =
types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped

View file

@ -367,5 +367,55 @@ pub fn decorate_attribute_lint(
&AttributeLintKind::UnexpectedCfgValue(name, value) => {
check_cfg::unexpected_cfg_value(sess, tcx, name, value).decorate_lint(diag)
}
&AttributeLintKind::DuplicateDocAlias { first_definition } => {
lints::DocAliasDuplicated { first_defn: first_definition }.decorate_lint(diag)
}
&AttributeLintKind::DocAutoCfgExpectsHideOrShow => {
lints::DocAutoCfgExpectsHideOrShow.decorate_lint(diag)
}
&AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => {
lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.decorate_lint(diag)
}
&AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name } => {
lints::DocAutoCfgHideShowExpectsList { attr_name }.decorate_lint(diag)
}
&AttributeLintKind::DocInvalid => { lints::DocInvalid }.decorate_lint(diag),
&AttributeLintKind::DocUnknownInclude { span, inner, value } => {
lints::DocUnknownInclude { inner, value, sugg: (span, Applicability::MaybeIncorrect) }
}
.decorate_lint(diag),
&AttributeLintKind::DocUnknownSpotlight { span } => {
lints::DocUnknownSpotlight { sugg_span: span }.decorate_lint(diag)
}
&AttributeLintKind::DocUnknownPasses { name, span } => {
lints::DocUnknownPasses { name, note_span: span }.decorate_lint(diag)
}
&AttributeLintKind::DocUnknownPlugins { span } => {
lints::DocUnknownPlugins { label_span: span }.decorate_lint(diag)
}
&AttributeLintKind::DocUnknownAny { name } => {
lints::DocUnknownAny { name }.decorate_lint(diag)
}
&AttributeLintKind::DocAutoCfgWrongLiteral => {
lints::DocAutoCfgWrongLiteral.decorate_lint(diag)
}
&AttributeLintKind::DocTestTakesList => lints::DocTestTakesList.decorate_lint(diag),
&AttributeLintKind::DocTestUnknown { name } => {
lints::DocTestUnknown { name }.decorate_lint(diag)
}
&AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.decorate_lint(diag),
}
}

View file

@ -3199,3 +3199,91 @@ pub(crate) struct UnusedVisibility {
#[suggestion(style = "short", code = "", applicability = "machine-applicable")]
pub span: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_doc_alias_duplicated)]
pub(crate) struct DocAliasDuplicated {
#[label]
pub first_defn: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_doc_auto_cfg_expects_hide_or_show)]
pub(crate) struct DocAutoCfgExpectsHideOrShow;
#[derive(LintDiagnostic)]
#[diag(lint_doc_auto_cfg_hide_show_unexpected_item)]
pub(crate) struct DocAutoCfgHideShowUnexpectedItem {
pub attr_name: Symbol,
}
#[derive(LintDiagnostic)]
#[diag(lint_doc_auto_cfg_hide_show_expects_list)]
pub(crate) struct DocAutoCfgHideShowExpectsList {
pub attr_name: Symbol,
}
#[derive(LintDiagnostic)]
#[diag(lint_doc_invalid)]
pub(crate) struct DocInvalid;
#[derive(LintDiagnostic)]
#[diag(lint_doc_unknown_include)]
pub(crate) struct DocUnknownInclude {
pub inner: &'static str,
pub value: Symbol,
#[suggestion(code = "#{inner}[doc = include_str!(\"{value}\")]")]
pub sugg: (Span, Applicability),
}
#[derive(LintDiagnostic)]
#[diag(lint_doc_unknown_spotlight)]
#[note]
#[note(lint_no_op_note)]
pub(crate) struct DocUnknownSpotlight {
#[suggestion(style = "short", applicability = "machine-applicable", code = "notable_trait")]
pub sugg_span: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_doc_unknown_passes)]
#[note]
#[note(lint_no_op_note)]
pub(crate) struct DocUnknownPasses {
pub name: Symbol,
#[label]
pub note_span: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_doc_unknown_plugins)]
#[note]
#[note(lint_no_op_note)]
pub(crate) struct DocUnknownPlugins {
#[label]
pub label_span: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_doc_unknown_any)]
pub(crate) struct DocUnknownAny {
pub name: Symbol,
}
#[derive(LintDiagnostic)]
#[diag(lint_doc_auto_cfg_wrong_literal)]
pub(crate) struct DocAutoCfgWrongLiteral;
#[derive(LintDiagnostic)]
#[diag(lint_doc_test_takes_list)]
pub(crate) struct DocTestTakesList;
#[derive(LintDiagnostic)]
#[diag(lint_doc_test_unknown)]
pub(crate) struct DocTestUnknown {
pub name: Symbol,
}
#[derive(LintDiagnostic)]
#[diag(lint_doc_test_literal)]
pub(crate) struct DocTestLiteral;

View file

@ -733,6 +733,41 @@ pub enum AttributeLintKind {
},
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
DuplicateDocAlias {
first_definition: Span,
},
DocAutoCfgExpectsHideOrShow,
DocAutoCfgHideShowUnexpectedItem {
attr_name: Symbol,
},
DocAutoCfgHideShowExpectsList {
attr_name: Symbol,
},
DocInvalid,
DocUnknownInclude {
span: Span,
inner: &'static str,
value: Symbol,
},
DocUnknownSpotlight {
span: Span,
},
DocUnknownPasses {
name: Symbol,
span: Span,
},
DocUnknownPlugins {
span: Span,
},
DocUnknownAny {
name: Symbol,
},
DocAutoCfgWrongLiteral,
DocTestTakesList,
DocTestUnknown {
name: Symbol,
},
DocTestLiteral,
}
pub type RegisteredTools = FxIndexSet<Ident>;

View file

@ -907,7 +907,19 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
for lint in &delayed_lints.lints {
match lint {
DelayedLint::AttributeParsing(attribute_lint) => {
rustc_attr_parsing::emit_attribute_lint(attribute_lint, tcx)
tcx.node_span_lint(
attribute_lint.lint_id.lint,
attribute_lint.id,
attribute_lint.span,
|diag| {
rustc_lint::decorate_attribute_lint(
tcx.sess,
Some(tcx),
&attribute_lint.kind,
diag,
);
},
);
}
}
}