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
.str_lit = try using `#[derive({$sym})]`
.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::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,
);
}
}

View File

@ -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)

View File

@ -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,
);
}
}

View File

@ -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,
);
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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(),
}
}

View File

@ -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,

View File

@ -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"`

View File

@ -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,
);
}
}

View File

@ -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)

View File

@ -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,
);
}
_ => {}
}

View File

@ -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 {

View File

@ -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,
);
}
}
}

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_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.

View File

@ -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,

View File

@ -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,