Auto merge of #101986 - WaffleLapkin:move_lint_note_to_the_bottom, r=estebank
Move lint level source explanation to the bottom So, uhhhhh r? `@estebank` ## User-facing change "note: `#[warn(...)]` on by default" and such are moved to the bottom of the diagnostic: ```diff - = note: `#[warn(unsupported_calling_conventions)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678> + = note: `#[warn(unsupported_calling_conventions)]` on by default ``` Why warning is enabled is the least important thing, so it shouldn't be the first note the user reads, IMO. ## Developer-facing change `struct_span_lint` and similar methods have a different signature. Before: `..., impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>)` After: `..., impl Into<DiagnosticMessage>, impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>) -> &'b mut DiagnosticBuilder<'a, ()>` The reason for this is that `struct_span_lint` needs to edit the diagnostic _after_ `decorate` closure is called. This also makes lint code a little bit nicer in my opinion. Another option is to use `impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>) -> DiagnosticBuilder<'a, ()>` altough I don't _really_ see reasons to do `let lint = lint.build(message)` everywhere. ## Subtle problem By moving the message outside of the closure (that may not be called if the lint is disabled) `format!(...)` is executed earlier, possibly formatting `Ty` which may call a query that trims paths that crashes the compiler if there were no warnings... I don't think it's that big of a deal, considering that we move from `format!(...)` to `fluent` (which is lazy by-default) anyway, however this required adding a workaround which is unfortunate. ## P.S. I'm sorry, I do not how to make this PR smaller/easier to review. Changes to the lint API affect SO MUCH 😢
This commit is contained in:
commit
744e397d88
827 changed files with 3370 additions and 3210 deletions
|
@ -118,37 +118,41 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
|
|||
// to an array or to a slice.
|
||||
_ => bug!("array type coerced to something other than array or slice"),
|
||||
};
|
||||
cx.struct_span_lint(ARRAY_INTO_ITER, call.ident.span, |lint| {
|
||||
let mut diag = lint.build(fluent::lint::array_into_iter);
|
||||
diag.set_arg("target", target);
|
||||
diag.span_suggestion(
|
||||
call.ident.span,
|
||||
fluent::lint::use_iter_suggestion,
|
||||
"iter",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if self.for_expr_span == expr.span {
|
||||
cx.struct_span_lint(
|
||||
ARRAY_INTO_ITER,
|
||||
call.ident.span,
|
||||
fluent::lint::array_into_iter,
|
||||
|diag| {
|
||||
diag.set_arg("target", target);
|
||||
diag.span_suggestion(
|
||||
receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
fluent::lint::remove_into_iter_suggestion,
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
call.ident.span,
|
||||
fluent::lint::use_iter_suggestion,
|
||||
"iter",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if receiver_ty.is_array() {
|
||||
diag.multipart_suggestion(
|
||||
fluent::lint::use_explicit_into_iter_suggestion,
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()),
|
||||
(
|
||||
receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
")".into(),
|
||||
),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
diag.emit();
|
||||
})
|
||||
if self.for_expr_span == expr.span {
|
||||
diag.span_suggestion(
|
||||
receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
fluent::lint::remove_into_iter_suggestion,
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else if receiver_ty.is_array() {
|
||||
diag.multipart_suggestion(
|
||||
fluent::lint::use_explicit_into_iter_suggestion,
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()),
|
||||
(
|
||||
receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
")".into(),
|
||||
),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
diag
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ use rustc_ast_pretty::pprust::{self, expr_to_string};
|
|||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::{
|
||||
fluent, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
|
||||
LintDiagnosticBuilder, MultiSpan,
|
||||
fluent, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, DiagnosticMessage,
|
||||
DiagnosticStyledString, MultiSpan,
|
||||
};
|
||||
use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
|
||||
use rustc_hir as hir;
|
||||
|
@ -103,9 +103,12 @@ impl EarlyLintPass for WhileTrue {
|
|||
&& !lit.span.from_expansion()
|
||||
{
|
||||
let condition_span = e.span.with_hi(cond.span.hi());
|
||||
cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| {
|
||||
lint.build(fluent::lint::builtin_while_true)
|
||||
.span_suggestion_short(
|
||||
cx.struct_span_lint(
|
||||
WHILE_TRUE,
|
||||
condition_span,
|
||||
fluent::lint::builtin_while_true,
|
||||
|lint| {
|
||||
lint.span_suggestion_short(
|
||||
condition_span,
|
||||
fluent::lint::suggestion,
|
||||
format!(
|
||||
|
@ -117,8 +120,8 @@ impl EarlyLintPass for WhileTrue {
|
|||
),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,9 +157,12 @@ impl BoxPointers {
|
|||
for leaf in ty.walk() {
|
||||
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
|
||||
if leaf_ty.is_box() {
|
||||
cx.struct_span_lint(BOX_POINTERS, span, |lint| {
|
||||
lint.build(fluent::lint::builtin_box_pointers).set_arg("ty", ty).emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
BOX_POINTERS,
|
||||
span,
|
||||
fluent::lint::builtin_box_pointers,
|
||||
|lint| lint.set_arg("ty", ty),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -255,19 +261,21 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
|
|||
if cx.tcx.find_field_index(ident, &variant)
|
||||
== Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
|
||||
{
|
||||
cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, |lint| {
|
||||
let suggested_ident =
|
||||
format!("{}{}", binding_annot.prefix_str(), ident);
|
||||
lint.build(fluent::lint::builtin_non_shorthand_field_patterns)
|
||||
.set_arg("ident", ident.clone())
|
||||
.span_suggestion(
|
||||
cx.struct_span_lint(
|
||||
NON_SHORTHAND_FIELD_PATTERNS,
|
||||
fieldpat.span,
|
||||
fluent::lint::builtin_non_shorthand_field_patterns,
|
||||
|lint| {
|
||||
let suggested_ident =
|
||||
format!("{}{}", binding_annot.prefix_str(), ident);
|
||||
lint.set_arg("ident", ident.clone()).span_suggestion(
|
||||
fieldpat.span,
|
||||
fluent::lint::suggestion,
|
||||
suggested_ident,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -307,14 +315,17 @@ impl UnsafeCode {
|
|||
&self,
|
||||
cx: &EarlyContext<'_>,
|
||||
span: Span,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
) {
|
||||
// This comes from a macro that has `#[allow_internal_unsafe]`.
|
||||
if span.allows_unsafe() {
|
||||
return;
|
||||
}
|
||||
|
||||
cx.struct_span_lint(UNSAFE_CODE, span, decorate);
|
||||
cx.struct_span_lint(UNSAFE_CODE, span, msg, decorate);
|
||||
}
|
||||
|
||||
fn report_overridden_symbol_name(
|
||||
|
@ -323,8 +334,8 @@ impl UnsafeCode {
|
|||
span: Span,
|
||||
msg: DiagnosticMessage,
|
||||
) {
|
||||
self.report_unsafe(cx, span, |lint| {
|
||||
lint.build(msg).note(fluent::lint::builtin_overridden_symbol_name).emit();
|
||||
self.report_unsafe(cx, span, msg, |lint| {
|
||||
lint.note(fluent::lint::builtin_overridden_symbol_name)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -334,8 +345,8 @@ impl UnsafeCode {
|
|||
span: Span,
|
||||
msg: DiagnosticMessage,
|
||||
) {
|
||||
self.report_unsafe(cx, span, |lint| {
|
||||
lint.build(msg).note(fluent::lint::builtin_overridden_symbol_section).emit();
|
||||
self.report_unsafe(cx, span, msg, |lint| {
|
||||
lint.note(fluent::lint::builtin_overridden_symbol_section)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -343,9 +354,12 @@ impl UnsafeCode {
|
|||
impl EarlyLintPass for UnsafeCode {
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
|
||||
if attr.has_name(sym::allow_internal_unsafe) {
|
||||
self.report_unsafe(cx, attr.span, |lint| {
|
||||
lint.build(fluent::lint::builtin_allow_internal_unsafe).emit();
|
||||
});
|
||||
self.report_unsafe(
|
||||
cx,
|
||||
attr.span,
|
||||
fluent::lint::builtin_allow_internal_unsafe,
|
||||
|lint| lint,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,24 +367,20 @@ impl EarlyLintPass for UnsafeCode {
|
|||
if let ast::ExprKind::Block(ref blk, _) = e.kind {
|
||||
// Don't warn about generated blocks; that'll just pollute the output.
|
||||
if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
|
||||
self.report_unsafe(cx, blk.span, |lint| {
|
||||
lint.build(fluent::lint::builtin_unsafe_block).emit();
|
||||
});
|
||||
self.report_unsafe(cx, blk.span, fluent::lint::builtin_unsafe_block, |lint| lint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
|
||||
match it.kind {
|
||||
ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
|
||||
.report_unsafe(cx, it.span, |lint| {
|
||||
lint.build(fluent::lint::builtin_unsafe_trait).emit();
|
||||
}),
|
||||
ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => {
|
||||
self.report_unsafe(cx, it.span, fluent::lint::builtin_unsafe_trait, |lint| lint)
|
||||
}
|
||||
|
||||
ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
|
||||
.report_unsafe(cx, it.span, |lint| {
|
||||
lint.build(fluent::lint::builtin_unsafe_impl).emit();
|
||||
}),
|
||||
ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => {
|
||||
self.report_unsafe(cx, it.span, fluent::lint::builtin_unsafe_impl, |lint| lint)
|
||||
}
|
||||
|
||||
ast::ItemKind::Fn(..) => {
|
||||
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
|
||||
|
@ -463,9 +473,7 @@ impl EarlyLintPass for UnsafeCode {
|
|||
FnCtxt::Assoc(_) if body.is_none() => fluent::lint::builtin_decl_unsafe_method,
|
||||
FnCtxt::Assoc(_) => fluent::lint::builtin_impl_unsafe_method,
|
||||
};
|
||||
self.report_unsafe(cx, span, |lint| {
|
||||
lint.build(msg).emit();
|
||||
});
|
||||
self.report_unsafe(cx, span, msg, |lint| lint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -566,12 +574,12 @@ impl MissingDoc {
|
|||
let attrs = cx.tcx.hir().attrs(cx.tcx.hir().local_def_id_to_hir_id(def_id));
|
||||
let has_doc = attrs.iter().any(has_doc);
|
||||
if !has_doc {
|
||||
cx.struct_span_lint(MISSING_DOCS, cx.tcx.def_span(def_id), |lint| {
|
||||
lint.build(fluent::lint::builtin_missing_doc)
|
||||
.set_arg("article", article)
|
||||
.set_arg("desc", desc)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
MISSING_DOCS,
|
||||
cx.tcx.def_span(def_id),
|
||||
fluent::lint::builtin_missing_doc,
|
||||
|lint| lint.set_arg("article", article).set_arg("desc", desc),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -758,9 +766,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
|
|||
)
|
||||
.is_ok()
|
||||
{
|
||||
cx.struct_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, |lint| {
|
||||
lint.build(fluent::lint::builtin_missing_copy_impl).emit();
|
||||
})
|
||||
cx.struct_span_lint(
|
||||
MISSING_COPY_IMPLEMENTATIONS,
|
||||
item.span,
|
||||
fluent::lint::builtin_missing_copy_impl,
|
||||
|lint| lint,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -834,11 +845,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
|
|||
}
|
||||
|
||||
if !self.impling_types.as_ref().unwrap().contains(&item.def_id.def_id) {
|
||||
cx.struct_span_lint(MISSING_DEBUG_IMPLEMENTATIONS, item.span, |lint| {
|
||||
lint.build(fluent::lint::builtin_missing_debug_impl)
|
||||
.set_arg("debug", cx.tcx.def_path_str(debug))
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
MISSING_DEBUG_IMPLEMENTATIONS,
|
||||
item.span,
|
||||
fluent::lint::builtin_missing_debug_impl,
|
||||
|lint| lint.set_arg("debug", cx.tcx.def_path_str(debug)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -906,24 +918,26 @@ impl EarlyLintPass for AnonymousParameters {
|
|||
for arg in sig.decl.inputs.iter() {
|
||||
if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind {
|
||||
if ident.name == kw::Empty {
|
||||
cx.struct_span_lint(ANONYMOUS_PARAMETERS, arg.pat.span, |lint| {
|
||||
let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);
|
||||
let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);
|
||||
|
||||
let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
|
||||
(snip.as_str(), Applicability::MachineApplicable)
|
||||
} else {
|
||||
("<type>", Applicability::HasPlaceholders)
|
||||
};
|
||||
|
||||
lint.build(fluent::lint::builtin_anonymous_params)
|
||||
.span_suggestion(
|
||||
let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
|
||||
(snip.as_str(), Applicability::MachineApplicable)
|
||||
} else {
|
||||
("<type>", Applicability::HasPlaceholders)
|
||||
};
|
||||
cx.struct_span_lint(
|
||||
ANONYMOUS_PARAMETERS,
|
||||
arg.pat.span,
|
||||
fluent::lint::builtin_anonymous_params,
|
||||
|lint| {
|
||||
lint.span_suggestion(
|
||||
arg.pat.span,
|
||||
fluent::lint::suggestion,
|
||||
format!("_: {}", ty_snip),
|
||||
appl,
|
||||
)
|
||||
.emit();
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -958,38 +972,44 @@ impl EarlyLintPass for DeprecatedAttr {
|
|||
_,
|
||||
) = gate
|
||||
{
|
||||
cx.struct_span_lint(DEPRECATED, attr.span, |lint| {
|
||||
// FIXME(davidtwco) translatable deprecated attr
|
||||
lint.build(fluent::lint::builtin_deprecated_attr_link)
|
||||
.set_arg("name", name)
|
||||
.set_arg("reason", reason)
|
||||
.set_arg("link", link)
|
||||
.span_suggestion_short(
|
||||
attr.span,
|
||||
suggestion.map(|s| s.into()).unwrap_or(
|
||||
fluent::lint::builtin_deprecated_attr_default_suggestion,
|
||||
),
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
// FIXME(davidtwco) translatable deprecated attr
|
||||
cx.struct_span_lint(
|
||||
DEPRECATED,
|
||||
attr.span,
|
||||
fluent::lint::builtin_deprecated_attr_link,
|
||||
|lint| {
|
||||
lint.set_arg("name", name)
|
||||
.set_arg("reason", reason)
|
||||
.set_arg("link", link)
|
||||
.span_suggestion_short(
|
||||
attr.span,
|
||||
suggestion.map(|s| s.into()).unwrap_or(
|
||||
fluent::lint::builtin_deprecated_attr_default_suggestion,
|
||||
),
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) {
|
||||
cx.struct_span_lint(DEPRECATED, attr.span, |lint| {
|
||||
lint.build(fluent::lint::builtin_deprecated_attr_used)
|
||||
.set_arg("name", pprust::path_to_string(&attr.get_normal_item().path))
|
||||
.span_suggestion_short(
|
||||
attr.span,
|
||||
fluent::lint::builtin_deprecated_attr_default_suggestion,
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
DEPRECATED,
|
||||
attr.span,
|
||||
fluent::lint::builtin_deprecated_attr_used,
|
||||
|lint| {
|
||||
lint.set_arg("name", pprust::path_to_string(&attr.get_normal_item().path))
|
||||
.span_suggestion_short(
|
||||
attr.span,
|
||||
fluent::lint::builtin_deprecated_attr_default_suggestion,
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1016,20 +1036,21 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
|
|||
let span = sugared_span.take().unwrap_or(attr.span);
|
||||
|
||||
if is_doc_comment || attr.has_name(sym::doc) {
|
||||
cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {
|
||||
let mut err = lint.build(fluent::lint::builtin_unused_doc_comment);
|
||||
err.set_arg("kind", node_kind);
|
||||
err.span_label(node_span, fluent::lint::label);
|
||||
match attr.kind {
|
||||
AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
|
||||
err.help(fluent::lint::plain_help);
|
||||
}
|
||||
AttrKind::DocComment(CommentKind::Block, _) => {
|
||||
err.help(fluent::lint::block_help);
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
UNUSED_DOC_COMMENTS,
|
||||
span,
|
||||
fluent::lint::builtin_unused_doc_comment,
|
||||
|lint| {
|
||||
lint.set_arg("kind", node_kind).span_label(node_span, fluent::lint::label).help(
|
||||
match attr.kind {
|
||||
AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
|
||||
fluent::lint::plain_help
|
||||
}
|
||||
AttrKind::DocComment(CommentKind::Block, _) => fluent::lint::block_help,
|
||||
},
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1143,9 +1164,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
|
|||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
|
||||
cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, span, |lint| {
|
||||
lint.build(fluent::lint::builtin_no_mangle_generic)
|
||||
.span_suggestion_short(
|
||||
cx.struct_span_lint(
|
||||
NO_MANGLE_GENERIC_ITEMS,
|
||||
span,
|
||||
fluent::lint::builtin_no_mangle_generic,
|
||||
|lint| {
|
||||
lint.span_suggestion_short(
|
||||
no_mangle_attr.span,
|
||||
fluent::lint::suggestion,
|
||||
"",
|
||||
|
@ -1153,8 +1177,8 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
|
|||
// fix may be to monomorphize source by hand
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
},
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1170,27 +1194,29 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
|
|||
if cx.sess().contains_name(attrs, sym::no_mangle) {
|
||||
// Const items do not refer to a particular location in memory, and therefore
|
||||
// don't have anything to attach a symbol to
|
||||
cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, |lint| {
|
||||
let mut err = lint.build(fluent::lint::builtin_const_no_mangle);
|
||||
|
||||
// account for "pub const" (#45562)
|
||||
let start = cx
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_snippet(it.span)
|
||||
.map(|snippet| snippet.find("const").unwrap_or(0))
|
||||
.unwrap_or(0) as u32;
|
||||
// `const` is 5 chars
|
||||
let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
|
||||
err.span_suggestion(
|
||||
const_span,
|
||||
fluent::lint::suggestion,
|
||||
"pub static",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
NO_MANGLE_CONST_ITEMS,
|
||||
it.span,
|
||||
fluent::lint::builtin_const_no_mangle,
|
||||
|lint| {
|
||||
// account for "pub const" (#45562)
|
||||
let start = cx
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_snippet(it.span)
|
||||
.map(|snippet| snippet.find("const").unwrap_or(0))
|
||||
.unwrap_or(0) as u32;
|
||||
// `const` is 5 chars
|
||||
let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
|
||||
lint.span_suggestion(
|
||||
const_span,
|
||||
fluent::lint::suggestion,
|
||||
"pub static",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
hir::ItemKind::Impl(hir::Impl { generics, items, .. }) => {
|
||||
|
@ -1250,9 +1276,12 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
|
|||
get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
|
||||
{
|
||||
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
|
||||
cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| {
|
||||
lint.build(fluent::lint::builtin_mutable_transmutes).emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
MUTABLE_TRANSMUTES,
|
||||
expr.span,
|
||||
fluent::lint::builtin_mutable_transmutes,
|
||||
|lint| lint,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1300,9 +1329,12 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
|
|||
if attr.has_name(sym::feature) {
|
||||
if let Some(items) = attr.meta_item_list() {
|
||||
for item in items {
|
||||
cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| {
|
||||
lint.build(fluent::lint::builtin_unstable_features).emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
UNSTABLE_FEATURES,
|
||||
item.span(),
|
||||
fluent::lint::builtin_unstable_features,
|
||||
|lint| lint,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1361,21 +1393,25 @@ impl UnreachablePub {
|
|||
applicability = Applicability::MaybeIncorrect;
|
||||
}
|
||||
let def_span = cx.tcx.def_span(def_id);
|
||||
cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| {
|
||||
let mut err = lint.build(fluent::lint::builtin_unreachable_pub);
|
||||
err.set_arg("what", what);
|
||||
cx.struct_span_lint(
|
||||
UNREACHABLE_PUB,
|
||||
def_span,
|
||||
fluent::lint::builtin_unreachable_pub,
|
||||
|lint| {
|
||||
lint.set_arg("what", what);
|
||||
|
||||
err.span_suggestion(
|
||||
vis_span,
|
||||
fluent::lint::suggestion,
|
||||
"pub(crate)",
|
||||
applicability,
|
||||
);
|
||||
if exportable {
|
||||
err.help(fluent::lint::help);
|
||||
}
|
||||
err.emit();
|
||||
});
|
||||
lint.span_suggestion(
|
||||
vis_span,
|
||||
fluent::lint::suggestion,
|
||||
"pub(crate)",
|
||||
applicability,
|
||||
);
|
||||
if exportable {
|
||||
lint.help(fluent::lint::help);
|
||||
}
|
||||
lint
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1505,36 +1541,34 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
|
|||
|
||||
let mut suggested_changing_assoc_types = false;
|
||||
if !where_spans.is_empty() {
|
||||
cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
|
||||
let mut err = lint.build(fluent::lint::builtin_type_alias_where_clause);
|
||||
err.set_span(where_spans);
|
||||
err.span_suggestion(
|
||||
cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint::builtin_type_alias_where_clause, |lint| {
|
||||
lint.set_span(where_spans);
|
||||
lint.span_suggestion(
|
||||
type_alias_generics.where_clause_span,
|
||||
fluent::lint::suggestion,
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if !suggested_changing_assoc_types {
|
||||
TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
|
||||
TypeAliasBounds::suggest_changing_assoc_types(ty, lint);
|
||||
suggested_changing_assoc_types = true;
|
||||
}
|
||||
err.emit();
|
||||
lint
|
||||
});
|
||||
}
|
||||
|
||||
if !inline_spans.is_empty() {
|
||||
cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
|
||||
let mut err = lint.build(fluent::lint::builtin_type_alias_generic_bounds);
|
||||
err.set_span(inline_spans);
|
||||
err.multipart_suggestion(
|
||||
cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint::builtin_type_alias_generic_bounds, |lint| {
|
||||
lint.set_span(inline_spans);
|
||||
lint.multipart_suggestion(
|
||||
fluent::lint::suggestion,
|
||||
inline_sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if !suggested_changing_assoc_types {
|
||||
TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
|
||||
TypeAliasBounds::suggest_changing_assoc_types(ty, lint);
|
||||
}
|
||||
err.emit();
|
||||
lint
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1633,12 +1667,15 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
|
|||
TypeWellFormedFromEnv(..) => continue,
|
||||
};
|
||||
if predicate.is_global() {
|
||||
cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {
|
||||
lint.build(fluent::lint::builtin_trivial_bounds)
|
||||
.set_arg("predicate_kind_name", predicate_kind_name)
|
||||
.set_arg("predicate", predicate)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
TRIVIAL_BOUNDS,
|
||||
span,
|
||||
fluent::lint::builtin_trivial_bounds,
|
||||
|lint| {
|
||||
lint.set_arg("predicate_kind_name", predicate_kind_name)
|
||||
.set_arg("predicate", predicate)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1754,15 +1791,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
|
|||
replace,
|
||||
});
|
||||
} else {
|
||||
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, |lint| {
|
||||
lint.build(msg)
|
||||
.span_suggestion(
|
||||
pat.span,
|
||||
suggestion,
|
||||
replace,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg, |lint| {
|
||||
lint.span_suggestion(
|
||||
pat.span,
|
||||
suggestion,
|
||||
replace,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
@ -1774,15 +1809,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
|
|||
replace: replace.to_string(),
|
||||
});
|
||||
} else {
|
||||
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, |lint| {
|
||||
lint.build(msg)
|
||||
.span_suggestion_short(
|
||||
join,
|
||||
suggestion,
|
||||
replace,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg, |lint| {
|
||||
lint.span_suggestion_short(
|
||||
join,
|
||||
suggestion,
|
||||
replace,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1863,9 +1896,12 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
|
|||
|
||||
let attrs = cx.tcx.hir().attrs(it.hir_id());
|
||||
if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) {
|
||||
cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| {
|
||||
lint.build(fluent::lint::builtin_unnameable_test_items).emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
UNNAMEABLE_TEST_ITEMS,
|
||||
attr.span,
|
||||
fluent::lint::builtin_unnameable_test_items,
|
||||
|lint| lint,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1981,18 +2017,19 @@ impl KeywordIdents {
|
|||
return;
|
||||
}
|
||||
|
||||
cx.struct_span_lint(KEYWORD_IDENTS, ident.span, |lint| {
|
||||
lint.build(fluent::lint::builtin_keyword_idents)
|
||||
.set_arg("kw", ident.clone())
|
||||
.set_arg("next", next_edition)
|
||||
.span_suggestion(
|
||||
cx.struct_span_lint(
|
||||
KEYWORD_IDENTS,
|
||||
ident.span,
|
||||
fluent::lint::builtin_keyword_idents,
|
||||
|lint| {
|
||||
lint.set_arg("kw", ident.clone()).set_arg("next", next_edition).span_suggestion(
|
||||
ident.span,
|
||||
fluent::lint::suggestion,
|
||||
format!("r#{}", ident),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2243,10 +2280,12 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
|||
}
|
||||
|
||||
if !lint_spans.is_empty() {
|
||||
cx.struct_span_lint(EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), |lint| {
|
||||
lint.build(fluent::lint::builtin_explicit_outlives)
|
||||
.set_arg("count", bound_count)
|
||||
.multipart_suggestion(
|
||||
cx.struct_span_lint(
|
||||
EXPLICIT_OUTLIVES_REQUIREMENTS,
|
||||
lint_spans.clone(),
|
||||
fluent::lint::builtin_explicit_outlives,
|
||||
|lint| {
|
||||
lint.set_arg("count", bound_count).multipart_suggestion(
|
||||
fluent::lint::suggestion,
|
||||
lint_spans
|
||||
.into_iter()
|
||||
|
@ -2254,8 +2293,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
|||
.collect::<Vec<_>>(),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2302,18 +2341,24 @@ impl EarlyLintPass for IncompleteFeatures {
|
|||
.chain(features.declared_lib_features.iter().map(|(name, span)| (name, span)))
|
||||
.filter(|(&name, _)| features.incomplete(name))
|
||||
.for_each(|(&name, &span)| {
|
||||
cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| {
|
||||
let mut builder = lint.build(fluent::lint::builtin_incomplete_features);
|
||||
builder.set_arg("name", name);
|
||||
if let Some(n) = rustc_feature::find_feature_issue(name, GateIssue::Language) {
|
||||
builder.set_arg("n", n);
|
||||
builder.note(fluent::lint::note);
|
||||
}
|
||||
if HAS_MIN_FEATURES.contains(&name) {
|
||||
builder.help(fluent::lint::help);
|
||||
}
|
||||
builder.emit();
|
||||
})
|
||||
cx.struct_span_lint(
|
||||
INCOMPLETE_FEATURES,
|
||||
span,
|
||||
fluent::lint::builtin_incomplete_features,
|
||||
|lint| {
|
||||
lint.set_arg("name", name);
|
||||
if let Some(n) =
|
||||
rustc_feature::find_feature_issue(name, GateIssue::Language)
|
||||
{
|
||||
lint.set_arg("n", n);
|
||||
lint.note(fluent::lint::note);
|
||||
}
|
||||
if HAS_MIN_FEATURES.contains(&name) {
|
||||
lint.help(fluent::lint::help);
|
||||
}
|
||||
lint
|
||||
},
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2628,28 +2673,37 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||
with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init))
|
||||
{
|
||||
// FIXME(davidtwco): make translatable
|
||||
cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| {
|
||||
let mut err = lint.build(&format!(
|
||||
"the type `{}` does not permit {}",
|
||||
conjured_ty,
|
||||
match init {
|
||||
InitKind::Zeroed => "zero-initialization",
|
||||
InitKind::Uninit => "being left uninitialized",
|
||||
},
|
||||
));
|
||||
err.span_label(expr.span, "this code causes undefined behavior when executed");
|
||||
err.span_label(
|
||||
expr.span,
|
||||
"help: use `MaybeUninit<T>` instead, \
|
||||
cx.struct_span_lint(
|
||||
INVALID_VALUE,
|
||||
expr.span,
|
||||
DelayDm(|| {
|
||||
format!(
|
||||
"the type `{}` does not permit {}",
|
||||
conjured_ty,
|
||||
match init {
|
||||
InitKind::Zeroed => "zero-initialization",
|
||||
InitKind::Uninit => "being left uninitialized",
|
||||
},
|
||||
)
|
||||
}),
|
||||
|lint| {
|
||||
lint.span_label(
|
||||
expr.span,
|
||||
"this code causes undefined behavior when executed",
|
||||
);
|
||||
lint.span_label(
|
||||
expr.span,
|
||||
"help: use `MaybeUninit<T>` instead, \
|
||||
and only call `assume_init` after initialization is done",
|
||||
);
|
||||
if let Some(span) = span {
|
||||
err.span_note(span, &msg);
|
||||
} else {
|
||||
err.note(&msg);
|
||||
}
|
||||
err.emit();
|
||||
});
|
||||
);
|
||||
if let Some(span) = span {
|
||||
lint.span_note(span, &msg);
|
||||
} else {
|
||||
lint.note(&msg);
|
||||
}
|
||||
lint
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2995,31 +3049,35 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
|
|||
SymbolName::Link(_, annot_span) => fi.span.to(annot_span),
|
||||
};
|
||||
// Finally, emit the diagnostic.
|
||||
|
||||
let msg = if orig.get_name() == this_fi.ident.name {
|
||||
fluent::lint::builtin_clashing_extern_same_name
|
||||
} else {
|
||||
fluent::lint::builtin_clashing_extern_diff_name
|
||||
};
|
||||
tcx.struct_span_lint_hir(
|
||||
CLASHING_EXTERN_DECLARATIONS,
|
||||
this_fi.hir_id(),
|
||||
get_relevant_span(this_fi),
|
||||
msg,
|
||||
|lint| {
|
||||
let mut expected_str = DiagnosticStyledString::new();
|
||||
expected_str.push(existing_decl_ty.fn_sig(tcx).to_string(), false);
|
||||
let mut found_str = DiagnosticStyledString::new();
|
||||
found_str.push(this_decl_ty.fn_sig(tcx).to_string(), true);
|
||||
|
||||
lint.build(if orig.get_name() == this_fi.ident.name {
|
||||
fluent::lint::builtin_clashing_extern_same_name
|
||||
} else {
|
||||
fluent::lint::builtin_clashing_extern_diff_name
|
||||
})
|
||||
.set_arg("this_fi", this_fi.ident.name)
|
||||
.set_arg("orig", orig.get_name())
|
||||
.span_label(
|
||||
get_relevant_span(orig_fi),
|
||||
fluent::lint::previous_decl_label,
|
||||
)
|
||||
.span_label(get_relevant_span(this_fi), fluent::lint::mismatch_label)
|
||||
// FIXME(davidtwco): translatable expected/found
|
||||
.note_expected_found(&"", expected_str, &"", found_str)
|
||||
.emit();
|
||||
lint.set_arg("this_fi", this_fi.ident.name)
|
||||
.set_arg("orig", orig.get_name())
|
||||
.span_label(
|
||||
get_relevant_span(orig_fi),
|
||||
fluent::lint::previous_decl_label,
|
||||
)
|
||||
.span_label(
|
||||
get_relevant_span(this_fi),
|
||||
fluent::lint::mismatch_label,
|
||||
)
|
||||
// FIXME(davidtwco): translatable expected/found
|
||||
.note_expected_found(&"", expected_str, &"", found_str)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -3100,11 +3158,12 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
|
|||
|
||||
if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind {
|
||||
if is_null_ptr(cx, expr_deref) {
|
||||
cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
|
||||
let mut err = lint.build(fluent::lint::builtin_deref_nullptr);
|
||||
err.span_label(expr.span, fluent::lint::label);
|
||||
err.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
DEREF_NULLPTR,
|
||||
expr.span,
|
||||
fluent::lint::builtin_deref_nullptr,
|
||||
|lint| lint.span_label(expr.span, fluent::lint::label),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3214,9 +3273,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
|
|||
cx.lookup_with_diagnostics(
|
||||
NAMED_ASM_LABELS,
|
||||
Some(target_spans),
|
||||
|diag| {
|
||||
diag.build(fluent::lint::builtin_asm_labels).emit();
|
||||
},
|
||||
fluent::lint::builtin_asm_labels,
|
||||
|lint| lint,
|
||||
BuiltinLintDiagnostics::NamedAsmLabel(
|
||||
"only local labels of the form `<number>:` should be used in inline asm"
|
||||
.to_string(),
|
||||
|
@ -3288,16 +3346,14 @@ impl EarlyLintPass for SpecialModuleName {
|
|||
}
|
||||
|
||||
match item.ident.name.as_str() {
|
||||
"lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
|
||||
lint.build("found module declaration for lib.rs")
|
||||
"lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, "found module declaration for lib.rs", |lint| {
|
||||
lint
|
||||
.note("lib.rs is the root of this crate's library target")
|
||||
.help("to refer to it from other targets, use the library's name as the path")
|
||||
.emit()
|
||||
}),
|
||||
"main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
|
||||
lint.build("found module declaration for main.rs")
|
||||
"main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, "found module declaration for main.rs", |lint| {
|
||||
lint
|
||||
.note("a binary crate cannot be used as library")
|
||||
.emit()
|
||||
}),
|
||||
_ => continue
|
||||
}
|
||||
|
@ -3317,24 +3373,27 @@ impl EarlyLintPass for UnexpectedCfgs {
|
|||
for &(name, value) in cfg {
|
||||
if let Some(names_valid) = &check_cfg.names_valid {
|
||||
if !names_valid.contains(&name) {
|
||||
cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
|
||||
diag.build(fluent::lint::builtin_unexpected_cli_config_name)
|
||||
.help(fluent::lint::help)
|
||||
.set_arg("name", name)
|
||||
.emit();
|
||||
});
|
||||
cx.lookup(
|
||||
UNEXPECTED_CFGS,
|
||||
None::<MultiSpan>,
|
||||
fluent::lint::builtin_unexpected_cli_config_name,
|
||||
|diag| diag.help(fluent::lint::help).set_arg("name", name),
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(value) = value {
|
||||
if let Some(values) = &check_cfg.values_valid.get(&name) {
|
||||
if !values.contains(&value) {
|
||||
cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
|
||||
diag.build(fluent::lint::builtin_unexpected_cli_config_value)
|
||||
.help(fluent::lint::help)
|
||||
.set_arg("name", name)
|
||||
.set_arg("value", value)
|
||||
.emit();
|
||||
});
|
||||
cx.lookup(
|
||||
UNEXPECTED_CFGS,
|
||||
None::<MultiSpan>,
|
||||
fluent::lint::builtin_unexpected_cli_config_value,
|
||||
|diag| {
|
||||
diag.help(fluent::lint::help)
|
||||
.set_arg("name", name)
|
||||
.set_arg("value", value)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,8 @@ use crate::passes::{EarlyLintPassObject, LateLintPassObject};
|
|||
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_errors::add_elided_lifetime_in_path_suggestion;
|
||||
use rustc_errors::{
|
||||
Applicability, DecorateLint, LintDiagnosticBuilder, MultiSpan, SuggestionStyle,
|
||||
};
|
||||
use rustc_errors::{add_elided_lifetime_in_path_suggestion, DiagnosticBuilder, DiagnosticMessage};
|
||||
use rustc_errors::{Applicability, DecorateLint, MultiSpan, SuggestionStyle};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def_id::{CrateNum, DefId};
|
||||
|
@ -580,13 +578,14 @@ pub trait LintContext: Sized {
|
|||
&self,
|
||||
lint: &'static Lint,
|
||||
span: Option<impl Into<MultiSpan>>,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
diagnostic: BuiltinLintDiagnostics,
|
||||
) {
|
||||
self.lookup(lint, span, |lint| {
|
||||
// We first generate a blank diagnostic.
|
||||
let mut db = lint.build("");
|
||||
|
||||
// We first generate a blank diagnostic.
|
||||
self.lookup(lint, span, msg,|db| {
|
||||
// Now, set up surrounding context.
|
||||
let sess = self.sess();
|
||||
match diagnostic {
|
||||
|
@ -660,7 +659,7 @@ pub trait LintContext: Sized {
|
|||
) => {
|
||||
add_elided_lifetime_in_path_suggestion(
|
||||
sess.source_map(),
|
||||
&mut db,
|
||||
db,
|
||||
n,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
|
@ -696,7 +695,7 @@ pub trait LintContext: Sized {
|
|||
}
|
||||
}
|
||||
BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
|
||||
stability::deprecation_suggestion(&mut db, "macro", suggestion, span)
|
||||
stability::deprecation_suggestion(db, "macro", suggestion, span)
|
||||
}
|
||||
BuiltinLintDiagnostics::UnusedDocComment(span) => {
|
||||
db.span_label(span, "rustdoc does not generate documentation for macro invocations");
|
||||
|
@ -867,7 +866,7 @@ pub trait LintContext: Sized {
|
|||
}
|
||||
}
|
||||
// Rewrap `db`, and pass control to the user.
|
||||
decorate(LintDiagnosticBuilder::new(db));
|
||||
decorate(db)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -877,7 +876,10 @@ pub trait LintContext: Sized {
|
|||
&self,
|
||||
lint: &'static Lint,
|
||||
span: Option<S>,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
);
|
||||
|
||||
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
|
||||
|
@ -888,31 +890,39 @@ pub trait LintContext: Sized {
|
|||
span: S,
|
||||
decorator: impl for<'a> DecorateLint<'a, ()>,
|
||||
) {
|
||||
self.lookup(lint, Some(span), |diag| decorator.decorate_lint(diag));
|
||||
self.lookup(lint, Some(span), decorator.msg(), |diag| decorator.decorate_lint(diag));
|
||||
}
|
||||
|
||||
fn struct_span_lint<S: Into<MultiSpan>>(
|
||||
&self,
|
||||
lint: &'static Lint,
|
||||
span: S,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
) {
|
||||
self.lookup(lint, Some(span), decorate);
|
||||
self.lookup(lint, Some(span), msg, decorate);
|
||||
}
|
||||
|
||||
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
|
||||
/// generated by `#[derive(LintDiagnostic)]`).
|
||||
fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> DecorateLint<'a, ()>) {
|
||||
self.lookup(lint, None as Option<Span>, |diag| decorator.decorate_lint(diag));
|
||||
self.lookup(lint, None as Option<Span>, decorator.msg(), |diag| {
|
||||
decorator.decorate_lint(diag)
|
||||
});
|
||||
}
|
||||
|
||||
/// Emit a lint at the appropriate level, with no associated span.
|
||||
fn lint(
|
||||
&self,
|
||||
lint: &'static Lint,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
) {
|
||||
self.lookup(lint, None as Option<Span>, decorate);
|
||||
self.lookup(lint, None as Option<Span>, msg, decorate);
|
||||
}
|
||||
|
||||
/// This returns the lint level for the given lint at the current location.
|
||||
|
@ -975,13 +985,16 @@ impl<'tcx> LintContext for LateContext<'tcx> {
|
|||
&self,
|
||||
lint: &'static Lint,
|
||||
span: Option<S>,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
) {
|
||||
let hir_id = self.last_node_with_lint_attrs;
|
||||
|
||||
match span {
|
||||
Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, decorate),
|
||||
None => self.tcx.struct_lint_node(lint, hir_id, decorate),
|
||||
Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, msg, decorate),
|
||||
None => self.tcx.struct_lint_node(lint, hir_id, msg, decorate),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1006,9 +1019,12 @@ impl LintContext for EarlyContext<'_> {
|
|||
&self,
|
||||
lint: &'static Lint,
|
||||
span: Option<S>,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
) {
|
||||
self.builder.struct_lint(lint, span.map(|s| s.into()), decorate)
|
||||
self.builder.struct_lint(lint, span.map(|s| s.into()), msg, decorate)
|
||||
}
|
||||
|
||||
fn get_lint_level(&self, lint: &'static Lint) -> Level {
|
||||
|
|
|
@ -43,9 +43,8 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
|
|||
self.context.lookup_with_diagnostics(
|
||||
lint_id.lint,
|
||||
Some(span),
|
||||
|lint| {
|
||||
lint.build(msg).emit();
|
||||
},
|
||||
msg,
|
||||
|lint| lint,
|
||||
diagnostic,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -50,26 +50,24 @@ fn enforce_mem_discriminant(
|
|||
) {
|
||||
let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0);
|
||||
if is_non_enum(ty_param) {
|
||||
cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, expr_span, |builder| {
|
||||
builder
|
||||
.build(fluent::lint::enum_intrinsics_mem_discriminant)
|
||||
.set_arg("ty_param", ty_param)
|
||||
.span_note(args_span, fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
ENUM_INTRINSICS_NON_ENUMS,
|
||||
expr_span,
|
||||
fluent::lint::enum_intrinsics_mem_discriminant,
|
||||
|lint| lint.set_arg("ty_param", ty_param).span_note(args_span, fluent::lint::note),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, span: Span) {
|
||||
let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0);
|
||||
if is_non_enum(ty_param) {
|
||||
cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, span, |builder| {
|
||||
builder
|
||||
.build(fluent::lint::enum_intrinsics_mem_variant)
|
||||
.set_arg("ty_param", ty_param)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
ENUM_INTRINSICS_NON_ENUMS,
|
||||
span,
|
||||
fluent::lint::enum_intrinsics_mem_variant,
|
||||
|lint| lint.set_arg("ty_param", ty_param).note(fluent::lint::note),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,17 +43,17 @@ fn emit_unfulfilled_expectation_lint(
|
|||
builtin::UNFULFILLED_LINT_EXPECTATIONS,
|
||||
hir_id,
|
||||
expectation.emission_span,
|
||||
|diag| {
|
||||
let mut diag = diag.build(fluent::lint::expectation);
|
||||
fluent::lint::expectation,
|
||||
|lint| {
|
||||
if let Some(rationale) = expectation.reason {
|
||||
diag.note(rationale.as_str());
|
||||
lint.note(rationale.as_str());
|
||||
}
|
||||
|
||||
if expectation.is_unfulfilled_lint_expectations {
|
||||
diag.note(fluent::lint::note);
|
||||
lint.note(fluent::lint::note);
|
||||
}
|
||||
|
||||
diag.emit();
|
||||
lint
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -60,52 +60,56 @@ impl HiddenUnicodeCodepoints {
|
|||
})
|
||||
.collect();
|
||||
|
||||
cx.struct_span_lint(TEXT_DIRECTION_CODEPOINT_IN_LITERAL, span, |lint| {
|
||||
let mut err = lint.build(fluent::lint::hidden_unicode_codepoints);
|
||||
err.set_arg("label", label);
|
||||
err.set_arg("count", spans.len());
|
||||
err.span_label(span, fluent::lint::label);
|
||||
err.note(fluent::lint::note);
|
||||
if point_at_inner_spans {
|
||||
for (c, span) in &spans {
|
||||
err.span_label(*span, format!("{:?}", c));
|
||||
cx.struct_span_lint(
|
||||
TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
|
||||
span,
|
||||
fluent::lint::hidden_unicode_codepoints,
|
||||
|lint| {
|
||||
lint.set_arg("label", label);
|
||||
lint.set_arg("count", spans.len());
|
||||
lint.span_label(span, fluent::lint::label);
|
||||
lint.note(fluent::lint::note);
|
||||
if point_at_inner_spans {
|
||||
for (c, span) in &spans {
|
||||
lint.span_label(*span, format!("{:?}", c));
|
||||
}
|
||||
}
|
||||
}
|
||||
if point_at_inner_spans && !spans.is_empty() {
|
||||
err.multipart_suggestion_with_style(
|
||||
fluent::lint::suggestion_remove,
|
||||
spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
|
||||
Applicability::MachineApplicable,
|
||||
SuggestionStyle::HideCodeAlways,
|
||||
);
|
||||
err.multipart_suggestion(
|
||||
fluent::lint::suggestion_escape,
|
||||
spans
|
||||
.into_iter()
|
||||
.map(|(c, span)| {
|
||||
let c = format!("{:?}", c);
|
||||
(span, c[1..c.len() - 1].to_string())
|
||||
})
|
||||
.collect(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
// FIXME: in other suggestions we've reversed the inner spans of doc comments. We
|
||||
// should do the same here to provide the same good suggestions as we do for
|
||||
// literals above.
|
||||
err.set_arg(
|
||||
"escaped",
|
||||
spans
|
||||
.into_iter()
|
||||
.map(|(c, _)| format!("{:?}", c))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", "),
|
||||
);
|
||||
err.note(fluent::lint::suggestion_remove);
|
||||
err.note(fluent::lint::no_suggestion_note_escape);
|
||||
}
|
||||
err.emit();
|
||||
});
|
||||
if point_at_inner_spans && !spans.is_empty() {
|
||||
lint.multipart_suggestion_with_style(
|
||||
fluent::lint::suggestion_remove,
|
||||
spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
|
||||
Applicability::MachineApplicable,
|
||||
SuggestionStyle::HideCodeAlways,
|
||||
);
|
||||
lint.multipart_suggestion(
|
||||
fluent::lint::suggestion_escape,
|
||||
spans
|
||||
.into_iter()
|
||||
.map(|(c, span)| {
|
||||
let c = format!("{:?}", c);
|
||||
(span, c[1..c.len() - 1].to_string())
|
||||
})
|
||||
.collect(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
// FIXME: in other suggestions we've reversed the inner spans of doc comments. We
|
||||
// should do the same here to provide the same good suggestions as we do for
|
||||
// literals above.
|
||||
lint.set_arg(
|
||||
"escaped",
|
||||
spans
|
||||
.into_iter()
|
||||
.map(|(c, _)| format!("{:?}", c))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", "),
|
||||
);
|
||||
lint.note(fluent::lint::suggestion_remove);
|
||||
lint.note(fluent::lint::no_suggestion_note_escape);
|
||||
}
|
||||
lint
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
impl EarlyLintPass for HiddenUnicodeCodepoints {
|
||||
|
|
|
@ -34,13 +34,16 @@ impl LateLintPass<'_> for DefaultHashTypes {
|
|||
Some(sym::HashSet) => "FxHashSet",
|
||||
_ => return,
|
||||
};
|
||||
cx.struct_span_lint(DEFAULT_HASH_TYPES, path.span, |lint| {
|
||||
lint.build(fluent::lint::default_hash_types)
|
||||
.set_arg("preferred", replace)
|
||||
.set_arg("used", cx.tcx.item_name(def_id))
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
DEFAULT_HASH_TYPES,
|
||||
path.span,
|
||||
fluent::lint::default_hash_types,
|
||||
|lint| {
|
||||
lint.set_arg("preferred", replace)
|
||||
.set_arg("used", cx.tcx.item_name(def_id))
|
||||
.note(fluent::lint::note)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,12 +83,12 @@ impl LateLintPass<'_> for QueryStability {
|
|||
if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) {
|
||||
let def_id = instance.def_id();
|
||||
if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
|
||||
cx.struct_span_lint(POTENTIAL_QUERY_INSTABILITY, span, |lint| {
|
||||
lint.build(fluent::lint::query_instability)
|
||||
.set_arg("query", cx.tcx.item_name(def_id))
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
})
|
||||
cx.struct_span_lint(
|
||||
POTENTIAL_QUERY_INSTABILITY,
|
||||
span,
|
||||
fluent::lint::query_instability,
|
||||
|lint| lint.set_arg("query", cx.tcx.item_name(def_id)).note(fluent::lint::note),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,15 +126,14 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
|||
let span = path.span.with_hi(
|
||||
segment.args.map_or(segment.ident.span, |a| a.span_ext).hi()
|
||||
);
|
||||
cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
|
||||
lint.build(fluent::lint::tykind_kind)
|
||||
cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, fluent::lint::tykind_kind, |lint| {
|
||||
lint
|
||||
.span_suggestion(
|
||||
span,
|
||||
fluent::lint::suggestion,
|
||||
"ty",
|
||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -140,76 +142,77 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
|||
match &ty.kind {
|
||||
TyKind::Path(QPath::Resolved(_, path)) => {
|
||||
if lint_ty_kind_usage(cx, &path.res) {
|
||||
cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
|
||||
let hir = cx.tcx.hir();
|
||||
match hir.find(hir.get_parent_node(ty.hir_id)) {
|
||||
Some(Node::Pat(Pat {
|
||||
kind:
|
||||
PatKind::Path(qpath)
|
||||
| PatKind::TupleStruct(qpath, ..)
|
||||
| PatKind::Struct(qpath, ..),
|
||||
..
|
||||
})) => {
|
||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||
&& qpath_ty.hir_id == ty.hir_id
|
||||
{
|
||||
lint.build(fluent::lint::tykind_kind)
|
||||
.span_suggestion(
|
||||
path.span,
|
||||
fluent::lint::suggestion,
|
||||
"ty",
|
||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
||||
)
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
let hir = cx.tcx.hir();
|
||||
let span = match hir.find(hir.get_parent_node(ty.hir_id)) {
|
||||
Some(Node::Pat(Pat {
|
||||
kind:
|
||||
PatKind::Path(qpath)
|
||||
| PatKind::TupleStruct(qpath, ..)
|
||||
| PatKind::Struct(qpath, ..),
|
||||
..
|
||||
})) => {
|
||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||
&& qpath_ty.hir_id == ty.hir_id
|
||||
{
|
||||
Some(path.span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
Some(Node::Expr(Expr {
|
||||
kind: ExprKind::Path(qpath),
|
||||
..
|
||||
})) => {
|
||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||
&& qpath_ty.hir_id == ty.hir_id
|
||||
{
|
||||
lint.build(fluent::lint::tykind_kind)
|
||||
.span_suggestion(
|
||||
path.span,
|
||||
fluent::lint::suggestion,
|
||||
"ty",
|
||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
||||
)
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Can't unify these two branches because qpath below is `&&` and above is `&`
|
||||
// and `A | B` paths don't play well together with adjustments, apparently.
|
||||
Some(Node::Expr(Expr {
|
||||
kind: ExprKind::Struct(qpath, ..),
|
||||
..
|
||||
})) => {
|
||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||
&& qpath_ty.hir_id == ty.hir_id
|
||||
{
|
||||
lint.build(fluent::lint::tykind_kind)
|
||||
.span_suggestion(
|
||||
path.span,
|
||||
fluent::lint::suggestion,
|
||||
"ty",
|
||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
||||
)
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
lint.build(fluent::lint::tykind).help(fluent::lint::help).emit();
|
||||
})
|
||||
Some(Node::Expr(Expr {
|
||||
kind: ExprKind::Path(qpath),
|
||||
..
|
||||
})) => {
|
||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||
&& qpath_ty.hir_id == ty.hir_id
|
||||
{
|
||||
Some(path.span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
// Can't unify these two branches because qpath below is `&&` and above is `&`
|
||||
// and `A | B` paths don't play well together with adjustments, apparently.
|
||||
Some(Node::Expr(Expr {
|
||||
kind: ExprKind::Struct(qpath, ..),
|
||||
..
|
||||
})) => {
|
||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||
&& qpath_ty.hir_id == ty.hir_id
|
||||
{
|
||||
Some(path.span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
|
||||
match span {
|
||||
Some(span) => {
|
||||
cx.struct_span_lint(
|
||||
USAGE_OF_TY_TYKIND,
|
||||
path.span,
|
||||
fluent::lint::tykind_kind,
|
||||
|lint| lint.span_suggestion(
|
||||
span,
|
||||
fluent::lint::suggestion,
|
||||
"ty",
|
||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
||||
)
|
||||
)
|
||||
},
|
||||
None => cx.struct_span_lint(
|
||||
USAGE_OF_TY_TYKIND,
|
||||
path.span,
|
||||
fluent::lint::tykind,
|
||||
|lint| lint.help(fluent::lint::help)
|
||||
)
|
||||
}
|
||||
} else if !ty.span.from_expansion() && let Some(t) = is_ty_or_ty_ctxt(cx, &path) {
|
||||
if path.segments.len() > 1 {
|
||||
cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| {
|
||||
lint.build(fluent::lint::ty_qualified)
|
||||
cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, fluent::lint::ty_qualified, |lint| {
|
||||
lint
|
||||
.set_arg("ty", t.clone())
|
||||
.span_suggestion(
|
||||
path.span,
|
||||
|
@ -218,7 +221,6 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
|||
// The import probably needs to be changed
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -308,11 +310,8 @@ impl EarlyLintPass for LintPassImpl {
|
|||
cx.struct_span_lint(
|
||||
LINT_PASS_IMPL_WITHOUT_MACRO,
|
||||
lint_pass.path.span,
|
||||
|lint| {
|
||||
lint.build(fluent::lint::lintpass_by_hand)
|
||||
.help(fluent::lint::help)
|
||||
.emit();
|
||||
},
|
||||
fluent::lint::lintpass_by_hand,
|
||||
|lint| lint.help(fluent::lint::help),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -349,12 +348,12 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
|
|||
if is_doc_keyword(v) {
|
||||
return;
|
||||
}
|
||||
cx.struct_span_lint(EXISTING_DOC_KEYWORD, attr.span, |lint| {
|
||||
lint.build(fluent::lint::non_existant_doc_keyword)
|
||||
.set_arg("keyword", v)
|
||||
.help(fluent::lint::help)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
EXISTING_DOC_KEYWORD,
|
||||
attr.span,
|
||||
fluent::lint::non_existant_doc_keyword,
|
||||
|lint| lint.set_arg("keyword", v).help(fluent::lint::help),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -412,9 +411,12 @@ impl LateLintPass<'_> for Diagnostics {
|
|||
}
|
||||
debug!(?found_impl);
|
||||
if !found_parent_with_attr && !found_impl {
|
||||
cx.struct_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, |lint| {
|
||||
lint.build(fluent::lint::diag_out_of_impl).emit();
|
||||
})
|
||||
cx.struct_span_lint(
|
||||
DIAGNOSTIC_OUTSIDE_OF_IMPL,
|
||||
span,
|
||||
fluent::lint::diag_out_of_impl,
|
||||
|lint| lint,
|
||||
)
|
||||
}
|
||||
|
||||
let mut found_diagnostic_message = false;
|
||||
|
@ -430,9 +432,12 @@ impl LateLintPass<'_> for Diagnostics {
|
|||
}
|
||||
debug!(?found_diagnostic_message);
|
||||
if !found_parent_with_attr && !found_diagnostic_message {
|
||||
cx.struct_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, |lint| {
|
||||
lint.build(fluent::lint::untranslatable_diag).emit();
|
||||
})
|
||||
cx.struct_span_lint(
|
||||
UNTRANSLATABLE_DIAGNOSTIC,
|
||||
span,
|
||||
fluent::lint::untranslatable_diag,
|
||||
|lint| lint,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -464,8 +469,8 @@ impl LateLintPass<'_> for BadOptAccess {
|
|||
let Some(literal) = item.literal() &&
|
||||
let ast::LitKind::Str(val, _) = literal.kind
|
||||
{
|
||||
cx.struct_span_lint(BAD_OPT_ACCESS, expr.span, |lint| {
|
||||
lint.build(val.as_str()).emit(); }
|
||||
cx.struct_span_lint(BAD_OPT_ACCESS, expr.span, val.as_str(), |lint|
|
||||
lint
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_errors::{Applicability, LintDiagnosticBuilder, MultiSpan};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::Symbol;
|
||||
|
@ -128,48 +128,41 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
|
|||
init.span,
|
||||
"this binding will immediately drop the value assigned to it".to_string(),
|
||||
);
|
||||
cx.struct_span_lint(LET_UNDERSCORE_LOCK, span, |lint| {
|
||||
build_and_emit_lint(
|
||||
lint,
|
||||
local,
|
||||
init.span,
|
||||
"non-binding let on a synchronization lock",
|
||||
)
|
||||
})
|
||||
cx.struct_span_lint(
|
||||
LET_UNDERSCORE_LOCK,
|
||||
span,
|
||||
"non-binding let on a synchronization lock",
|
||||
|lint| build_lint(lint, local, init.span),
|
||||
)
|
||||
} else {
|
||||
cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| {
|
||||
build_and_emit_lint(
|
||||
lint,
|
||||
local,
|
||||
init.span,
|
||||
"non-binding let on a type that implements `Drop`",
|
||||
);
|
||||
})
|
||||
cx.struct_span_lint(
|
||||
LET_UNDERSCORE_DROP,
|
||||
local.span,
|
||||
"non-binding let on a type that implements `Drop`",
|
||||
|lint| build_lint(lint, local, init.span),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_and_emit_lint(
|
||||
lint: LintDiagnosticBuilder<'_, ()>,
|
||||
fn build_lint<'a, 'b>(
|
||||
lint: &'a mut DiagnosticBuilder<'b, ()>,
|
||||
local: &hir::Local<'_>,
|
||||
init_span: rustc_span::Span,
|
||||
msg: &str,
|
||||
) {
|
||||
lint.build(msg)
|
||||
.span_suggestion_verbose(
|
||||
local.pat.span,
|
||||
"consider binding to an unused variable to avoid immediately dropping the value",
|
||||
"_unused",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.multipart_suggestion(
|
||||
"consider immediately dropping the value",
|
||||
vec![
|
||||
(local.span.until(init_span), "drop(".to_string()),
|
||||
(init_span.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
) -> &'a mut DiagnosticBuilder<'b, ()> {
|
||||
lint.span_suggestion_verbose(
|
||||
local.pat.span,
|
||||
"consider binding to an unused variable to avoid immediately dropping the value",
|
||||
"_unused",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.multipart_suggestion(
|
||||
"consider immediately dropping the value",
|
||||
vec![
|
||||
(local.span.until(init_span), "drop(".to_string()),
|
||||
(init_span.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::late::unerased_lint_store;
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan};
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{intravisit, HirId};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
|
@ -214,14 +214,14 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
self.struct_lint(
|
||||
FORBIDDEN_LINT_GROUPS,
|
||||
Some(src.span().into()),
|
||||
|diag_builder| {
|
||||
let mut diag_builder = diag_builder.build(&format!(
|
||||
"{}({}) incompatible with previous forbid",
|
||||
level.as_str(),
|
||||
src.name(),
|
||||
));
|
||||
decorate_diag(&mut diag_builder);
|
||||
diag_builder.emit();
|
||||
format!(
|
||||
"{}({}) incompatible with previous forbid",
|
||||
level.as_str(),
|
||||
src.name(),
|
||||
),
|
||||
|lint| {
|
||||
decorate_diag(lint);
|
||||
lint
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -466,20 +466,18 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
lvl,
|
||||
src,
|
||||
Some(sp.into()),
|
||||
format!(
|
||||
"lint name `{}` is deprecated \
|
||||
and may not have an effect in the future.",
|
||||
name
|
||||
),
|
||||
|lint| {
|
||||
let msg = format!(
|
||||
"lint name `{}` is deprecated \
|
||||
and may not have an effect in the future.",
|
||||
name
|
||||
);
|
||||
lint.build(&msg)
|
||||
.span_suggestion(
|
||||
sp,
|
||||
"change it to",
|
||||
new_lint_name,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
lint.span_suggestion(
|
||||
sp,
|
||||
"change it to",
|
||||
new_lint_name,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -533,17 +531,17 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
renamed_lint_level,
|
||||
src,
|
||||
Some(sp.into()),
|
||||
msg,
|
||||
|lint| {
|
||||
let mut err = lint.build(msg);
|
||||
if let Some(new_name) = &renamed {
|
||||
err.span_suggestion(
|
||||
lint.span_suggestion(
|
||||
sp,
|
||||
"use the new name",
|
||||
new_name,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
lint
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -555,23 +553,30 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
Some(self.current_specs()),
|
||||
self.sess,
|
||||
);
|
||||
struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| {
|
||||
let name = if let Some(tool_ident) = tool_ident {
|
||||
format!("{}::{}", tool_ident.name, name)
|
||||
} else {
|
||||
name.to_string()
|
||||
};
|
||||
let mut db = lint.build(format!("unknown lint: `{}`", name));
|
||||
if let Some(suggestion) = suggestion {
|
||||
db.span_suggestion(
|
||||
sp,
|
||||
"did you mean",
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
db.emit();
|
||||
});
|
||||
let name = if let Some(tool_ident) = tool_ident {
|
||||
format!("{}::{}", tool_ident.name, name)
|
||||
} else {
|
||||
name.to_string()
|
||||
};
|
||||
struct_lint_level(
|
||||
self.sess,
|
||||
lint,
|
||||
level,
|
||||
src,
|
||||
Some(sp.into()),
|
||||
format!("unknown lint: `{}`", name),
|
||||
|lint| {
|
||||
if let Some(suggestion) = suggestion {
|
||||
lint.span_suggestion(
|
||||
sp,
|
||||
"did you mean",
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
lint
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
// If this lint was renamed, apply the new lint instead of ignoring the attribute.
|
||||
|
@ -621,14 +626,12 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
lint_level,
|
||||
lint_src,
|
||||
Some(lint_attr_span.into()),
|
||||
|lint| {
|
||||
let mut db = lint.build(&format!(
|
||||
"{}({}) is ignored unless specified at crate level",
|
||||
level.as_str(),
|
||||
lint_attr_name
|
||||
));
|
||||
db.emit();
|
||||
},
|
||||
format!(
|
||||
"{}({}) is ignored unless specified at crate level",
|
||||
level.as_str(),
|
||||
lint_attr_name
|
||||
),
|
||||
|lint| lint,
|
||||
);
|
||||
// don't set a separate error for every lint in the group
|
||||
break;
|
||||
|
@ -665,13 +668,21 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
if !self.sess.features_untracked().enabled(feature) {
|
||||
let lint = builtin::UNKNOWN_LINTS;
|
||||
let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS);
|
||||
struct_lint_level(self.sess, lint, level, src, Some(span.into()), |lint_db| {
|
||||
let mut db =
|
||||
lint_db.build(&format!("unknown lint: `{}`", lint_id.lint.name_lower()));
|
||||
db.note(&format!("the `{}` lint is unstable", lint_id.lint.name_lower(),));
|
||||
add_feature_diagnostics(&mut db, &self.sess.parse_sess, feature);
|
||||
db.emit();
|
||||
});
|
||||
struct_lint_level(
|
||||
self.sess,
|
||||
lint,
|
||||
level,
|
||||
src,
|
||||
Some(span.into()),
|
||||
format!("unknown lint: `{}`", lint_id.lint.name_lower()),
|
||||
|lint| {
|
||||
lint.note(
|
||||
&format!("the `{}` lint is unstable", lint_id.lint.name_lower(),),
|
||||
);
|
||||
add_feature_diagnostics(lint, &self.sess.parse_sess, feature);
|
||||
lint
|
||||
},
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -694,10 +705,13 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
&self,
|
||||
lint: &'static Lint,
|
||||
span: Option<MultiSpan>,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
) {
|
||||
let (level, src) = self.lint_level(lint);
|
||||
struct_lint_level(self.sess, lint, level, src, span, decorate)
|
||||
struct_lint_level(self.sess, lint, level, src, span, msg, decorate)
|
||||
}
|
||||
|
||||
/// Registers the ID provided with the current set of lints stored in
|
||||
|
|
|
@ -90,14 +90,17 @@ fn lint_cstring_as_ptr(
|
|||
if cx.tcx.is_diagnostic_item(sym::Result, def.did()) {
|
||||
if let ty::Adt(adt, _) = substs.type_at(0).kind() {
|
||||
if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did()) {
|
||||
cx.struct_span_lint(TEMPORARY_CSTRING_AS_PTR, as_ptr_span, |diag| {
|
||||
diag.build(fluent::lint::cstring_ptr)
|
||||
.span_label(as_ptr_span, fluent::lint::as_ptr_label)
|
||||
.span_label(unwrap.span, fluent::lint::unwrap_label)
|
||||
.note(fluent::lint::note)
|
||||
.help(fluent::lint::help)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
TEMPORARY_CSTRING_AS_PTR,
|
||||
as_ptr_span,
|
||||
fluent::lint::cstring_ptr,
|
||||
|diag| {
|
||||
diag.span_label(as_ptr_span, fluent::lint::as_ptr_label)
|
||||
.span_label(unwrap.span, fluent::lint::unwrap_label)
|
||||
.note(fluent::lint::note)
|
||||
.help(fluent::lint::help)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,15 +180,21 @@ impl EarlyLintPass for NonAsciiIdents {
|
|||
continue;
|
||||
}
|
||||
has_non_ascii_idents = true;
|
||||
cx.struct_span_lint(NON_ASCII_IDENTS, sp, |lint| {
|
||||
lint.build(fluent::lint::identifier_non_ascii_char).emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
NON_ASCII_IDENTS,
|
||||
sp,
|
||||
fluent::lint::identifier_non_ascii_char,
|
||||
|lint| lint,
|
||||
);
|
||||
if check_uncommon_codepoints
|
||||
&& !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed)
|
||||
{
|
||||
cx.struct_span_lint(UNCOMMON_CODEPOINTS, sp, |lint| {
|
||||
lint.build(fluent::lint::identifier_uncommon_codepoints).emit();
|
||||
})
|
||||
cx.struct_span_lint(
|
||||
UNCOMMON_CODEPOINTS,
|
||||
sp,
|
||||
fluent::lint::identifier_uncommon_codepoints,
|
||||
|lint| lint,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,13 +222,16 @@ impl EarlyLintPass for NonAsciiIdents {
|
|||
.entry(skeleton_sym)
|
||||
.and_modify(|(existing_symbol, existing_span, existing_is_ascii)| {
|
||||
if !*existing_is_ascii || !is_ascii {
|
||||
cx.struct_span_lint(CONFUSABLE_IDENTS, sp, |lint| {
|
||||
lint.build(fluent::lint::confusable_identifier_pair)
|
||||
.set_arg("existing_sym", *existing_symbol)
|
||||
.set_arg("sym", symbol)
|
||||
.span_label(*existing_span, fluent::lint::label)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
CONFUSABLE_IDENTS,
|
||||
sp,
|
||||
fluent::lint::confusable_identifier_pair,
|
||||
|lint| {
|
||||
lint.set_arg("existing_sym", *existing_symbol)
|
||||
.set_arg("sym", symbol)
|
||||
.span_label(*existing_span, fluent::lint::label)
|
||||
},
|
||||
);
|
||||
}
|
||||
if *existing_is_ascii && !is_ascii {
|
||||
*existing_symbol = symbol;
|
||||
|
@ -322,22 +331,25 @@ impl EarlyLintPass for NonAsciiIdents {
|
|||
}
|
||||
|
||||
for ((sp, ch_list), script_set) in lint_reports {
|
||||
cx.struct_span_lint(MIXED_SCRIPT_CONFUSABLES, sp, |lint| {
|
||||
let mut includes = String::new();
|
||||
for (idx, ch) in ch_list.into_iter().enumerate() {
|
||||
if idx != 0 {
|
||||
includes += ", ";
|
||||
cx.struct_span_lint(
|
||||
MIXED_SCRIPT_CONFUSABLES,
|
||||
sp,
|
||||
fluent::lint::mixed_script_confusables,
|
||||
|lint| {
|
||||
let mut includes = String::new();
|
||||
for (idx, ch) in ch_list.into_iter().enumerate() {
|
||||
if idx != 0 {
|
||||
includes += ", ";
|
||||
}
|
||||
let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
|
||||
includes += &char_info;
|
||||
}
|
||||
let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
|
||||
includes += &char_info;
|
||||
}
|
||||
lint.build(fluent::lint::mixed_script_confusables)
|
||||
.set_arg("set", script_set.to_string())
|
||||
.set_arg("includes", includes)
|
||||
.note(fluent::lint::includes_note)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
lint.set_arg("set", script_set.to_string())
|
||||
.set_arg("includes", includes)
|
||||
.note(fluent::lint::includes_note)
|
||||
.note(fluent::lint::note)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,21 +119,19 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||
arg_span = expn.call_site;
|
||||
}
|
||||
|
||||
cx.struct_span_lint(NON_FMT_PANICS, arg_span, |lint| {
|
||||
let mut l = lint.build(fluent::lint::non_fmt_panic);
|
||||
l.set_arg("name", symbol);
|
||||
l.note(fluent::lint::note);
|
||||
l.note(fluent::lint::more_info_note);
|
||||
cx.struct_span_lint(NON_FMT_PANICS, arg_span, fluent::lint::non_fmt_panic, |lint| {
|
||||
lint.set_arg("name", symbol);
|
||||
lint.note(fluent::lint::note);
|
||||
lint.note(fluent::lint::more_info_note);
|
||||
if !is_arg_inside_call(arg_span, span) {
|
||||
// No clue where this argument is coming from.
|
||||
l.emit();
|
||||
return;
|
||||
return lint;
|
||||
}
|
||||
if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
|
||||
// A case of `panic!(format!(..))`.
|
||||
l.note(fluent::lint::supports_fmt_note);
|
||||
lint.note(fluent::lint::supports_fmt_note);
|
||||
if let Some((open, close, _)) = find_delimiters(cx, arg_span) {
|
||||
l.multipart_suggestion(
|
||||
lint.multipart_suggestion(
|
||||
fluent::lint::supports_fmt_suggestion,
|
||||
vec![
|
||||
(arg_span.until(open.shrink_to_hi()), "".into()),
|
||||
|
@ -180,15 +178,15 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||
};
|
||||
|
||||
if suggest_display {
|
||||
l.span_suggestion_verbose(
|
||||
lint.span_suggestion_verbose(
|
||||
arg_span.shrink_to_lo(),
|
||||
fluent::lint::display_suggestion,
|
||||
"\"{}\", ",
|
||||
fmt_applicability,
|
||||
);
|
||||
} else if suggest_debug {
|
||||
l.set_arg("ty", ty);
|
||||
l.span_suggestion_verbose(
|
||||
lint.set_arg("ty", ty);
|
||||
lint.span_suggestion_verbose(
|
||||
arg_span.shrink_to_lo(),
|
||||
fluent::lint::debug_suggestion,
|
||||
"\"{:?}\", ",
|
||||
|
@ -198,8 +196,8 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||
|
||||
if suggest_panic_any {
|
||||
if let Some((open, close, del)) = find_delimiters(cx, span) {
|
||||
l.set_arg("already_suggested", suggest_display || suggest_debug);
|
||||
l.multipart_suggestion(
|
||||
lint.set_arg("already_suggested", suggest_display || suggest_debug);
|
||||
lint.multipart_suggestion(
|
||||
fluent::lint::panic_suggestion,
|
||||
if del == '(' {
|
||||
vec![(span.until(open), "std::panic::panic_any".into())]
|
||||
|
@ -214,7 +212,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||
}
|
||||
}
|
||||
}
|
||||
l.emit();
|
||||
lint
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -258,26 +256,30 @@ fn check_panic_str<'tcx>(
|
|||
.map(|span| fmt_span.from_inner(InnerSpan::new(span.start, span.end)))
|
||||
.collect(),
|
||||
};
|
||||
cx.struct_span_lint(NON_FMT_PANICS, arg_spans, |lint| {
|
||||
let mut l = lint.build(fluent::lint::non_fmt_panic_unused);
|
||||
l.set_arg("count", n_arguments);
|
||||
l.note(fluent::lint::note);
|
||||
if is_arg_inside_call(arg.span, span) {
|
||||
l.span_suggestion(
|
||||
arg.span.shrink_to_hi(),
|
||||
fluent::lint::add_args_suggestion,
|
||||
", ...",
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
l.span_suggestion(
|
||||
arg.span.shrink_to_lo(),
|
||||
fluent::lint::add_fmt_suggestion,
|
||||
"\"{}\", ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
l.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
NON_FMT_PANICS,
|
||||
arg_spans,
|
||||
fluent::lint::non_fmt_panic_unused,
|
||||
|lint| {
|
||||
lint.set_arg("count", n_arguments);
|
||||
lint.note(fluent::lint::note);
|
||||
if is_arg_inside_call(arg.span, span) {
|
||||
lint.span_suggestion(
|
||||
arg.span.shrink_to_hi(),
|
||||
fluent::lint::add_args_suggestion,
|
||||
", ...",
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
lint.span_suggestion(
|
||||
arg.span.shrink_to_lo(),
|
||||
fluent::lint::add_fmt_suggestion,
|
||||
"\"{}\", ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
lint
|
||||
},
|
||||
);
|
||||
} else {
|
||||
let brace_spans: Option<Vec<_>> =
|
||||
snippet.filter(|s| s.starts_with('"') || s.starts_with("r#")).map(|s| {
|
||||
|
@ -287,20 +289,24 @@ fn check_panic_str<'tcx>(
|
|||
.collect()
|
||||
});
|
||||
let count = brace_spans.as_ref().map(|v| v.len()).unwrap_or(/* any number >1 */ 2);
|
||||
cx.struct_span_lint(NON_FMT_PANICS, brace_spans.unwrap_or_else(|| vec![span]), |lint| {
|
||||
let mut l = lint.build(fluent::lint::non_fmt_panic_braces);
|
||||
l.set_arg("count", count);
|
||||
l.note(fluent::lint::note);
|
||||
if is_arg_inside_call(arg.span, span) {
|
||||
l.span_suggestion(
|
||||
arg.span.shrink_to_lo(),
|
||||
fluent::lint::suggestion,
|
||||
"\"{}\", ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
l.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
NON_FMT_PANICS,
|
||||
brace_spans.unwrap_or_else(|| vec![span]),
|
||||
fluent::lint::non_fmt_panic_braces,
|
||||
|lint| {
|
||||
lint.set_arg("count", count);
|
||||
lint.note(fluent::lint::note);
|
||||
if is_arg_inside_call(arg.span, span) {
|
||||
lint.span_suggestion(
|
||||
arg.span.shrink_to_lo(),
|
||||
fluent::lint::suggestion,
|
||||
"\"{}\", ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
lint
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -136,26 +136,30 @@ impl NonCamelCaseTypes {
|
|||
let name = ident.name.as_str();
|
||||
|
||||
if !is_camel_case(name) {
|
||||
cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| {
|
||||
let mut err = lint.build(fluent::lint::non_camel_case_type);
|
||||
let cc = to_camel_case(name);
|
||||
// We cannot provide meaningful suggestions
|
||||
// if the characters are in the category of "Lowercase Letter".
|
||||
if *name != cc {
|
||||
err.span_suggestion(
|
||||
ident.span,
|
||||
fluent::lint::suggestion,
|
||||
to_camel_case(name),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.span_label(ident.span, fluent::lint::label);
|
||||
}
|
||||
cx.struct_span_lint(
|
||||
NON_CAMEL_CASE_TYPES,
|
||||
ident.span,
|
||||
fluent::lint::non_camel_case_type,
|
||||
|lint| {
|
||||
let cc = to_camel_case(name);
|
||||
// We cannot provide meaningful suggestions
|
||||
// if the characters are in the category of "Lowercase Letter".
|
||||
if *name != cc {
|
||||
lint.span_suggestion(
|
||||
ident.span,
|
||||
fluent::lint::suggestion,
|
||||
to_camel_case(name),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
lint.span_label(ident.span, fluent::lint::label);
|
||||
}
|
||||
|
||||
err.set_arg("sort", sort);
|
||||
err.set_arg("name", name);
|
||||
err.emit();
|
||||
})
|
||||
lint.set_arg("sort", sort);
|
||||
lint.set_arg("name", name);
|
||||
lint
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -280,9 +284,8 @@ impl NonSnakeCase {
|
|||
let name = ident.name.as_str();
|
||||
|
||||
if !is_snake_case(name) {
|
||||
cx.struct_span_lint(NON_SNAKE_CASE, ident.span, |lint| {
|
||||
cx.struct_span_lint(NON_SNAKE_CASE, ident.span, fluent::lint::non_snake_case, |lint| {
|
||||
let sc = NonSnakeCase::to_snake_case(name);
|
||||
let mut err = lint.build(fluent::lint::non_snake_case);
|
||||
// We cannot provide meaningful suggestions
|
||||
// if the characters are in the category of "Uppercase Letter".
|
||||
if name != sc {
|
||||
|
@ -297,30 +300,30 @@ impl NonSnakeCase {
|
|||
if sc_ident.name.can_be_raw() {
|
||||
(fluent::lint::rename_or_convert_suggestion, sc_ident.to_string())
|
||||
} else {
|
||||
err.note(fluent::lint::cannot_convert_note);
|
||||
lint.note(fluent::lint::cannot_convert_note);
|
||||
(fluent::lint::rename_suggestion, String::new())
|
||||
}
|
||||
} else {
|
||||
(fluent::lint::convert_suggestion, sc.clone())
|
||||
};
|
||||
|
||||
err.span_suggestion(
|
||||
lint.span_suggestion(
|
||||
ident.span,
|
||||
message,
|
||||
suggestion,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.help(fluent::lint::help);
|
||||
lint.help(fluent::lint::help);
|
||||
}
|
||||
} else {
|
||||
err.span_label(ident.span, fluent::lint::label);
|
||||
lint.span_label(ident.span, fluent::lint::label);
|
||||
}
|
||||
|
||||
err.set_arg("sort", sort);
|
||||
err.set_arg("name", name);
|
||||
err.set_arg("sc", sc);
|
||||
err.emit();
|
||||
lint.set_arg("sort", sort);
|
||||
lint.set_arg("name", name);
|
||||
lint.set_arg("sc", sc);
|
||||
lint
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -478,26 +481,30 @@ impl NonUpperCaseGlobals {
|
|||
fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) {
|
||||
let name = ident.name.as_str();
|
||||
if name.chars().any(|c| c.is_lowercase()) {
|
||||
cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| {
|
||||
let uc = NonSnakeCase::to_snake_case(&name).to_uppercase();
|
||||
let mut err = lint.build(fluent::lint::non_upper_case_global);
|
||||
// We cannot provide meaningful suggestions
|
||||
// if the characters are in the category of "Lowercase Letter".
|
||||
if *name != uc {
|
||||
err.span_suggestion(
|
||||
ident.span,
|
||||
fluent::lint::suggestion,
|
||||
uc,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.span_label(ident.span, fluent::lint::label);
|
||||
}
|
||||
cx.struct_span_lint(
|
||||
NON_UPPER_CASE_GLOBALS,
|
||||
ident.span,
|
||||
fluent::lint::non_upper_case_global,
|
||||
|lint| {
|
||||
let uc = NonSnakeCase::to_snake_case(&name).to_uppercase();
|
||||
// We cannot provide meaningful suggestions
|
||||
// if the characters are in the category of "Lowercase Letter".
|
||||
if *name != uc {
|
||||
lint.span_suggestion(
|
||||
ident.span,
|
||||
fluent::lint::suggestion,
|
||||
uc,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
lint.span_label(ident.span, fluent::lint::label);
|
||||
}
|
||||
|
||||
err.set_arg("sort", sort);
|
||||
err.set_arg("name", name);
|
||||
err.emit();
|
||||
})
|
||||
lint.set_arg("sort", sort);
|
||||
lint.set_arg("name", name);
|
||||
lint
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,13 +90,11 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
|||
}
|
||||
let expr_span = expr.span;
|
||||
let span = expr_span.with_lo(receiver.span.hi());
|
||||
cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
|
||||
lint.build(fluent::lint::noop_method_call)
|
||||
.set_arg("method", call.ident.name)
|
||||
cx.struct_span_lint(NOOP_METHOD_CALL, span, fluent::lint::noop_method_call, |lint| {
|
||||
lint.set_arg("method", call.ident.name)
|
||||
.set_arg("receiver_ty", receiver_ty)
|
||||
.span_label(span, fluent::lint::label)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,18 +29,20 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue {
|
|||
}
|
||||
}
|
||||
if let Some(t) = path_for_pass_by_value(cx, &inner_ty) {
|
||||
cx.struct_span_lint(PASS_BY_VALUE, ty.span, |lint| {
|
||||
lint.build(fluent::lint::pass_by_value)
|
||||
.set_arg("ty", t.clone())
|
||||
.span_suggestion(
|
||||
cx.struct_span_lint(
|
||||
PASS_BY_VALUE,
|
||||
ty.span,
|
||||
fluent::lint::pass_by_value,
|
||||
|lint| {
|
||||
lint.set_arg("ty", t.clone()).span_suggestion(
|
||||
ty.span,
|
||||
fluent::lint::suggestion,
|
||||
t,
|
||||
// Changing type of function argument
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -48,11 +48,18 @@ fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, boo
|
|||
return;
|
||||
}
|
||||
|
||||
cx.struct_span_lint(REDUNDANT_SEMICOLONS, span, |lint| {
|
||||
lint.build(fluent::lint::redundant_semicolons)
|
||||
.set_arg("multiple", multiple)
|
||||
.span_suggestion(span, fluent::lint::suggestion, "", Applicability::MaybeIncorrect)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
REDUNDANT_SEMICOLONS,
|
||||
span,
|
||||
fluent::lint::redundant_semicolons,
|
||||
|lint| {
|
||||
lint.set_arg("multiple", multiple).span_suggestion(
|
||||
span,
|
||||
fluent::lint::suggestion,
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,15 +100,18 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
|||
if trait_predicate.trait_ref.self_ty().is_impl_trait() {
|
||||
continue;
|
||||
}
|
||||
cx.struct_span_lint(DROP_BOUNDS, span, |lint| {
|
||||
let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
|
||||
return
|
||||
};
|
||||
lint.build(fluent::lint::drop_trait_constraints)
|
||||
.set_arg("predicate", predicate)
|
||||
.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
|
||||
.emit();
|
||||
});
|
||||
let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
|
||||
continue;
|
||||
};
|
||||
cx.struct_span_lint(
|
||||
DROP_BOUNDS,
|
||||
span,
|
||||
fluent::lint::drop_trait_constraints,
|
||||
|lint| {
|
||||
lint.set_arg("predicate", predicate)
|
||||
.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,14 +122,11 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
|||
};
|
||||
for bound in &bounds[..] {
|
||||
let def_id = bound.trait_ref.trait_def_id();
|
||||
if cx.tcx.lang_items().drop_trait() == def_id {
|
||||
cx.struct_span_lint(DYN_DROP, bound.span, |lint| {
|
||||
let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
|
||||
return
|
||||
};
|
||||
lint.build(fluent::lint::drop_glue)
|
||||
.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
|
||||
.emit();
|
||||
if cx.tcx.lang_items().drop_trait() == def_id
|
||||
&& let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop)
|
||||
{
|
||||
cx.struct_span_lint(DYN_DROP, bound.span, fluent::lint::drop_glue, |lint| {
|
||||
lint.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,12 +144,18 @@ fn lint_overflowing_range_endpoint<'tcx>(
|
|||
// We can suggest using an inclusive range
|
||||
// (`..=`) instead only if it is the `end` that is
|
||||
// overflowing and only by 1.
|
||||
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, struct_expr.span, |lint| {
|
||||
let mut err = lint.build(fluent::lint::range_endpoint_out_of_range);
|
||||
err.set_arg("ty", ty);
|
||||
if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
|
||||
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max
|
||||
&& let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span)
|
||||
{
|
||||
cx.struct_span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
struct_expr.span,
|
||||
fluent::lint::range_endpoint_out_of_range,
|
||||
|lint| {
|
||||
use ast::{LitIntType, LitKind};
|
||||
|
||||
lint.set_arg("ty", ty);
|
||||
|
||||
// We need to preserve the literal's suffix,
|
||||
// as it may determine typing information.
|
||||
let suffix = match lit.node {
|
||||
|
@ -159,16 +165,17 @@ fn lint_overflowing_range_endpoint<'tcx>(
|
|||
_ => bug!(),
|
||||
};
|
||||
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
|
||||
err.span_suggestion(
|
||||
lint.span_suggestion(
|
||||
struct_expr.span,
|
||||
fluent::lint::suggestion,
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
overwritten = true;
|
||||
}
|
||||
});
|
||||
|
||||
lint
|
||||
},
|
||||
);
|
||||
}
|
||||
overwritten
|
||||
}
|
||||
|
@ -221,52 +228,58 @@ fn report_bin_hex_error(
|
|||
negative: bool,
|
||||
) {
|
||||
let size = Integer::from_attr(&cx.tcx, ty).size();
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, expr.span, |lint| {
|
||||
let (t, actually) = match ty {
|
||||
attr::IntType::SignedInt(t) => {
|
||||
let actually = if negative {
|
||||
-(size.sign_extend(val) as i128)
|
||||
} else {
|
||||
size.sign_extend(val) as i128
|
||||
};
|
||||
(t.name_str(), actually.to_string())
|
||||
}
|
||||
attr::IntType::UnsignedInt(t) => {
|
||||
let actually = size.truncate(val);
|
||||
(t.name_str(), actually.to_string())
|
||||
}
|
||||
};
|
||||
let mut err = lint.build(fluent::lint::overflowing_bin_hex);
|
||||
if negative {
|
||||
// If the value is negative,
|
||||
// emits a note about the value itself, apart from the literal.
|
||||
err.note(fluent::lint::negative_note);
|
||||
err.note(fluent::lint::negative_becomes_note);
|
||||
} else {
|
||||
err.note(fluent::lint::positive_note);
|
||||
}
|
||||
if let Some(sugg_ty) =
|
||||
get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative)
|
||||
{
|
||||
err.set_arg("suggestion_ty", sugg_ty);
|
||||
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
|
||||
let (sans_suffix, _) = repr_str.split_at(pos);
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
fluent::lint::suggestion,
|
||||
format!("{}{}", sans_suffix, sugg_ty),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
cx.struct_span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
expr.span,
|
||||
fluent::lint::overflowing_bin_hex,
|
||||
|lint| {
|
||||
let (t, actually) = match ty {
|
||||
attr::IntType::SignedInt(t) => {
|
||||
let actually = if negative {
|
||||
-(size.sign_extend(val) as i128)
|
||||
} else {
|
||||
size.sign_extend(val) as i128
|
||||
};
|
||||
(t.name_str(), actually.to_string())
|
||||
}
|
||||
attr::IntType::UnsignedInt(t) => {
|
||||
let actually = size.truncate(val);
|
||||
(t.name_str(), actually.to_string())
|
||||
}
|
||||
};
|
||||
|
||||
if negative {
|
||||
// If the value is negative,
|
||||
// emits a note about the value itself, apart from the literal.
|
||||
lint.note(fluent::lint::negative_note);
|
||||
lint.note(fluent::lint::negative_becomes_note);
|
||||
} else {
|
||||
err.help(fluent::lint::help);
|
||||
lint.note(fluent::lint::positive_note);
|
||||
}
|
||||
}
|
||||
err.set_arg("ty", t);
|
||||
err.set_arg("lit", repr_str);
|
||||
err.set_arg("dec", val);
|
||||
err.set_arg("actually", actually);
|
||||
err.emit();
|
||||
});
|
||||
if let Some(sugg_ty) =
|
||||
get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative)
|
||||
{
|
||||
lint.set_arg("suggestion_ty", sugg_ty);
|
||||
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
|
||||
let (sans_suffix, _) = repr_str.split_at(pos);
|
||||
lint.span_suggestion(
|
||||
expr.span,
|
||||
fluent::lint::suggestion,
|
||||
format!("{}{}", sans_suffix, sugg_ty),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
lint.help(fluent::lint::help);
|
||||
}
|
||||
}
|
||||
lint.set_arg("ty", t)
|
||||
.set_arg("lit", repr_str)
|
||||
.set_arg("dec", val)
|
||||
.set_arg("actually", actually);
|
||||
|
||||
lint
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// This function finds the next fitting type and generates a suggestion string.
|
||||
|
@ -349,26 +362,27 @@ fn lint_int_literal<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
|
||||
let mut err = lint.build(fluent::lint::overflowing_int);
|
||||
err.set_arg("ty", t.name_str());
|
||||
err.set_arg(
|
||||
"lit",
|
||||
cx.sess()
|
||||
.source_map()
|
||||
.span_to_snippet(lit.span)
|
||||
.expect("must get snippet from literal"),
|
||||
);
|
||||
err.set_arg("min", min);
|
||||
err.set_arg("max", max);
|
||||
err.note(fluent::lint::note);
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint::overflowing_int, |lint| {
|
||||
lint.set_arg("ty", t.name_str())
|
||||
.set_arg(
|
||||
"lit",
|
||||
cx.sess()
|
||||
.source_map()
|
||||
.span_to_snippet(lit.span)
|
||||
.expect("must get snippet from literal"),
|
||||
)
|
||||
.set_arg("min", min)
|
||||
.set_arg("max", max)
|
||||
.note(fluent::lint::note);
|
||||
|
||||
if let Some(sugg_ty) =
|
||||
get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
|
||||
{
|
||||
err.set_arg("suggestion_ty", sugg_ty);
|
||||
err.help(fluent::lint::help);
|
||||
lint.set_arg("suggestion_ty", sugg_ty);
|
||||
lint.help(fluent::lint::help);
|
||||
}
|
||||
err.emit();
|
||||
|
||||
lint
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -393,16 +407,19 @@ fn lint_uint_literal<'tcx>(
|
|||
match par_e.kind {
|
||||
hir::ExprKind::Cast(..) => {
|
||||
if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, par_e.span, |lint| {
|
||||
lint.build(fluent::lint::only_cast_u8_to_char)
|
||||
.span_suggestion(
|
||||
cx.struct_span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
par_e.span,
|
||||
fluent::lint::only_cast_u8_to_char,
|
||||
|lint| {
|
||||
lint.span_suggestion(
|
||||
par_e.span,
|
||||
fluent::lint::suggestion,
|
||||
format!("'\\u{{{:X}}}'", lit_val),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -424,9 +441,8 @@ fn lint_uint_literal<'tcx>(
|
|||
);
|
||||
return;
|
||||
}
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
|
||||
lint.build(fluent::lint::overflowing_uint)
|
||||
.set_arg("ty", t.name_str())
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint::overflowing_uint, |lint| {
|
||||
lint.set_arg("ty", t.name_str())
|
||||
.set_arg(
|
||||
"lit",
|
||||
cx.sess()
|
||||
|
@ -437,7 +453,6 @@ fn lint_uint_literal<'tcx>(
|
|||
.set_arg("min", min)
|
||||
.set_arg("max", max)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -467,19 +482,22 @@ fn lint_literal<'tcx>(
|
|||
_ => bug!(),
|
||||
};
|
||||
if is_infinite == Ok(true) {
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
|
||||
lint.build(fluent::lint::overflowing_literal)
|
||||
.set_arg("ty", t.name_str())
|
||||
.set_arg(
|
||||
"lit",
|
||||
cx.sess()
|
||||
.source_map()
|
||||
.span_to_snippet(lit.span)
|
||||
.expect("must get snippet from literal"),
|
||||
)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
e.span,
|
||||
fluent::lint::overflowing_literal,
|
||||
|lint| {
|
||||
lint.set_arg("ty", t.name_str())
|
||||
.set_arg(
|
||||
"lit",
|
||||
cx.sess()
|
||||
.source_map()
|
||||
.span_to_snippet(lit.span)
|
||||
.expect("must get snippet from literal"),
|
||||
)
|
||||
.note(fluent::lint::note)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -497,9 +515,12 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
|
|||
}
|
||||
hir::ExprKind::Binary(binop, ref l, ref r) => {
|
||||
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
|
||||
cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| {
|
||||
lint.build(fluent::lint::unused_comparisons).emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
UNUSED_COMPARISONS,
|
||||
e.span,
|
||||
fluent::lint::unused_comparisons,
|
||||
|lint| lint,
|
||||
);
|
||||
}
|
||||
}
|
||||
hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit),
|
||||
|
@ -1150,25 +1171,24 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
CItemKind::Definition => IMPROPER_CTYPES_DEFINITIONS,
|
||||
};
|
||||
|
||||
self.cx.struct_span_lint(lint, sp, |lint| {
|
||||
self.cx.struct_span_lint(lint, sp, fluent::lint::improper_ctypes, |lint| {
|
||||
let item_description = match self.mode {
|
||||
CItemKind::Declaration => "block",
|
||||
CItemKind::Definition => "fn",
|
||||
};
|
||||
let mut diag = lint.build(fluent::lint::improper_ctypes);
|
||||
diag.set_arg("ty", ty);
|
||||
diag.set_arg("desc", item_description);
|
||||
diag.span_label(sp, fluent::lint::label);
|
||||
lint.set_arg("ty", ty);
|
||||
lint.set_arg("desc", item_description);
|
||||
lint.span_label(sp, fluent::lint::label);
|
||||
if let Some(help) = help {
|
||||
diag.help(help);
|
||||
lint.help(help);
|
||||
}
|
||||
diag.note(note);
|
||||
lint.note(note);
|
||||
if let ty::Adt(def, _) = ty.kind() {
|
||||
if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) {
|
||||
diag.span_note(sp, fluent::lint::note);
|
||||
lint.span_note(sp, fluent::lint::note);
|
||||
}
|
||||
}
|
||||
diag.emit();
|
||||
lint
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1381,11 +1401,8 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
|
|||
cx.struct_span_lint(
|
||||
VARIANT_SIZE_DIFFERENCES,
|
||||
enum_definition.variants[largest_index].span,
|
||||
|lint| {
|
||||
lint.build(fluent::lint::variant_size_differences)
|
||||
.set_arg("largest", largest)
|
||||
.emit();
|
||||
},
|
||||
fluent::lint::variant_size_differences,
|
||||
|lint| lint.set_arg("largest", largest),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1493,25 +1510,16 @@ impl InvalidAtomicOrdering {
|
|||
|
||||
fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store])
|
||||
&& let Some((ordering_arg, invalid_ordering)) = match method {
|
||||
sym::load => Some((&args[0], sym::Release)),
|
||||
sym::store => Some((&args[1], sym::Acquire)),
|
||||
&& let Some((ordering_arg, invalid_ordering, msg)) = match method {
|
||||
sym::load => Some((&args[0], sym::Release, fluent::lint::atomic_ordering_load)),
|
||||
sym::store => Some((&args[1], sym::Acquire, fluent::lint::atomic_ordering_store)),
|
||||
_ => None,
|
||||
}
|
||||
&& let Some(ordering) = Self::match_ordering(cx, ordering_arg)
|
||||
&& (ordering == invalid_ordering || ordering == sym::AcqRel)
|
||||
{
|
||||
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, |diag| {
|
||||
if method == sym::load {
|
||||
diag.build(fluent::lint::atomic_ordering_load)
|
||||
.help(fluent::lint::help)
|
||||
.emit()
|
||||
} else {
|
||||
debug_assert_eq!(method, sym::store);
|
||||
diag.build(fluent::lint::atomic_ordering_store)
|
||||
.help(fluent::lint::help)
|
||||
.emit();
|
||||
}
|
||||
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, msg, |lint| {
|
||||
lint.help(fluent::lint::help)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1523,10 +1531,9 @@ impl InvalidAtomicOrdering {
|
|||
&& matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence))
|
||||
&& Self::match_ordering(cx, &args[0]) == Some(sym::Relaxed)
|
||||
{
|
||||
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, |diag| {
|
||||
diag.build(fluent::lint::atomic_ordering_fence)
|
||||
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, fluent::lint::atomic_ordering_fence, |lint| {
|
||||
lint
|
||||
.help(fluent::lint::help)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,9 +154,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
};
|
||||
|
||||
if let Some(must_use_op) = must_use_op {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, expr.span, |lint| {
|
||||
lint.build(fluent::lint::unused_op)
|
||||
.set_arg("op", must_use_op)
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, expr.span, fluent::lint::unused_op, |lint| {
|
||||
lint.set_arg("op", must_use_op)
|
||||
.span_label(expr.span, fluent::lint::label)
|
||||
.span_suggestion_verbose(
|
||||
expr.span.shrink_to_lo(),
|
||||
|
@ -164,14 +163,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
"let _ = ",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
op_warned = true;
|
||||
}
|
||||
|
||||
if !(type_permits_lack_of_use || fn_warned || op_warned) {
|
||||
cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| {
|
||||
lint.build(fluent::lint::unused_result).set_arg("ty", ty).emit();
|
||||
cx.struct_span_lint(UNUSED_RESULTS, s.span, fluent::lint::unused_result, |lint| {
|
||||
lint.set_arg("ty", ty)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -267,29 +265,35 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
}
|
||||
},
|
||||
ty::Closure(..) => {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
|
||||
// FIXME(davidtwco): this isn't properly translatable because of the
|
||||
// pre/post strings
|
||||
lint.build(fluent::lint::unused_closure)
|
||||
.set_arg("count", plural_len)
|
||||
.set_arg("pre", descr_pre)
|
||||
.set_arg("post", descr_post)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
UNUSED_MUST_USE,
|
||||
span,
|
||||
fluent::lint::unused_closure,
|
||||
|lint| {
|
||||
// FIXME(davidtwco): this isn't properly translatable because of the
|
||||
// pre/post strings
|
||||
lint.set_arg("count", plural_len)
|
||||
.set_arg("pre", descr_pre)
|
||||
.set_arg("post", descr_post)
|
||||
.note(fluent::lint::note)
|
||||
},
|
||||
);
|
||||
true
|
||||
}
|
||||
ty::Generator(..) => {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
|
||||
// FIXME(davidtwco): this isn't properly translatable because of the
|
||||
// pre/post strings
|
||||
lint.build(fluent::lint::unused_generator)
|
||||
.set_arg("count", plural_len)
|
||||
.set_arg("pre", descr_pre)
|
||||
.set_arg("post", descr_post)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
UNUSED_MUST_USE,
|
||||
span,
|
||||
fluent::lint::unused_generator,
|
||||
|lint| {
|
||||
// FIXME(davidtwco): this isn't properly translatable because of the
|
||||
// pre/post strings
|
||||
lint.set_arg("count", plural_len)
|
||||
.set_arg("pre", descr_pre)
|
||||
.set_arg("post", descr_post)
|
||||
.note(fluent::lint::note)
|
||||
},
|
||||
);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
|
@ -309,18 +313,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
descr_post_path: &str,
|
||||
) -> bool {
|
||||
if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, span, fluent::lint::unused_def, |lint| {
|
||||
// FIXME(davidtwco): this isn't properly translatable because of the pre/post
|
||||
// strings
|
||||
let mut err = lint.build(fluent::lint::unused_def);
|
||||
err.set_arg("pre", descr_pre_path);
|
||||
err.set_arg("post", descr_post_path);
|
||||
err.set_arg("def", cx.tcx.def_path_str(def_id));
|
||||
lint.set_arg("pre", descr_pre_path);
|
||||
lint.set_arg("post", descr_post_path);
|
||||
lint.set_arg("def", cx.tcx.def_path_str(def_id));
|
||||
// check for #[must_use = "..."]
|
||||
if let Some(note) = attr.value_str() {
|
||||
err.note(note.as_str());
|
||||
lint.note(note.as_str());
|
||||
}
|
||||
err.emit();
|
||||
lint
|
||||
});
|
||||
true
|
||||
} else {
|
||||
|
@ -357,25 +360,34 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
|
|||
fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
|
||||
if let hir::StmtKind::Semi(expr) = s.kind {
|
||||
if let hir::ExprKind::Path(_) = expr.kind {
|
||||
cx.struct_span_lint(PATH_STATEMENTS, s.span, |lint| {
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if ty.needs_drop(cx.tcx, cx.param_env) {
|
||||
let mut lint = lint.build(fluent::lint::path_statement_drop);
|
||||
if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
|
||||
lint.span_suggestion(
|
||||
s.span,
|
||||
fluent::lint::suggestion,
|
||||
format!("drop({});", snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
lint.span_help(s.span, fluent::lint::suggestion);
|
||||
}
|
||||
lint.emit();
|
||||
} else {
|
||||
lint.build(fluent::lint::path_statement_no_effect).emit();
|
||||
}
|
||||
});
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if ty.needs_drop(cx.tcx, cx.param_env) {
|
||||
cx.struct_span_lint(
|
||||
PATH_STATEMENTS,
|
||||
s.span,
|
||||
fluent::lint::path_statement_drop,
|
||||
|lint| {
|
||||
if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
|
||||
lint.span_suggestion(
|
||||
s.span,
|
||||
fluent::lint::suggestion,
|
||||
format!("drop({});", snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
lint.span_help(s.span, fluent::lint::suggestion);
|
||||
}
|
||||
lint
|
||||
},
|
||||
);
|
||||
} else {
|
||||
cx.struct_span_lint(
|
||||
PATH_STATEMENTS,
|
||||
s.span,
|
||||
fluent::lint::path_statement_no_effect,
|
||||
|lint| lint,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -545,22 +557,21 @@ trait UnusedDelimLint {
|
|||
} else {
|
||||
MultiSpan::from(value_span)
|
||||
};
|
||||
cx.struct_span_lint(self.lint(), primary_span, |lint| {
|
||||
let mut db = lint.build(fluent::lint::unused_delim);
|
||||
db.set_arg("delim", Self::DELIM_STR);
|
||||
db.set_arg("item", msg);
|
||||
cx.struct_span_lint(self.lint(), primary_span, fluent::lint::unused_delim, |lint| {
|
||||
lint.set_arg("delim", Self::DELIM_STR);
|
||||
lint.set_arg("item", msg);
|
||||
if let Some((lo, hi)) = spans {
|
||||
let replacement = vec![
|
||||
(lo, if keep_space.0 { " ".into() } else { "".into() }),
|
||||
(hi, if keep_space.1 { " ".into() } else { "".into() }),
|
||||
];
|
||||
db.multipart_suggestion(
|
||||
lint.multipart_suggestion(
|
||||
fluent::lint::suggestion,
|
||||
replacement,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
db.emit();
|
||||
lint
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1128,9 +1139,12 @@ impl UnusedImportBraces {
|
|||
ast::UseTreeKind::Nested(_) => return,
|
||||
};
|
||||
|
||||
cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| {
|
||||
lint.build(fluent::lint::unused_import_braces).set_arg("node", node_name).emit();
|
||||
});
|
||||
cx.struct_span_lint(
|
||||
UNUSED_IMPORT_BRACES,
|
||||
item.span,
|
||||
fluent::lint::unused_import_braces,
|
||||
|lint| lint.set_arg("node", node_name),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1179,15 +1193,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
|
|||
|
||||
for adj in cx.typeck_results().expr_adjustments(e) {
|
||||
if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
|
||||
cx.struct_span_lint(UNUSED_ALLOCATION, e.span, |lint| {
|
||||
lint.build(match m {
|
||||
cx.struct_span_lint(
|
||||
UNUSED_ALLOCATION,
|
||||
e.span,
|
||||
match m {
|
||||
adjustment::AutoBorrowMutability::Not => fluent::lint::unused_allocation,
|
||||
adjustment::AutoBorrowMutability::Mut { .. } => {
|
||||
fluent::lint::unused_allocation_mut
|
||||
}
|
||||
})
|
||||
.emit();
|
||||
});
|
||||
},
|
||||
|lint| lint,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue