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-03-16 23:33:54 +01:00
|
|
|
mod check_cfg;
|
2024-02-16 21:32:53 +01:00
|
|
|
|
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-04-14 17:59:54 +00:00
|
|
|
BuiltinLintDiag::Normal(_) => (),
|
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-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::UnknownCrateTypes(span, note, sugg) => {
|
2024-02-23 10:20:45 +11:00
|
|
|
diag.span_suggestion(span, note, sugg, 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-05-15 00:49:33 +02:00
|
|
|
BuiltinLintDiag::MaybeTypo { span, name } => {
|
|
|
|
|
diag.span_suggestion_verbose(
|
|
|
|
|
span,
|
|
|
|
|
"an attribute with a similar name exists",
|
|
|
|
|
name,
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
}
|
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::Normal(msg) => msg.clone(),
|
|
|
|
|
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()
|
|
|
|
|
}
|
|
|
|
|
BuiltinLintDiag::UnknownCrateTypes(_, _, _) => "invalid `crate_type` value".into(),
|
|
|
|
|
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(),
|
|
|
|
|
}
|
|
|
|
|
}
|