1
Fork 0

Convert uses of BuiltinLintDiag::Normal to custom variants

This ensures all diagnostic messages are created at diagnostic emission
time, making them translatable.
This commit is contained in:
Xiretza 2024-04-14 20:11:14 +00:00
parent 41a20b4c56
commit b7abf014ec
20 changed files with 295 additions and 173 deletions

View file

@ -247,5 +247,3 @@ builtin_macros_unexpected_lit = expected path to a trait, found literal
.label = not a trait .label = not a trait
.str_lit = try using `#[derive({$sym})]` .str_lit = try using `#[derive({$sym})]`
.other = for example, write `#[derive(Debug)]` for `Debug` .other = for example, write `#[derive(Debug)]` for `Debug`
builtin_macros_unnameable_test_items = cannot test inner items

View file

@ -1,6 +1,7 @@
use crate::errors; use crate::errors;
use crate::util::expr_to_spanned_string; use crate::util::expr_to_spanned_string;
use ast::token::IdentIsRaw; use ast::token::IdentIsRaw;
use lint::BuiltinLintDiag;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter}; use rustc_ast::token::{self, Delimiter};
@ -509,19 +510,19 @@ fn expand_preparsed_asm(
}; };
if template_str.contains(".intel_syntax") { if template_str.contains(".intel_syntax") {
ecx.psess().buffer_lint( ecx.psess().buffer_lint_with_diagnostic(
lint::builtin::BAD_ASM_STYLE, lint::builtin::BAD_ASM_STYLE,
find_span(".intel_syntax"), find_span(".intel_syntax"),
ecx.current_expansion.lint_node_id, ecx.current_expansion.lint_node_id,
"avoid using `.intel_syntax`, Intel syntax is the default", BuiltinLintDiag::AvoidUsingIntelSyntax,
); );
} }
if template_str.contains(".att_syntax") { if template_str.contains(".att_syntax") {
ecx.psess().buffer_lint( ecx.psess().buffer_lint_with_diagnostic(
lint::builtin::BAD_ASM_STYLE, lint::builtin::BAD_ASM_STYLE,
find_span(".att_syntax"), find_span(".att_syntax"),
ecx.current_expansion.lint_node_id, ecx.current_expansion.lint_node_id,
"avoid using `.att_syntax`, prefer using `options(att_syntax)` instead", BuiltinLintDiag::AvoidUsingAttSyntax,
); );
} }
} }

View file

@ -11,6 +11,7 @@ use rustc_expand::base::{
resolve_path, DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, resolve_path, DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult,
}; };
use rustc_expand::module::DirOwnership; use rustc_expand::module::DirOwnership;
use rustc_lint_defs::BuiltinLintDiag;
use rustc_parse::new_parser_from_file; use rustc_parse::new_parser_from_file;
use rustc_parse::parser::{ForceCollect, Parser}; use rustc_parse::parser::{ForceCollect, Parser};
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; 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>> { fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<P<ast::Expr>> {
let expr = parse_expr(&mut self.p).ok()?; let expr = parse_expr(&mut self.p).ok()?;
if self.p.token != token::Eof { if self.p.token != token::Eof {
self.p.psess.buffer_lint( self.p.psess.buffer_lint_with_diagnostic(
INCOMPLETE_INCLUDE, INCOMPLETE_INCLUDE,
self.p.token.span, self.p.token.span,
self.node_id, self.node_id,
"include macro expected single expression in source", BuiltinLintDiag::IncompleteInclude,
); );
} }
Some(expr) Some(expr)

View file

@ -9,6 +9,7 @@ use rustc_ast::{attr, ModKind};
use rustc_expand::base::{ExtCtxt, ResolverExpand}; use rustc_expand::base::{ExtCtxt, ResolverExpand};
use rustc_expand::expand::{AstFragment, ExpansionConfig}; use rustc_expand::expand::{AstFragment, ExpansionConfig};
use rustc_feature::Features; use rustc_feature::Features;
use rustc_lint_defs::BuiltinLintDiag;
use rustc_session::lint::builtin::UNNAMEABLE_TEST_ITEMS; use rustc_session::lint::builtin::UNNAMEABLE_TEST_ITEMS;
use rustc_session::Session; use rustc_session::Session;
use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency}; use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency};
@ -159,11 +160,11 @@ struct InnerItemLinter<'a> {
impl<'a> Visitor<'a> for InnerItemLinter<'_> { impl<'a> Visitor<'a> for InnerItemLinter<'_> {
fn visit_item(&mut self, i: &'a ast::Item) { fn visit_item(&mut self, i: &'a ast::Item) {
if let Some(attr) = attr::find_by_name(&i.attrs, sym::rustc_test_marker) { 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, UNNAMEABLE_TEST_ITEMS,
attr.span, attr.span,
i.id, i.id,
crate::fluent_generated::builtin_macros_unnameable_test_items, BuiltinLintDiag::UnnameableTestItems,
); );
} }
} }

View file

@ -5,7 +5,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt};
use rustc_expand::expand::AstFragment; use rustc_expand::expand::AstFragment;
use rustc_feature::AttributeTemplate; 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_parse::{parser, validate_attr};
use rustc_session::errors::report_lit_error; use rustc_session::errors::report_lit_error;
use rustc_span::{BytePos, Span, Symbol}; 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(attrs) = attrs {
if let Some(attr) = attr::find_by_name(attrs, name) { if let Some(attr) = attr::find_by_name(attrs, name) {
ecx.psess().buffer_lint( ecx.psess().buffer_lint_with_diagnostic(
DUPLICATE_MACRO_ATTRIBUTES, DUPLICATE_MACRO_ATTRIBUTES,
attr.span, attr.span,
ecx.current_expansion.lint_node_id, ecx.current_expansion.lint_node_id,
"duplicated attribute", BuiltinLintDiag::DuplicateMacroAttribute,
); );
} }
} }

View file

@ -14,6 +14,7 @@ use rustc_attr as attr;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_feature::Features; use rustc_feature::Features;
use rustc_feature::{ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES}; use rustc_feature::{ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES};
use rustc_lint_defs::BuiltinLintDiag;
use rustc_parse::validate_attr; use rustc_parse::validate_attr;
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_session::Session; use rustc_session::Session;
@ -248,7 +249,6 @@ impl<'a> StripUnconfigured<'a> {
/// Gives a compiler warning when the `cfg_attr` contains no attributes and /// 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 /// is in the original source file. Gives a compiler error if the syntax of
/// the attribute is incorrect. /// 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> { pub(crate) fn expand_cfg_attr(&self, attr: &Attribute, recursive: bool) -> Vec<Attribute> {
let Some((cfg_predicate, expanded_attrs)) = let Some((cfg_predicate, expanded_attrs)) =
rustc_parse::parse_cfg_attr(attr, &self.sess.psess) rustc_parse::parse_cfg_attr(attr, &self.sess.psess)
@ -258,11 +258,11 @@ impl<'a> StripUnconfigured<'a> {
// Lint on zero attributes in source. // Lint on zero attributes in source.
if expanded_attrs.is_empty() { if expanded_attrs.is_empty() {
self.sess.psess.buffer_lint( self.sess.psess.buffer_lint_with_diagnostic(
rustc_lint_defs::builtin::UNUSED_ATTRIBUTES, rustc_lint_defs::builtin::UNUSED_ATTRIBUTES,
attr.span, attr.span,
ast::CRATE_NODE_ID, 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( fn expand_cfg_attr_item(
&self, &self,
attr: &Attribute, attr: &Attribute,
@ -342,19 +341,19 @@ impl<'a> StripUnconfigured<'a> {
item_span, item_span,
); );
if attr.has_name(sym::crate_type) { 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, rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
attr.span, attr.span,
ast::CRATE_NODE_ID, ast::CRATE_NODE_ID,
"`crate_type` within an `#![cfg_attr] attribute is deprecated`", BuiltinLintDiag::CrateTypeInCfgAttr,
); );
} }
if attr.has_name(sym::crate_name) { 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, rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
attr.span, attr.span,
ast::CRATE_NODE_ID, ast::CRATE_NODE_ID,
"`crate_name` within an `#![cfg_attr] attribute is deprecated`", BuiltinLintDiag::CrateNameInCfgAttr,
); );
} }
attr attr

View file

@ -110,7 +110,8 @@ use crate::mbe::{KleeneToken, TokenTree};
use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind}; use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind};
use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_ast::{NodeId, DUMMY_NODE_ID};
use rustc_data_structures::fx::FxHashMap; 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::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER};
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
use rustc_span::symbol::kw; 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. // 1. The meta-variable is already bound in the current LHS: This is an error.
let mut span = MultiSpan::from_span(span); let mut span = MultiSpan::from_span(span);
span.push_span_label(prev_info.span, "previous declaration"); 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() { } else if get_binder_info(macros, binders, name).is_none() {
// 2. The meta-variable is free: This is a binder. // 2. The meta-variable is free: This is a binder.
binders.insert(name, BinderInfo { span, ops: ops.into() }); 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 // 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 // `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. // as a hard error and then once as a buffered lint.
psess.buffer_lint( psess.buffer_lint_with_diagnostic(
MISSING_FRAGMENT_SPECIFIER, MISSING_FRAGMENT_SPECIFIER,
span, span,
node_id, node_id,
"missing fragment specifier", BuiltinLintDiag::MissingFragmentSpecifier,
); );
} }
if !macros.is_empty() { if !macros.is_empty() {
@ -595,7 +596,7 @@ fn check_ops_is_prefix(
return; 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`. /// Returns whether `binder_ops` is a prefix of `occurrence_ops`.
@ -628,8 +629,7 @@ fn ops_is_prefix(
if i >= occurrence_ops.len() { if i >= occurrence_ops.len() {
let mut span = MultiSpan::from_span(span); let mut span = MultiSpan::from_span(span);
span.push_span_label(binder.span, "expected repetition"); 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, BuiltinLintDiag::MetaVariableStillRepeating(name));
buffer_lint(psess, span, node_id, message);
return; return;
} }
let occurrence = &occurrence_ops[i]; let occurrence = &occurrence_ops[i];
@ -637,21 +637,15 @@ fn ops_is_prefix(
let mut span = MultiSpan::from_span(span); let mut span = MultiSpan::from_span(span);
span.push_span_label(binder.span, "expected repetition"); span.push_span_label(binder.span, "expected repetition");
span.push_span_label(occurrence.span, "conflicting repetition"); span.push_span_label(occurrence.span, "conflicting repetition");
let message = "meta-variable repeats with different Kleene operator"; buffer_lint(psess, span, node_id, BuiltinLintDiag::MetaVariableWrongOperator);
buffer_lint(psess, span, node_id, message);
return; return;
} }
} }
} }
fn buffer_lint( fn buffer_lint(psess: &ParseSess, span: MultiSpan, node_id: NodeId, diag: BuiltinLintDiag) {
psess: &ParseSess,
span: MultiSpan,
node_id: NodeId,
message: impl Into<DiagMessage>,
) {
// Macros loaded from other crates have dummy node ids. // Macros loaded from other crates have dummy node ids.
if node_id != DUMMY_NODE_ID { 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);
} }
} }

View file

@ -399,30 +399,17 @@ pub(crate) fn check_attr_crate_type(
if let ast::MetaItemKind::NameValue(spanned) = a.meta_kind().unwrap() { if let ast::MetaItemKind::NameValue(spanned) = a.meta_kind().unwrap() {
let span = spanned.span; 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<_>>(), &CRATE_TYPES.iter().map(|(k, _)| *k).collect::<Vec<_>>(),
n, n,
None, None,
); );
if let Some(candidate) = lev_candidate {
lint_buffer.buffer_lint_with_diagnostic( lint_buffer.buffer_lint_with_diagnostic(
lint::builtin::UNKNOWN_CRATE_TYPES, lint::builtin::UNKNOWN_CRATE_TYPES,
ast::CRATE_NODE_ID, ast::CRATE_NODE_ID,
span, span,
BuiltinLintDiag::UnknownCrateTypes( BuiltinLintDiag::UnknownCrateTypes { span, candidate },
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",
);
}
} }
} else { } else {
// This is here mainly to check for using a macro, such as // This is here mainly to check for using a macro, such as

View file

@ -156,6 +156,9 @@ lint_builtin_unused_doc_comment = unused doc comment
lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}` lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
.suggestion = use `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_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
lint_command_line_source = `forbid` lint level was set on command line 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}` .current_use = this identifier can be confused with `{$existing_sym}`
.other_use = other identifier used here .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` lint_cstring_ptr = getting the inner pointer of a temporary `CString`
.as_ptr_label = this pointer will be invalid .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 .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}` 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 .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_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
lint_untranslatable_diag = diagnostics should be created using translatable messages 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 = lint_variant_size_differences =
enum variant is more than three times larger ({$largest} bytes) than the next largest 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

View file

@ -11,8 +11,13 @@ use rustc_session::lint::BuiltinLintDiag;
use rustc_session::Session; use rustc_session::Session;
use rustc_span::BytePos; use rustc_span::BytePos;
use std::fmt::Write;
mod check_cfg; mod check_cfg;
#[cfg(test)]
mod tests;
pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) { pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) {
match diagnostic { match diagnostic {
BuiltinLintDiag::UnicodeTextFlow(span, content) => { BuiltinLintDiag::UnicodeTextFlow(span, content) => {
@ -52,7 +57,6 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
); );
} }
} }
BuiltinLintDiag::Normal(_) => (),
BuiltinLintDiag::AbsPathWithModule(span) => { BuiltinLintDiag::AbsPathWithModule(span) => {
let (sugg, app) = match sess.source_map().span_to_snippet(span) { let (sugg, app) = match sess.source_map().span_to_snippet(span) {
Ok(ref s) => { Ok(ref s) => {
@ -87,8 +91,15 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
), ),
); );
} }
BuiltinLintDiag::UnknownCrateTypes(span, note, sugg) => { BuiltinLintDiag::UnknownCrateTypes { span, candidate } => {
diag.span_suggestion(span, note, sugg, Applicability::MaybeIncorrect); 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, .. } => { BuiltinLintDiag::UnusedImports { fix_msg, fixes, test_module_span, .. } => {
if !fixes.is_empty() { 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", "reduce the glob import's visibility or increase visibility of imported items",
); );
} }
BuiltinLintDiag::MaybeTypo { span, name } => { BuiltinLintDiag::UnknownDiagnosticAttribute { span, typo_name } => {
if let Some(typo_name) = typo_name {
diag.span_suggestion_verbose( diag.span_suggestion_verbose(
span, span,
"an attribute with a similar name exists", "an attribute with a similar name exists",
name, typo_name,
Applicability::MachineApplicable, 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 { pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage {
match diagnostic { match diagnostic {
BuiltinLintDiag::Normal(msg) => msg.clone(),
BuiltinLintDiag::AbsPathWithModule(_) => { BuiltinLintDiag::AbsPathWithModule(_) => {
"absolute paths must start with `self`, `super`, `crate`, or an \ "absolute paths must start with `self`, `super`, `crate`, or an \
external crate name in the 2018 edition" external crate name in the 2018 edition"
@ -391,7 +428,7 @@ pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage {
BuiltinLintDiag::ElidedLifetimesInPaths(_, _, _, _) => { BuiltinLintDiag::ElidedLifetimesInPaths(_, _, _, _) => {
"hidden lifetime parameters in types are deprecated".into() "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!( BuiltinLintDiag::UnusedImports { span_snippets, .. } => format!(
"unused import{}{}", "unused import{}{}",
pluralize!(span_snippets.len()), pluralize!(span_snippets.len()),
@ -490,5 +527,81 @@ pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage {
import_vis import_vis
) )
.into(), .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(),
} }
} }

View file

@ -5,12 +5,13 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::stable_hasher::{ use rustc_data_structures::stable_hasher::{
HashStable, StableCompare, StableHasher, ToStableHashKey, HashStable, StableCompare, StableHasher, ToStableHashKey,
}; };
use rustc_error_messages::{DiagMessage, MultiSpan}; use rustc_error_messages::MultiSpan;
use rustc_hir::def::Namespace; use rustc_hir::def::Namespace;
use rustc_hir::HashStableContext; use rustc_hir::HashStableContext;
use rustc_hir::HirId; use rustc_hir::HirId;
use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
use rustc_span::symbol::MacroRulesNormalizedIdent;
use rustc_span::{sym, symbol::Ident, Span, Symbol}; use rustc_span::{sym, symbol::Ident, Span, Symbol};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
@ -577,7 +578,6 @@ pub enum DeprecatedSinceKind {
// becomes hacky (and it gets allocated). // becomes hacky (and it gets allocated).
#[derive(Debug)] #[derive(Debug)]
pub enum BuiltinLintDiag { pub enum BuiltinLintDiag {
Normal(DiagMessage),
AbsPathWithModule(Span), AbsPathWithModule(Span),
ProcMacroDeriveResolutionFallback { ProcMacroDeriveResolutionFallback {
span: Span, span: Span,
@ -586,7 +586,10 @@ pub enum BuiltinLintDiag {
}, },
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
ElidedLifetimesInPaths(usize, Span, bool, Span), ElidedLifetimesInPaths(usize, Span, bool, Span),
UnknownCrateTypes(Span, String, String), UnknownCrateTypes {
span: Span,
candidate: Option<Symbol>,
},
UnusedImports { UnusedImports {
fix_msg: String, fix_msg: String,
fixes: Vec<(Span, String)>, fixes: Vec<(Span, String)>,
@ -694,9 +697,42 @@ pub enum BuiltinLintDiag {
max_vis: String, max_vis: String,
import_vis: String, import_vis: String,
}, },
MaybeTypo { UnknownDiagnosticAttribute {
span: Span, 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() 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( pub fn buffer_lint_with_diagnostic(
&mut self, &mut self,
lint: &'static Lint, lint: &'static Lint,

View file

@ -284,8 +284,6 @@ metadata_unsupported_abi =
metadata_unsupported_abi_i686 = metadata_unsupported_abi_i686 =
ABI not supported by `#[link(kind = "raw-dylib")]` on 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 = metadata_wasm_import_form =
wasm import module must be of the form `wasm_import_module = "string"` wasm import module must be of the form `wasm_import_module = "string"`

View file

@ -20,7 +20,7 @@ use rustc_middle::bug;
use rustc_middle::ty::{TyCtxt, TyCtxtFeed}; use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
use rustc_session::config::{self, CrateType, ExternLocation}; use rustc_session::config::{self, CrateType, ExternLocation};
use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource}; 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::output::validate_crate_name;
use rustc_session::search_paths::PathKind; use rustc_session::search_paths::PathKind;
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
@ -974,15 +974,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
continue; continue;
} }
self.sess.psess.buffer_lint( self.sess.psess.buffer_lint_with_diagnostic(
lint::builtin::UNUSED_CRATE_DEPENDENCIES, lint::builtin::UNUSED_CRATE_DEPENDENCIES,
span, span,
ast::CRATE_NODE_ID, ast::CRATE_NODE_ID,
format!( BuiltinLintDiag::UnusedExternCrate2 {
"external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`", extern_crate: name_interned,
name, local_crate: self.tcx.crate_name(LOCAL_CRATE),
self.tcx.crate_name(LOCAL_CRATE), },
name),
); );
} }
} }
@ -1016,11 +1015,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
// Make a point span rather than covering the whole file // Make a point span rather than covering the whole file
let span = krate.spans.inner_span.shrink_to_lo(); 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, lint::builtin::WASM_C_ABI,
span, span,
ast::CRATE_NODE_ID, ast::CRATE_NODE_ID,
crate::fluent_generated::metadata_wasm_c_abi, BuiltinLintDiag::WasmCAbi,
); );
} }
} }

View file

@ -10,6 +10,7 @@ use rustc_errors::{Applicability, FatalError, PResult};
use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
use rustc_session::errors::report_lit_error; use rustc_session::errors::report_lit_error;
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
use rustc_span::{sym, Span, Symbol}; use rustc_span::{sym, Span, Symbol};
@ -176,37 +177,26 @@ fn emit_malformed_attribute(
}; };
let error_msg = format!("malformed `{name}` attribute input"); 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 suggestions = vec![];
let mut first = true;
let inner = if style == ast::AttrStyle::Inner { "!" } else { "" }; let inner = if style == ast::AttrStyle::Inner { "!" } else { "" };
if template.word { if template.word {
first = false; suggestions.push(format!("#{inner}[{name}]"));
let code = format!("#{inner}[{name}]");
msg.push_str(&format!("`{code}`"));
suggestions.push(code);
} }
if let Some(descr) = template.list { if let Some(descr) = template.list {
if !first { suggestions.push(format!("#{inner}[{name}({descr})]"));
msg.push_str(" or ");
}
first = false;
let code = format!("#{inner}[{name}({descr})]");
msg.push_str(&format!("`{code}`"));
suggestions.push(code);
} }
if let Some(descr) = template.name_value_str { if let Some(descr) = template.name_value_str {
if !first { suggestions.push(format!("#{inner}[{name} = \"{descr}\"]"));
msg.push_str(" or ");
} }
let code = format!("#{inner}[{name} = \"{descr}\"]");
msg.push_str(&format!("`{code}`"));
suggestions.push(code);
}
suggestions.sort();
if should_warn(name) { 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 { } else {
suggestions.sort();
psess psess
.dcx .dcx
.struct_span_err(span, error_msg) .struct_span_err(span, error_msg)

View file

@ -388,14 +388,11 @@ impl Resolver<'_, '_> {
{ {
if let ImportKind::MacroUse { .. } = import.kind { if let ImportKind::MacroUse { .. } = import.kind {
if !import.span.is_dummy() { if !import.span.is_dummy() {
self.lint_buffer.buffer_lint( self.lint_buffer.buffer_lint_with_diagnostic(
MACRO_USE_EXTERN_CRATE, MACRO_USE_EXTERN_CRATE,
import.root_id, import.root_id,
import.span, import.span,
"deprecated `#[macro_use]` attribute used to \ BuiltinLintDiag::MacroUseDeprecated,
import macros should be replaced at use sites \
with a `use` item to import the macro \
instead",
); );
} }
} }
@ -412,8 +409,12 @@ impl Resolver<'_, '_> {
} }
} }
ImportKind::MacroUse { .. } => { ImportKind::MacroUse { .. } => {
let msg = "unused `#[macro_use]` import"; self.lint_buffer.buffer_lint_with_diagnostic(
self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.root_id, import.span, msg); UNUSED_IMPORTS,
import.root_id,
import.span,
BuiltinLintDiag::UnusedMacroUse,
);
} }
_ => {} _ => {}
} }

View file

@ -1246,16 +1246,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if !any_successful_reexport { if !any_successful_reexport {
let (ns, binding) = reexport_error.unwrap(); let (ns, binding) = reexport_error.unwrap();
if pub_use_of_private_extern_crate_hack(import, binding) { if pub_use_of_private_extern_crate_hack(import, binding) {
let msg = format!( self.lint_buffer.buffer_lint_with_diagnostic(
"extern crate `{ident}` is private, and cannot be \
re-exported (error E0365), consider declaring with \
`pub`"
);
self.lint_buffer.buffer_lint(
PUB_USE_OF_PRIVATE_EXTERN_CRATE, PUB_USE_OF_PRIVATE_EXTERN_CRATE,
import_id, import_id,
import.span, import.span,
msg, BuiltinLintDiag::PrivateExternCrateReexport(ident),
); );
} else { } else {
if ns == TypeNS { if ns == TypeNS {

View file

@ -24,7 +24,7 @@ use rustc_middle::middle::resolve_bound_vars::Set1;
use rustc_middle::ty::DelegationFnSig; use rustc_middle::ty::DelegationFnSig;
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_session::config::{CrateType, ResolveDocLinks}; use rustc_session::config::{CrateType, ResolveDocLinks};
use rustc_session::lint; use rustc_session::lint::{self, BuiltinLintDiag};
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_span::source_map::{respan, Spanned}; use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol}; 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)); late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
visit::walk_crate(&mut late_resolution_visitor, krate); visit::walk_crate(&mut late_resolution_visitor, krate);
for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() { 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,
);
} }
} }
} }

View file

@ -51,7 +51,7 @@ use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTo
use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed}; use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed};
use rustc_query_system::ich::StableHashingContext; use rustc_query_system::ich::StableHashingContext;
use rustc_session::lint::builtin::PRIVATE_MACRO_USE; 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::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP}; 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 NameBindingKind::Import { import, binding } = used_binding.kind {
if let ImportKind::MacroUse { warn_private: true } = import.kind { if let ImportKind::MacroUse { warn_private: true } = import.kind {
let msg = format!("macro `{ident}` is private"); self.lint_buffer().buffer_lint_with_diagnostic(
self.lint_buffer().buffer_lint(PRIVATE_MACRO_USE, import.root_id, ident.span, msg); PRIVATE_MACRO_USE,
import.root_id,
ident.span,
BuiltinLintDiag::MacroIsPrivate(ident),
);
} }
// Avoid marking `extern crate` items that refer to a name from extern prelude, // 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. // but not introduce it, as used if they are accessed from lexical scope.

View file

@ -311,11 +311,11 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
fn check_unused_macros(&mut self) { fn check_unused_macros(&mut self) {
for (_, &(node_id, ident)) in self.unused_macros.iter() { for (_, &(node_id, ident)) in self.unused_macros.iter() {
self.lint_buffer.buffer_lint( self.lint_buffer.buffer_lint_with_diagnostic(
UNUSED_MACROS, UNUSED_MACROS,
node_id, node_id,
ident.span, 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() { 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; continue;
} }
let node_id = self.def_id_to_node_id[def_id]; 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, UNUSED_MACRO_RULES,
node_id, node_id,
rule_span, 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. // 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 { if res != Res::Err && inner_attr && !self.tcx.features().custom_inner_attributes {
let msg = match res { let is_macro = match res {
Res::Def(..) => "inner macro attributes are unstable", Res::Def(..) => true,
Res::NonMacroAttr(..) => "custom inner attributes are unstable", Res::NonMacroAttr(..) => false,
_ => unreachable!(), _ => unreachable!(),
}; };
if soft_custom_inner_attributes_gate { 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 { } 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(); 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 = let distance =
edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5); edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);
let help = if distance.is_some() { let typo_name = distance.map(|_| sym::on_unimplemented);
BuiltinLintDiag::MaybeTypo { span: attribute.span(), name: sym::on_unimplemented }
} else {
BuiltinLintDiag::Normal
};
self.tcx.sess.psess.buffer_lint_with_diagnostic( self.tcx.sess.psess.buffer_lint_with_diagnostic(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
attribute.span(), attribute.span(),
node_id, node_id,
"unknown diagnostic attribute", BuiltinLintDiag::UnknownDiagnosticAttribute { span: attribute.span(), typo_name },
help,
); );
} }
@ -835,8 +842,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature)); let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
if !is_allowed(feature) && !allowed_by_implication { if !is_allowed(feature) && !allowed_by_implication {
let lint_buffer = &mut self.lint_buffer; let lint_buffer = &mut self.lint_buffer;
let soft_handler = let soft_handler = |lint, span, msg: String| {
|lint, span, msg: String| lint_buffer.buffer_lint(lint, node_id, span, msg); lint_buffer.buffer_lint_with_diagnostic(
lint,
node_id,
span,
BuiltinLintDiag::UnstableFeature(msg),
)
};
stability::report_unstable( stability::report_unstable(
self.tcx.sess, self.tcx.sess,
feature, feature,

View file

@ -300,23 +300,6 @@ impl ParseSess {
self.source_map.clone() 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( pub fn buffer_lint_with_diagnostic(
&self, &self,
lint: &'static Lint, lint: &'static Lint,