Auto merge of #124417 - Xiretza:translate-early-lints, r=fmease

Make early lints translatable

<del>Requires https://github.com/projectfluent/fluent-rs/pull/353.</del> 5134a04eaa

r? diagnostics
This commit is contained in:
bors 2024-05-21 21:36:09 +00:00
commit 791adf759c
80 changed files with 2114 additions and 907 deletions

View file

@ -32,7 +32,7 @@ use rustc_ast as ast;
use rustc_ast::visit::{self, Visitor};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{pluralize, MultiSpan};
use rustc_errors::MultiSpan;
use rustc_hir::def::{DefKind, Res};
use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES};
use rustc_session::lint::builtin::{UNUSED_IMPORTS, UNUSED_QUALIFICATIONS};
@ -151,11 +151,10 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
// We do this in any edition.
if warn_if_unused {
if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) {
self.r.lint_buffer.buffer_lint_with_diagnostic(
self.r.lint_buffer.buffer_lint(
UNUSED_EXTERN_CRATES,
extern_crate.id,
span,
"unused extern crate",
BuiltinLintDiag::UnusedExternCrate {
removal_span: extern_crate.span_with_attributes,
},
@ -204,11 +203,10 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
.span
.find_ancestor_inside(extern_crate.span)
.unwrap_or(extern_crate.ident.span);
self.r.lint_buffer.buffer_lint_with_diagnostic(
self.r.lint_buffer.buffer_lint(
UNUSED_EXTERN_CRATES,
extern_crate.id,
extern_crate.span,
"`extern crate` is not idiomatic in the new edition",
BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span },
);
}
@ -394,10 +392,7 @@ impl Resolver<'_, '_> {
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,
);
}
}
@ -414,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(
UNUSED_IMPORTS,
import.root_id,
import.span,
BuiltinLintDiag::UnusedMacroUse,
);
}
_ => {}
}
@ -434,20 +433,12 @@ impl Resolver<'_, '_> {
visitor.report_unused_extern_crate_items(maybe_unused_extern_crates);
for unused in visitor.unused_imports.values() {
let mut fixes = Vec::new();
let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) {
UnusedSpanResult::Used => continue,
UnusedSpanResult::Unused { spans, remove } => {
fixes.push((remove, String::new()));
spans
}
UnusedSpanResult::PartialUnused { spans, remove } => {
for fix in &remove {
fixes.push((*fix, String::new()));
}
spans
}
};
let (spans, remove_spans) =
match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) {
UnusedSpanResult::Used => continue,
UnusedSpanResult::Unused { spans, remove } => (spans, vec![remove]),
UnusedSpanResult::PartialUnused { spans, remove } => (spans, remove),
};
let ms = MultiSpan::from_spans(spans);
@ -459,23 +450,8 @@ impl Resolver<'_, '_> {
.collect::<Vec<String>>();
span_snippets.sort();
let msg = format!(
"unused import{}{}",
pluralize!(ms.primary_spans().len()),
if !span_snippets.is_empty() {
format!(": {}", span_snippets.join(", "))
} else {
String::new()
}
);
let fix_msg = if fixes.len() == 1 && fixes[0].0 == unused.item_span {
"remove the whole `use` item"
} else if ms.primary_spans().len() > 1 {
"remove the unused imports"
} else {
"remove the unused import"
};
let remove_whole_use = remove_spans.len() == 1 && remove_spans[0] == unused.item_span;
let num_to_remove = ms.primary_spans().len();
// If we are in the `--test` mode, suppress a help that adds the `#[cfg(test)]`
// attribute; however, if not, suggest adding the attribute. There is no way to
@ -501,12 +477,17 @@ impl Resolver<'_, '_> {
}
};
visitor.r.lint_buffer.buffer_lint_with_diagnostic(
visitor.r.lint_buffer.buffer_lint(
UNUSED_IMPORTS,
unused.use_tree_id,
ms,
msg,
BuiltinLintDiag::UnusedImports(fix_msg.into(), fixes, test_module_span),
BuiltinLintDiag::UnusedImports {
remove_whole_use,
num_to_remove,
remove_spans,
test_module_span,
span_snippets,
},
);
}
@ -552,11 +533,10 @@ impl Resolver<'_, '_> {
continue;
}
self.lint_buffer.buffer_lint_with_diagnostic(
self.lint_buffer.buffer_lint(
UNUSED_QUALIFICATIONS,
unn_qua.node_id,
unn_qua.path_span,
"unnecessary qualification",
BuiltinLintDiag::UnusedQualifications { removal_span: unn_qua.removal_span },
);
}

View file

@ -128,13 +128,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.report_with_use_injections(krate);
for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
let msg = "macro-expanded `macro_export` macros from the current crate \
cannot be referred to by absolute paths";
self.lint_buffer.buffer_lint_with_diagnostic(
self.lint_buffer.buffer_lint(
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
CRATE_NODE_ID,
span_use,
msg,
BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
);
}
@ -145,11 +142,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else {
unreachable!()
};
self.lint_buffer.buffer_lint_with_diagnostic(
self.lint_buffer.buffer_lint(
AMBIGUOUS_GLOB_IMPORTS,
import.root_id,
ambiguity_error.ident.span,
diag.msg.to_string(),
BuiltinLintDiag::AmbiguousGlobImports { diag },
);
} else {
@ -526,12 +522,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
let diag = BuiltinLintDiag::AbsPathWithModule(root_span);
self.lint_buffer.buffer_lint_with_diagnostic(
self.lint_buffer.buffer_lint(
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
node_id,
root_span,
"absolute paths must start with `self`, `super`, \
`crate`, or an external crate name in the 2018 edition",
diag,
);
}

View file

@ -524,18 +524,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match binding {
Ok(binding) => {
if let Some(lint_id) = derive_fallback_lint_id {
this.lint_buffer.buffer_lint_with_diagnostic(
this.lint_buffer.buffer_lint(
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
lint_id,
orig_ident.span,
format!(
"cannot find {} `{}` in this scope",
ns.descr(),
ident
),
BuiltinLintDiag::ProcMacroDeriveResolutionFallback(
orig_ident.span,
),
BuiltinLintDiag::ProcMacroDeriveResolutionFallback {
span: orig_ident.span,
ns,
ident,
},
);
}
let misc_flags = if module == this.graph_root {

View file

@ -619,11 +619,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&& binding.res() != Res::Err
&& exported_ambiguities.contains(&binding)
{
self.lint_buffer.buffer_lint_with_diagnostic(
self.lint_buffer.buffer_lint(
AMBIGUOUS_GLOB_REEXPORTS,
import.root_id,
import.root_span,
"ambiguous glob re-exports",
BuiltinLintDiag::AmbiguousGlobReexports {
name: key.ident.to_string(),
namespace: key.ns.descr().to_string(),
@ -655,11 +654,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&& glob_binding.vis.is_public()
&& !binding.vis.is_public()
{
self.lint_buffer.buffer_lint_with_diagnostic(
self.lint_buffer.buffer_lint(
HIDDEN_GLOB_REEXPORTS,
binding_id,
binding.span,
"private item shadows public glob re-export",
BuiltinLintDiag::HiddenGlobReexports {
name: key.ident.name.to_string(),
namespace: key.ns.descr().to_owned(),
@ -1015,17 +1013,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&& !max_vis.is_at_least(import_vis, self.tcx)
{
let def_id = self.local_def_id(id);
let msg = format!(
"glob import doesn't reexport anything with visibility `{}` because no imported item is public enough",
import_vis.to_string(def_id, self.tcx)
);
self.lint_buffer.buffer_lint_with_diagnostic(
self.lint_buffer.buffer_lint(
UNUSED_IMPORTS,
id,
import.span,
msg,
BuiltinLintDiag::RedundantImportVisibility {
max_vis: max_vis.to_string(def_id, self.tcx),
import_vis: import_vis.to_string(def_id, self.tcx),
span: import.span,
},
);
@ -1252,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(
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
import_id,
import.span,
msg,
BuiltinLintDiag::PrivateExternCrateReexport(ident),
);
} else {
if ns == TypeNS {
@ -1397,7 +1386,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
UNUSED_IMPORTS,
id,
import.span,
format!("the item `{source}` is imported redundantly"),
BuiltinLintDiag::RedundantImport(redundant_spans, source),
);
*/

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};
@ -1675,16 +1675,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
return;
}
LifetimeRibKind::AnonymousWarn(node_id) => {
let msg = if elided {
"`&` without an explicit lifetime name cannot be used here"
} else {
"`'_` cannot be used here"
};
self.r.lint_buffer.buffer_lint_with_diagnostic(
self.r.lint_buffer.buffer_lint(
lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
node_id,
lifetime.ident.span,
msg,
lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
elided,
span: lifetime.ident.span,
@ -1966,11 +1960,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}
if should_lint {
self.r.lint_buffer.buffer_lint_with_diagnostic(
self.r.lint_buffer.buffer_lint(
lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
segment_id,
elided_lifetime_span,
"hidden lifetime parameters in types are deprecated",
lint::BuiltinLintDiag::ElidedLifetimesInPaths(
expected_lifetimes,
path_span,
@ -4822,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(
lint::builtin::UNUSED_LABELS,
*id,
*span,
BuiltinLintDiag::UnusedLabel,
);
}
}
}

View file

@ -2652,15 +2652,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
let deletion_span =
if param.bounds.is_empty() { deletion_span() } else { None };
self.r.lint_buffer.buffer_lint_with_diagnostic(
self.r.lint_buffer.buffer_lint(
lint::builtin::SINGLE_USE_LIFETIMES,
param.id,
param.ident.span,
format!("lifetime parameter `{}` only used once", param.ident),
lint::BuiltinLintDiag::SingleUseLifetime {
param_span: param.ident.span,
use_span: Some((use_span, elidable)),
deletion_span,
ident: param.ident,
},
);
}
@ -2670,15 +2670,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
// if the lifetime originates from expanded code, we won't be able to remove it #104432
if deletion_span.is_some_and(|sp| !sp.in_derive_expansion()) {
self.r.lint_buffer.buffer_lint_with_diagnostic(
self.r.lint_buffer.buffer_lint(
lint::builtin::UNUSED_LIFETIMES,
param.id,
param.ident.span,
format!("lifetime parameter `{}` never used", param.ident),
lint::BuiltinLintDiag::SingleUseLifetime {
param_span: param.ident.span,
use_span: None,
deletion_span,
ident: param.ident,
},
);
}

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

@ -315,7 +315,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
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() {
@ -328,7 +328,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
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(
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
};
self.tcx.sess.psess.buffer_lint_with_diagnostic(
let typo_name = distance.map(|_| sym::on_unimplemented);
self.tcx.sess.psess.buffer_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
attribute.span(),
node_id,
"unknown diagnostic attribute",
help,
BuiltinLintDiag::UnknownDiagnosticAttribute { span: attribute.span(), typo_name },
);
}
@ -782,11 +789,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
.invocation_parents
.get(&parent_scope.expansion)
.map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0]);
self.lint_buffer.buffer_lint_with_diagnostic(
self.lint_buffer.buffer_lint(
LEGACY_DERIVE_HELPERS,
node_id,
ident.span,
"derive helper attribute is used before it is introduced",
BuiltinLintDiag::LegacyDeriveHelpers(binding.span),
);
}
@ -836,8 +842,17 @@ 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(
lint,
node_id,
span,
BuiltinLintDiag::UnstableFeature(
// FIXME make this translatable
msg.into(),
),
)
};
stability::report_unstable(
self.tcx.sess,
feature,
@ -853,14 +868,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
if let Some(depr) = &ext.deprecation {
let path = pprust::path_to_string(path);
let (message, lint) = stability::deprecation_message_and_lint(depr, "macro", &path);
stability::early_report_deprecation(
stability::early_report_macro_deprecation(
&mut self.lint_buffer,
message,
depr.suggestion,
lint,
depr,
span,
node_id,
path,
);
}
}