Reduce capabilities of `Diagnostic`.
Currently many diagnostic modifier methods are available on both
`Diagnostic` and `DiagnosticBuilder`. This commit removes most of them
from `Diagnostic`. To minimize the diff size, it keeps them within
`diagnostic.rs` but changes the surrounding `impl Diagnostic` block to
`impl DiagnosticBuilder`. (I intend to move things around later, to give
a more sensible code layout.)
`Diagnostic` keeps a few methods that it still needs, like `sub`,
`arg`, and `replace_args`.
The `forward!` macro, which defined two additional methods per call
(e.g. `note` and `with_note`), is replaced by the `with_fn!` macro,
which defines one additional method per call (e.g. `with_note`). It's
now also only used when necessary -- not all modifier methods currently
need a `with_*` form. (New ones can be easily added as necessary.)
All this also requires changing `trait AddToDiagnostic` so its methods
take `DiagnosticBuilder` instead of `Diagnostic`, which leads to many
mechanical changes. `SubdiagnosticMessageOp` gains a type parameter `G`.
There are three subdiagnostics -- `DelayedAtWithoutNewline`,
`DelayedAtWithNewline`, and `InvalidFlushedDelayedDiagnosticLevel` --
that are created within the diagnostics machinery and appended to
external diagnostics. These are handled at the `Diagnostic` level, which
means it's now hard to construct them via `derive(Diagnostic)`, so
instead we construct them by hand. This has no effect on what they look
like when printed.
There are lots of new `allow` markers for `untranslatable_diagnostics`
and `diagnostics_outside_of_impl`. This is because
`#[rustc_lint_diagnostics]` annotations were present on the `Diagnostic`
modifier methods, but missing from the `DiagnosticBuilder` modifier
methods. They're now present.
2024-02-06 16:44:30 +11:00
|
|
|
#![allow(rustc::diagnostic_outside_of_impl)]
|
|
|
|
|
#![allow(rustc::untranslatable_diagnostic)]
|
|
|
|
|
|
2023-12-30 16:13:23 +01:00
|
|
|
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
|
2024-04-21 13:24:25 +00:00
|
|
|
use rustc_errors::{
|
|
|
|
|
elided_lifetime_in_path_suggestion, pluralize, Diag, DiagMessage, LintDiagnostic,
|
|
|
|
|
};
|
2023-12-30 16:13:23 +01:00
|
|
|
use rustc_errors::{Applicability, SuggestionStyle};
|
|
|
|
|
use rustc_middle::middle::stability;
|
2024-02-29 16:40:44 +11:00
|
|
|
use rustc_session::lint::BuiltinLintDiag;
|
2023-12-30 16:13:23 +01:00
|
|
|
use rustc_session::Session;
|
|
|
|
|
use rustc_span::BytePos;
|
|
|
|
|
|
2024-04-14 20:11:14 +00:00
|
|
|
use std::fmt::Write;
|
|
|
|
|
|
2024-03-16 23:33:54 +01:00
|
|
|
mod check_cfg;
|
2024-02-16 21:32:53 +01:00
|
|
|
|
2024-04-14 20:11:14 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests;
|
|
|
|
|
|
2024-02-29 16:40:44 +11:00
|
|
|
pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) {
|
2023-12-30 16:13:23 +01:00
|
|
|
match diagnostic {
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::UnicodeTextFlow(span, content) => {
|
2023-12-30 16:13:23 +01:00
|
|
|
let spans: Vec<_> = content
|
|
|
|
|
.char_indices()
|
|
|
|
|
.filter_map(|(i, c)| {
|
|
|
|
|
TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
|
|
|
|
|
let lo = span.lo() + BytePos(2 + i as u32);
|
|
|
|
|
(c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
let (an, s) = match spans.len() {
|
|
|
|
|
1 => ("an ", ""),
|
|
|
|
|
_ => ("", "s"),
|
|
|
|
|
};
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(
|
2023-12-30 16:13:23 +01:00
|
|
|
span,
|
|
|
|
|
format!(
|
|
|
|
|
"this comment contains {an}invisible unicode text flow control codepoint{s}",
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
for (c, span) in &spans {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(*span, format!("{c:?}"));
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.note(
|
2023-12-30 16:13:23 +01:00
|
|
|
"these kind of unicode codepoints change the way text flows on \
|
|
|
|
|
applications that support them, but can cause confusion because they \
|
|
|
|
|
change the order of characters on the screen",
|
|
|
|
|
);
|
|
|
|
|
if !spans.is_empty() {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.multipart_suggestion_with_style(
|
2023-12-30 16:13:23 +01:00
|
|
|
"if their presence wasn't intentional, you can remove them",
|
|
|
|
|
spans.into_iter().map(|(_, span)| (span, "".to_string())).collect(),
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
SuggestionStyle::HideCodeAlways,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::AbsPathWithModule(span) => {
|
2023-12-30 16:13:23 +01:00
|
|
|
let (sugg, app) = match sess.source_map().span_to_snippet(span) {
|
|
|
|
|
Ok(ref s) => {
|
|
|
|
|
// FIXME(Manishearth) ideally the emitting code
|
|
|
|
|
// can tell us whether or not this is global
|
|
|
|
|
let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
|
|
|
|
|
|
|
|
|
|
(format!("crate{opt_colon}{s}"), Applicability::MachineApplicable)
|
|
|
|
|
}
|
|
|
|
|
Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
|
|
|
|
|
};
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_suggestion(span, "use `crate`", sugg, app);
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-04-14 17:59:54 +00:00
|
|
|
BuiltinLintDiag::ProcMacroDeriveResolutionFallback { span, .. } => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(
|
2023-12-30 16:13:23 +01:00
|
|
|
span,
|
|
|
|
|
"names from parent modules are not accessible without an explicit import",
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_note(span_def, "the macro is defined here");
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => {
|
2024-04-20 13:21:15 +00:00
|
|
|
diag.subdiagnostic(
|
|
|
|
|
sess.dcx(),
|
|
|
|
|
elided_lifetime_in_path_suggestion(
|
|
|
|
|
sess.source_map(),
|
|
|
|
|
n,
|
|
|
|
|
path_span,
|
|
|
|
|
incl_angl_brckt,
|
|
|
|
|
insertion_span,
|
|
|
|
|
),
|
2023-12-30 16:13:23 +01:00
|
|
|
);
|
|
|
|
|
}
|
2024-04-14 20:11:14 +00:00
|
|
|
BuiltinLintDiag::UnknownCrateTypes { span, candidate } => {
|
|
|
|
|
if let Some(candidate) = candidate {
|
|
|
|
|
diag.span_suggestion(
|
|
|
|
|
span,
|
|
|
|
|
"did you mean",
|
|
|
|
|
format!(r#""{candidate}""#),
|
|
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-04-14 17:59:54 +00:00
|
|
|
BuiltinLintDiag::UnusedImports { fix_msg, fixes, test_module_span, .. } => {
|
|
|
|
|
if !fixes.is_empty() {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.tool_only_multipart_suggestion(
|
2024-04-14 17:59:54 +00:00
|
|
|
fix_msg,
|
|
|
|
|
fixes,
|
2023-12-30 16:13:23 +01:00
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-14 17:59:54 +00:00
|
|
|
if let Some(span) = test_module_span {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_help(
|
2023-12-30 16:13:23 +01:00
|
|
|
sess.source_map().guess_head_span(span),
|
2024-02-25 09:37:57 +02:00
|
|
|
"if this is a test module, consider adding a `#[cfg(test)]` to the containing module",
|
2023-12-30 16:13:23 +01:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::RedundantImport(spans, ident) => {
|
2023-12-30 16:13:23 +01:00
|
|
|
for (span, is_imported) in spans {
|
|
|
|
|
let introduced = if is_imported { "imported" } else { "defined" };
|
2024-03-23 17:30:44 +01:00
|
|
|
let span_msg = if span.is_dummy() { "by the extern prelude" } else { "here" };
|
2024-03-04 10:24:23 +08:00
|
|
|
diag.span_label(
|
|
|
|
|
span,
|
|
|
|
|
format!("the item `{ident}` is already {introduced} {span_msg}"),
|
|
|
|
|
);
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
|
|
|
|
}
|
2024-04-21 13:24:25 +00:00
|
|
|
BuiltinLintDiag::DeprecatedMacro {
|
|
|
|
|
suggestion,
|
|
|
|
|
suggestion_span,
|
|
|
|
|
note,
|
|
|
|
|
path,
|
|
|
|
|
since_kind,
|
|
|
|
|
} => {
|
|
|
|
|
let sub = suggestion.map(|suggestion| stability::DeprecationSuggestion {
|
|
|
|
|
span: suggestion_span,
|
|
|
|
|
kind: "macro".to_owned(),
|
|
|
|
|
suggestion,
|
|
|
|
|
});
|
|
|
|
|
let deprecated =
|
|
|
|
|
stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind };
|
|
|
|
|
deprecated.decorate_lint(diag);
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::UnusedDocComment(span) => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(span, "rustdoc does not generate documentation for macro invocations");
|
|
|
|
|
diag.help("to document an item produced by a macro, \
|
2023-12-30 16:13:23 +01:00
|
|
|
the macro must produce the documentation as part of its expansion");
|
|
|
|
|
}
|
2024-04-14 17:59:54 +00:00
|
|
|
BuiltinLintDiag::PatternsInFnsWithoutBody { span, ident, .. } => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_suggestion(
|
2023-12-30 16:13:23 +01:00
|
|
|
span,
|
|
|
|
|
"remove `mut` from the parameter",
|
|
|
|
|
ident,
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::MissingAbi(span, default_abi) => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(span, "ABI should be specified here");
|
|
|
|
|
diag.help(format!("the default ABI is {}", default_abi.name()));
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::LegacyDeriveHelpers(span) => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(span, "the attribute is introduced here");
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::ProcMacroBackCompat(note) => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.note(note);
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::OrPatternsBackCompat(span, suggestion) => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_suggestion(
|
2023-12-30 16:13:23 +01:00
|
|
|
span,
|
|
|
|
|
"use pat_param to preserve semantics",
|
|
|
|
|
suggestion,
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-04-14 17:59:54 +00:00
|
|
|
BuiltinLintDiag::ReservedPrefix(span, _) => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(span, "unknown prefix");
|
|
|
|
|
diag.span_suggestion_verbose(
|
2023-12-30 16:13:23 +01:00
|
|
|
span.shrink_to_hi(),
|
|
|
|
|
"insert whitespace here to avoid this being parsed as a prefix in Rust 2021",
|
|
|
|
|
" ",
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_note(
|
2023-12-30 16:13:23 +01:00
|
|
|
invoc_span,
|
|
|
|
|
format!("the built-in attribute `{attr_name}` will be ignored, since it's applied to the macro invocation `{macro_name}`")
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::TrailingMacro(is_trailing, name) => {
|
2023-12-30 16:13:23 +01:00
|
|
|
if is_trailing {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.note("macro invocations at the end of a block are treated as expressions");
|
|
|
|
|
diag.note(format!("to ignore the value produced by the macro, add a semicolon after the invocation of `{name}`"));
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
|
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::BreakWithLabelAndLoop(span) => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.multipart_suggestion(
|
2023-12-30 16:13:23 +01:00
|
|
|
"wrap this expression in parentheses",
|
|
|
|
|
vec![
|
|
|
|
|
(span.shrink_to_lo(), "(".to_string()),
|
|
|
|
|
(span.shrink_to_hi(), ")".to_string()),
|
|
|
|
|
],
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-03-16 23:33:54 +01:00
|
|
|
BuiltinLintDiag::UnexpectedCfgName(name, value) => {
|
|
|
|
|
check_cfg::unexpected_cfg_name(sess, diag, name, value)
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-03-16 23:33:54 +01:00
|
|
|
BuiltinLintDiag::UnexpectedCfgValue(name, value) => {
|
|
|
|
|
check_cfg::unexpected_cfg_value(sess, diag, name, value)
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg) => {
|
2024-02-20 04:41:01 +01:00
|
|
|
let left_sp = diag.span.primary_span().unwrap();
|
|
|
|
|
match sugg {
|
|
|
|
|
Some((right_sp, sugg)) => diag.multipart_suggestion(
|
|
|
|
|
"move it to the end of the type declaration",
|
|
|
|
|
vec![(left_sp, String::new()), (right_sp, sugg)],
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
),
|
|
|
|
|
None => diag.span_suggestion(
|
|
|
|
|
left_sp,
|
|
|
|
|
"remove this `where`",
|
|
|
|
|
"",
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
),
|
|
|
|
|
};
|
|
|
|
|
diag.note("see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information");
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::SingleUseLifetime {
|
2023-12-30 16:13:23 +01:00
|
|
|
param_span,
|
|
|
|
|
use_span: Some((use_span, elide)),
|
|
|
|
|
deletion_span,
|
2024-04-14 17:59:54 +00:00
|
|
|
..
|
2023-12-30 16:13:23 +01:00
|
|
|
} => {
|
|
|
|
|
debug!(?param_span, ?use_span, ?deletion_span);
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(param_span, "this lifetime...");
|
|
|
|
|
diag.span_label(use_span, "...is used only here");
|
2023-12-30 16:13:23 +01:00
|
|
|
if let Some(deletion_span) = deletion_span {
|
|
|
|
|
let msg = "elide the single-use lifetime";
|
|
|
|
|
let (use_span, replace_lt) = if elide {
|
2024-04-07 19:38:05 -04:00
|
|
|
let use_span = sess.source_map().span_extend_while_whitespace(use_span);
|
2023-12-30 16:13:23 +01:00
|
|
|
(use_span, String::new())
|
|
|
|
|
} else {
|
|
|
|
|
(use_span, "'_".to_owned())
|
|
|
|
|
};
|
|
|
|
|
debug!(?deletion_span, ?use_span);
|
|
|
|
|
|
|
|
|
|
// issue 107998 for the case such as a wrong function pointer type
|
|
|
|
|
// `deletion_span` is empty and there is no need to report lifetime uses here
|
|
|
|
|
let suggestions = if deletion_span.is_empty() {
|
|
|
|
|
vec![(use_span, replace_lt)]
|
|
|
|
|
} else {
|
|
|
|
|
vec![(deletion_span, String::new()), (use_span, replace_lt)]
|
|
|
|
|
};
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable);
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
|
|
|
|
}
|
2024-04-14 17:59:54 +00:00
|
|
|
BuiltinLintDiag::SingleUseLifetime {
|
|
|
|
|
param_span: _, use_span: None, deletion_span, ..
|
|
|
|
|
} => {
|
2023-12-30 16:13:23 +01:00
|
|
|
debug!(?deletion_span);
|
|
|
|
|
if let Some(deletion_span) = deletion_span {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_suggestion(
|
2023-12-30 16:13:23 +01:00
|
|
|
deletion_span,
|
|
|
|
|
"elide the unused lifetime",
|
|
|
|
|
"",
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::NamedArgumentUsedPositionally {
|
2023-12-30 16:13:23 +01:00
|
|
|
position_sp_to_replace,
|
|
|
|
|
position_sp_for_msg,
|
|
|
|
|
named_arg_sp,
|
|
|
|
|
named_arg_name,
|
|
|
|
|
is_formatting_arg,
|
|
|
|
|
} => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(
|
2023-12-30 16:13:23 +01:00
|
|
|
named_arg_sp,
|
|
|
|
|
"this named argument is referred to by position in formatting string",
|
|
|
|
|
);
|
|
|
|
|
if let Some(positional_arg_for_msg) = position_sp_for_msg {
|
|
|
|
|
let msg = format!(
|
|
|
|
|
"this formatting argument uses named argument `{named_arg_name}` by position"
|
|
|
|
|
);
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(positional_arg_for_msg, msg);
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some(positional_arg_to_replace) = position_sp_to_replace {
|
|
|
|
|
let name = if is_formatting_arg { named_arg_name + "$" } else { named_arg_name };
|
|
|
|
|
let span_to_replace = if let Ok(positional_arg_content) =
|
|
|
|
|
sess.source_map().span_to_snippet(positional_arg_to_replace)
|
|
|
|
|
&& positional_arg_content.starts_with(':')
|
|
|
|
|
{
|
|
|
|
|
positional_arg_to_replace.shrink_to_lo()
|
|
|
|
|
} else {
|
|
|
|
|
positional_arg_to_replace
|
|
|
|
|
};
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_suggestion_verbose(
|
2023-12-30 16:13:23 +01:00
|
|
|
span_to_replace,
|
|
|
|
|
"use the named argument by name to avoid ambiguity",
|
|
|
|
|
name,
|
|
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-04-14 17:59:54 +00:00
|
|
|
BuiltinLintDiag::ByteSliceInPackedStructWithDerive { .. } => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.help("consider implementing the trait by hand, or remove the `packed` attribute");
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::UnusedExternCrate { removal_span } => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_suggestion(removal_span, "remove it", "", Applicability::MachineApplicable);
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => {
|
2023-12-30 16:13:23 +01:00
|
|
|
let suggestion_span = vis_span.between(ident_span);
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_suggestion_verbose(
|
2023-12-30 16:13:23 +01:00
|
|
|
suggestion_span,
|
|
|
|
|
"convert it to a `use`",
|
|
|
|
|
if vis_span.is_empty() { "use " } else { " use " },
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => {
|
2024-02-23 10:20:45 +11:00
|
|
|
rustc_errors::report_ambiguity_error(diag, ambiguity);
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::AmbiguousGlobReexports {
|
2023-12-30 16:13:23 +01:00
|
|
|
name,
|
|
|
|
|
namespace,
|
|
|
|
|
first_reexport_span,
|
|
|
|
|
duplicate_reexport_span,
|
|
|
|
|
} => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(
|
2023-12-30 16:13:23 +01:00
|
|
|
first_reexport_span,
|
|
|
|
|
format!("the name `{name}` in the {namespace} namespace is first re-exported here"),
|
|
|
|
|
);
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_label(
|
2023-12-30 16:13:23 +01:00
|
|
|
duplicate_reexport_span,
|
|
|
|
|
format!(
|
|
|
|
|
"but the name `{name}` in the {namespace} namespace is also re-exported here"
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::HiddenGlobReexports {
|
2023-12-30 16:13:23 +01:00
|
|
|
name,
|
|
|
|
|
namespace,
|
|
|
|
|
glob_reexport_span,
|
|
|
|
|
private_item_span,
|
|
|
|
|
} => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_note(glob_reexport_span, format!("the name `{name}` in the {namespace} namespace is supposed to be publicly re-exported here"));
|
|
|
|
|
diag.span_note(private_item_span, "but the private item here shadows it".to_owned());
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::UnusedQualifications { removal_span } => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_suggestion_verbose(
|
2023-12-30 16:13:23 +01:00
|
|
|
removal_span,
|
|
|
|
|
"remove the unnecessary path segments",
|
|
|
|
|
"",
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span } => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_suggestion_verbose(
|
2023-12-30 16:13:23 +01:00
|
|
|
if elided { span.shrink_to_hi() } else { span },
|
|
|
|
|
"use the `'static` lifetime",
|
|
|
|
|
if elided { "'static " } else { "'static" },
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-04-14 17:59:54 +00:00
|
|
|
BuiltinLintDiag::RedundantImportVisibility { max_vis, span, .. } => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_note(span, format!("the most public imported item is `{max_vis}`"));
|
|
|
|
|
diag.help(
|
|
|
|
|
"reduce the glob import's visibility or increase visibility of imported items",
|
|
|
|
|
);
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
2024-04-14 20:11:14 +00:00
|
|
|
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,
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-05-15 00:49:33 +02:00
|
|
|
}
|
2024-04-14 20:11:14 +00:00
|
|
|
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 { .. } => {}
|
2023-12-30 16:13:23 +01:00
|
|
|
}
|
|
|
|
|
}
|
2024-04-14 17:59:54 +00:00
|
|
|
|
|
|
|
|
pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage {
|
|
|
|
|
match diagnostic {
|
|
|
|
|
BuiltinLintDiag::AbsPathWithModule(_) => {
|
|
|
|
|
"absolute paths must start with `self`, `super`, `crate`, or an \
|
|
|
|
|
external crate name in the 2018 edition"
|
|
|
|
|
.into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::ProcMacroDeriveResolutionFallback { ns, ident, .. } => {
|
|
|
|
|
format!("cannot find {} `{}` in this scope", ns.descr(), ident).into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(_) => {
|
|
|
|
|
"macro-expanded `macro_export` macros from the current crate cannot \
|
|
|
|
|
be referred to by absolute paths"
|
|
|
|
|
.into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::ElidedLifetimesInPaths(_, _, _, _) => {
|
|
|
|
|
"hidden lifetime parameters in types are deprecated".into()
|
|
|
|
|
}
|
2024-04-14 20:11:14 +00:00
|
|
|
BuiltinLintDiag::UnknownCrateTypes { .. } => "invalid `crate_type` value".into(),
|
2024-04-14 17:59:54 +00:00
|
|
|
BuiltinLintDiag::UnusedImports { span_snippets, .. } => format!(
|
|
|
|
|
"unused import{}{}",
|
|
|
|
|
pluralize!(span_snippets.len()),
|
|
|
|
|
if !span_snippets.is_empty() {
|
|
|
|
|
format!(": {}", span_snippets.join(", "))
|
|
|
|
|
} else {
|
|
|
|
|
String::new()
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
.into(),
|
|
|
|
|
BuiltinLintDiag::RedundantImport(_, source) => {
|
|
|
|
|
format!("the item `{source}` is imported redundantly").into()
|
|
|
|
|
}
|
2024-04-21 13:24:25 +00:00
|
|
|
BuiltinLintDiag::DeprecatedMacro { since_kind, .. } => {
|
|
|
|
|
stability::Deprecated::msg_for_since_kind(since_kind)
|
|
|
|
|
}
|
2024-04-14 17:59:54 +00:00
|
|
|
BuiltinLintDiag::MissingAbi(_, _) => crate::fluent_generated::lint_extern_without_abi,
|
|
|
|
|
BuiltinLintDiag::UnusedDocComment(_) => "unused doc comment".into(),
|
|
|
|
|
BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, .. } => {
|
|
|
|
|
format!("unused attribute `{attr_name}`").into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::PatternsInFnsWithoutBody { is_foreign, .. } => {
|
|
|
|
|
if *is_foreign {
|
|
|
|
|
crate::fluent_generated::lint_pattern_in_foreign
|
|
|
|
|
} else {
|
|
|
|
|
crate::fluent_generated::lint_pattern_in_bodiless
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::LegacyDeriveHelpers(_) => {
|
|
|
|
|
"derive helper attribute is used before it is introduced".into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::ProcMacroBackCompat(_) => "using an old version of `rental`".into(),
|
|
|
|
|
BuiltinLintDiag::OrPatternsBackCompat(_, _) => {
|
|
|
|
|
"the meaning of the `pat` fragment specifier is changing in Rust 2021, \
|
|
|
|
|
which may affect this macro"
|
|
|
|
|
.into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::ReservedPrefix(_, prefix) => {
|
|
|
|
|
format!("prefix `{prefix}` is unknown").into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::TrailingMacro(_, _) => {
|
|
|
|
|
"trailing semicolon in macro used in expression position".into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::BreakWithLabelAndLoop(_) => {
|
|
|
|
|
"this labeled break expression is easy to confuse with an unlabeled break with a \
|
|
|
|
|
labeled value expression"
|
|
|
|
|
.into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::UnicodeTextFlow(_, _) => {
|
|
|
|
|
"unicode codepoint changing visible direction of text present in comment".into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::UnexpectedCfgName((name, _), _) => {
|
|
|
|
|
format!("unexpected `cfg` condition name: `{}`", name).into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::UnexpectedCfgValue(_, v) => if let Some((value, _)) = v {
|
|
|
|
|
format!("unexpected `cfg` condition value: `{value}`")
|
|
|
|
|
} else {
|
|
|
|
|
format!("unexpected `cfg` condition value: (none)")
|
|
|
|
|
}
|
|
|
|
|
.into(),
|
|
|
|
|
BuiltinLintDiag::DeprecatedWhereclauseLocation(_) => {
|
|
|
|
|
crate::fluent_generated::lint_deprecated_where_clause_location
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::SingleUseLifetime { use_span, ident, .. } => {
|
|
|
|
|
if use_span.is_some() {
|
|
|
|
|
format!("lifetime parameter `{}` only used once", ident).into()
|
|
|
|
|
} else {
|
|
|
|
|
format!("lifetime parameter `{}` never used", ident).into()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::NamedArgumentUsedPositionally { named_arg_name, .. } => {
|
|
|
|
|
format!("named argument `{}` is not used by name", named_arg_name).into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => {
|
|
|
|
|
format!("{ty} slice in a packed struct that derives a built-in trait").into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::UnusedExternCrate { .. } => "unused extern crate".into(),
|
|
|
|
|
BuiltinLintDiag::ExternCrateNotIdiomatic { .. } => {
|
|
|
|
|
"`extern crate` is not idiomatic in the new edition".into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::AmbiguousGlobImports { diag } => diag.msg.clone().into(),
|
|
|
|
|
BuiltinLintDiag::AmbiguousGlobReexports { .. } => "ambiguous glob re-exports".into(),
|
|
|
|
|
BuiltinLintDiag::HiddenGlobReexports { .. } => {
|
|
|
|
|
"private item shadows public glob re-export".into()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::UnusedQualifications { .. } => "unnecessary qualification".into(),
|
|
|
|
|
BuiltinLintDiag::AssociatedConstElidedLifetime { elided, .. } => if *elided {
|
|
|
|
|
"`&` without an explicit lifetime name cannot be used here"
|
|
|
|
|
} else {
|
|
|
|
|
"`'_` cannot be used here"
|
|
|
|
|
}
|
|
|
|
|
.into(),
|
|
|
|
|
BuiltinLintDiag::RedundantImportVisibility { import_vis, .. } => format!(
|
|
|
|
|
"glob import doesn't reexport anything with visibility `{}` \
|
|
|
|
|
because no imported item is public enough",
|
|
|
|
|
import_vis
|
|
|
|
|
)
|
|
|
|
|
.into(),
|
2024-04-14 20:11:14 +00:00
|
|
|
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(),
|
2024-04-14 17:59:54 +00:00
|
|
|
}
|
|
|
|
|
}
|