mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 15:14:29 +00:00
Merge pull request #3191 from vi/suggest_with_applicability
Use span_suggestion_with_applicability instead of span_suggestion
This commit is contained in:
commit
af2d6a0c14
35 changed files with 427 additions and 106 deletions
|
@ -6,6 +6,7 @@ use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
|||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use if_chain::if_chain;
|
||||
use crate::syntax::ast;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for `a = a op b` or `a = b commutative_op a`
|
||||
/// patterns.
|
||||
|
@ -78,7 +79,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
|
|||
let r = &sugg::Sugg::hir(cx, rhs, "..");
|
||||
let long =
|
||||
format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r));
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
&format!(
|
||||
"Did you mean {} = {} {} {} or {}? Consider replacing it with",
|
||||
|
@ -89,8 +90,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
|
|||
long
|
||||
),
|
||||
format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"or",
|
||||
long,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
db.span_suggestion(expr.span, "or", long);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -172,10 +179,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
|
|||
if let (Some(snip_a), Some(snip_r)) =
|
||||
(snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
|
||||
{
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"replace it with",
|
||||
format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -13,6 +13,7 @@ use crate::rustc::ty::{self, TyCtxt};
|
|||
use semver::Version;
|
||||
use crate::syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
|
||||
use crate::syntax::source_map::Span;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for items annotated with `#[inline(always)]`,
|
||||
/// unless the annotated function is empty or simply panics.
|
||||
|
@ -203,7 +204,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
|
|||
"useless lint attribute",
|
||||
|db| {
|
||||
sugg = sugg.replacen("#[", "#![", 1);
|
||||
db.span_suggestion(line_span, "if you just forgot a `!`, use", sugg);
|
||||
db.span_suggestion_with_applicability(
|
||||
line_span,
|
||||
"if you just forgot a `!`, use",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::syntax::source_map::Span;
|
|||
use crate::utils::{span_lint, span_lint_and_then};
|
||||
use crate::utils::sugg::Sugg;
|
||||
use crate::consts::{constant, Constant};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for incompatible bit masks in comparisons.
|
||||
///
|
||||
|
@ -138,7 +139,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask {
|
|||
"bit mask could be simplified with a call to `trailing_zeros`",
|
||||
|db| {
|
||||
let sugg = Sugg::hir(cx, left1, "...").maybe_par();
|
||||
db.span_suggestion(e.span, "try", format!("{}.trailing_zeros() >= {}", sugg, n.count_ones()));
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"try",
|
||||
format!("{}.trailing_zeros() >= {}", sugg, n.count_ones()),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID};
|
|||
use crate::syntax::source_map::{dummy_spanned, Span, DUMMY_SP};
|
||||
use crate::rustc_data_structures::thin_vec::ThinVec;
|
||||
use crate::utils::{in_macro, paths, match_type, snippet_opt, span_lint_and_then, SpanlessEq, get_trait_def_id, implements_trait};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for boolean expressions that can be written more
|
||||
/// concisely.
|
||||
|
@ -390,10 +391,13 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
|||
"this expression can be optimized out by applying boolean operations to the \
|
||||
outer expression",
|
||||
);
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"it would look like the following",
|
||||
suggest(self.cx, suggestion, &h2q.terminals).0,
|
||||
// nonminimal_bool can produce minimal but
|
||||
// not human readable expressions (#3141)
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -416,7 +420,16 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
|||
NONMINIMAL_BOOL,
|
||||
e.span,
|
||||
"this boolean expression can be simplified",
|
||||
|db| { db.span_suggestions(e.span, "try", suggestions); },
|
||||
|db| {
|
||||
db.span_suggestions_with_applicability(
|
||||
e.span,
|
||||
"try",
|
||||
suggestions,
|
||||
// nonminimal_bool can produce minimal but
|
||||
// not human readable expressions (#3141)
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
);
|
||||
};
|
||||
if improvements.is_empty() {
|
||||
|
|
|
@ -19,6 +19,7 @@ use crate::syntax::ast;
|
|||
|
||||
use crate::utils::{in_macro, snippet_block, span_lint_and_sugg, span_lint_and_then};
|
||||
use crate::utils::sugg::Sugg;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for nested `if` statements which can be collapsed
|
||||
/// by `&&`-combining their conditions and for `else { if ... }` expressions
|
||||
|
@ -133,11 +134,16 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &
|
|||
span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this if statement can be collapsed", |db| {
|
||||
let lhs = Sugg::ast(cx, check, "..");
|
||||
let rhs = Sugg::ast(cx, check_inner, "..");
|
||||
db.span_suggestion(expr.span,
|
||||
"try",
|
||||
format!("if {} {}",
|
||||
lhs.and(&rhs),
|
||||
snippet_block(cx, content.span, "..")));
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"try",
|
||||
format!(
|
||||
"if {} {}",
|
||||
lhs.and(&rhs),
|
||||
snippet_block(cx, content.span, ".."),
|
||||
),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::syntax::ast::*;
|
|||
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::utils::{in_macro, snippet, span_lint_and_then};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for constants with an explicit `'static` lifetime.
|
||||
///
|
||||
|
@ -60,7 +61,12 @@ impl StaticConst {
|
|||
lifetime.ident.span,
|
||||
"Constants have by default a `'static` lifetime",
|
||||
|db| {
|
||||
db.span_suggestion(ty.span, "consider removing `'static`", sugg);
|
||||
db.span_suggestion_with_applicability(
|
||||
ty.span,
|
||||
"consider removing `'static`",
|
||||
sugg,
|
||||
Applicability::MachineApplicable, //snippet
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -202,7 +202,8 @@ fn lint_match_arms(cx: &LateContext<'_, '_>, expr: &Expr) {
|
|||
|db| {
|
||||
db.span_note(i.body.span, "same as this");
|
||||
|
||||
// Note: this does not use `span_suggestion` on purpose: there is no clean way
|
||||
// Note: this does not use `span_suggestion_with_applicability` on purpose:
|
||||
// there is no clean way
|
||||
// to remove the other arm. Building a span and suggest to replace it to ""
|
||||
// makes an even more confusing error message. Also in order not to make up a
|
||||
// span for the whole pattern, the suggestion is only shown when there is only
|
||||
|
|
|
@ -6,6 +6,7 @@ use if_chain::if_chain;
|
|||
use crate::syntax::source_map::Span;
|
||||
use crate::utils::SpanlessEq;
|
||||
use crate::utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for uses of `contains_key` + `insert` on `HashMap`
|
||||
/// or `BTreeMap`.
|
||||
|
@ -139,14 +140,24 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> {
|
|||
snippet(self.cx, params[1].span, ".."),
|
||||
snippet(self.cx, params[2].span, ".."));
|
||||
|
||||
db.span_suggestion(self.span, "consider using", help);
|
||||
db.span_suggestion_with_applicability(
|
||||
self.span,
|
||||
"consider using",
|
||||
help,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
}
|
||||
else {
|
||||
let help = format!("{}.entry({})",
|
||||
snippet(self.cx, self.map.span, "map"),
|
||||
snippet(self.cx, params[1].span, ".."));
|
||||
|
||||
db.span_suggestion(self.span, "consider using", help);
|
||||
db.span_suggestion_with_applicability(
|
||||
self.span,
|
||||
"consider using",
|
||||
help,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::rustc::hir::*;
|
|||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for equal operands to comparison, logical and
|
||||
/// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`,
|
||||
|
@ -113,7 +114,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||
} else if lcpy && !rcpy && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) {
|
||||
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
|
||||
let lsnip = snippet(cx, l.span, "...").to_string();
|
||||
db.span_suggestion(left.span, "use the left value directly", lsnip);
|
||||
db.span_suggestion_with_applicability(
|
||||
left.span,
|
||||
"use the left value directly",
|
||||
lsnip,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
})
|
||||
} else if !lcpy && rcpy && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) {
|
||||
span_lint_and_then(
|
||||
|
@ -123,7 +129,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||
"needlessly taken reference of right operand",
|
||||
|db| {
|
||||
let rsnip = snippet(cx, r.span, "...").to_string();
|
||||
db.span_suggestion(right.span, "use the right value directly", rsnip);
|
||||
db.span_suggestion_with_applicability(
|
||||
right.span,
|
||||
"use the right value directly",
|
||||
rsnip,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -135,7 +146,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||
if (requires_ref || lcpy) && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) {
|
||||
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
|
||||
let lsnip = snippet(cx, l.span, "...").to_string();
|
||||
db.span_suggestion(left.span, "use the left value directly", lsnip);
|
||||
db.span_suggestion_with_applicability(
|
||||
left.span,
|
||||
"use the left value directly",
|
||||
lsnip,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
})
|
||||
}
|
||||
},
|
||||
|
@ -146,7 +162,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||
if (requires_ref || rcpy) && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) {
|
||||
span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| {
|
||||
let rsnip = snippet(cx, r.span, "...").to_string();
|
||||
db.span_suggestion(right.span, "use the right value directly", rsnip);
|
||||
db.span_suggestion_with_applicability(
|
||||
right.span,
|
||||
"use the right value directly",
|
||||
rsnip,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
})
|
||||
}
|
||||
},
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::rustc::{declare_tool_lint, lint_array};
|
|||
use crate::rustc::ty;
|
||||
use crate::rustc::hir::*;
|
||||
use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
#[allow(missing_copy_implementations)]
|
||||
pub struct EtaPass;
|
||||
|
@ -96,7 +97,12 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) {
|
|||
}
|
||||
span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| {
|
||||
if let Some(snippet) = snippet_opt(cx, caller.span) {
|
||||
db.span_suggestion(expr.span, "remove closure as shown", snippet);
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"remove closure as shown",
|
||||
snippet,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::syntax::ast::LitKind;
|
|||
use crate::syntax_pos::Span;
|
||||
use crate::utils::paths;
|
||||
use crate::utils::{in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for the use of `format!("string literal with no
|
||||
/// argument")` and `format!("{}", foo)` where `foo` is a string.
|
||||
|
@ -60,7 +61,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
then {
|
||||
let sugg = format!("{}.to_string()", snippet(cx, format_arg, "<arg>").into_owned());
|
||||
span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| {
|
||||
db.span_suggestion(expr.span, "consider using .to_string()", sugg);
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"consider using .to_string()",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +76,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
if tup.is_empty() {
|
||||
let sugg = format!("{}.to_string()", snippet(cx, expr.span, "<expr>").into_owned());
|
||||
span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| {
|
||||
db.span_suggestion(span, "consider using .to_string()", sugg);
|
||||
db.span_suggestion_with_applicability(
|
||||
span,
|
||||
"consider using .to_string()",
|
||||
sugg,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::rustc::hir::*;
|
|||
use crate::syntax::ast::NodeId;
|
||||
use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then};
|
||||
use crate::utils::{opt_def_id, paths, resolve_node};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for always-identical `Into`/`From`/`IntoIter` conversions.
|
||||
///
|
||||
|
@ -63,7 +64,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion {
|
|||
if same_tys(cx, a, b) {
|
||||
let sugg = snippet(cx, args[0].span, "<expr>").into_owned();
|
||||
span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| {
|
||||
db.span_suggestion(e.span, "consider removing `.into()`", sugg);
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"consider removing `.into()`",
|
||||
sugg,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +79,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion {
|
|||
if same_tys(cx, a, b) {
|
||||
let sugg = snippet(cx, args[0].span, "<expr>").into_owned();
|
||||
span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| {
|
||||
db.span_suggestion(e.span, "consider removing `.into_iter()`", sugg);
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"consider removing `.into_iter()`",
|
||||
sugg,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +99,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion {
|
|||
let sugg = snippet(cx, args[0].span.source_callsite(), "<expr>").into_owned();
|
||||
let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from"));
|
||||
span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| {
|
||||
db.span_suggestion(e.span, &sugg_msg, sugg);
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
&sugg_msg,
|
||||
sugg,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
|||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc::hir::*;
|
||||
use crate::utils::{match_qpath, paths, snippet, span_lint_and_then};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Lint for redundant pattern matching over `Result` or
|
||||
/// `Option`
|
||||
|
@ -77,10 +78,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
&format!("redundant pattern matching, consider using `{}`", good_method),
|
||||
|db| {
|
||||
let span = expr.span.with_hi(op.span.hi());
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
span,
|
||||
"try this",
|
||||
format!("if {}.{}", snippet(cx, op.span, "_"), good_method),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::rustc::hir::*;
|
|||
use crate::syntax::ast::{Attribute, Name};
|
||||
use crate::utils::span_lint_and_then;
|
||||
use crate::utils::sugg::DiagnosticBuilderExt;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for `#[inline]` on trait methods without bodies
|
||||
///
|
||||
|
@ -56,7 +57,7 @@ fn check_attrs(cx: &LateContext<'_, '_>, name: Name, attrs: &[Attribute]) {
|
|||
attr.span,
|
||||
&format!("use of `#[inline]` on trait method `{}` which has no body", name),
|
||||
|db| {
|
||||
db.suggest_remove_item(cx, attr.span, "remove");
|
||||
db.suggest_remove_item(cx, attr.span, "remove", Applicability::MachineApplicable);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::ast::*;
|
||||
|
||||
use crate::utils::{snippet_opt, span_lint_and_then};
|
||||
|
@ -152,7 +153,12 @@ impl IntPlusOne {
|
|||
|
||||
fn emit_warning(&self, cx: &EarlyContext<'_>, block: &Expr, recommendation: String) {
|
||||
span_lint_and_then(cx, INT_PLUS_ONE, block.span, "Unnecessary `>= y + 1` or `x - 1 >=`", |db| {
|
||||
db.span_suggestion(block.span, "change `>= y + 1` to `> y` as shown", recommendation);
|
||||
db.span_suggestion_with_applicability(
|
||||
block.span,
|
||||
"change `>= y + 1` to `> y` as shown",
|
||||
recommendation,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::rustc::{declare_tool_lint, lint_array};
|
|||
use crate::rustc::hir::*;
|
||||
use crate::utils::{snippet_opt, span_lint_and_then};
|
||||
use crate::rustc::ty::layout::LayoutOf;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for large size differences between variants on
|
||||
/// `enum`s.
|
||||
|
@ -96,11 +97,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
|
|||
VariantData::Unit(_) => unreachable!(),
|
||||
};
|
||||
if let Some(snip) = snippet_opt(cx, span) {
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
span,
|
||||
"consider boxing the large fields to reduce the total size of the \
|
||||
enum",
|
||||
format!("Box<{}>", snip),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::rustc::hir::BindingAnnotation;
|
|||
use crate::rustc::hir::def::Def;
|
||||
use crate::syntax::ast;
|
||||
use crate::utils::{snippet, span_lint_and_then};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for variable declarations immediately followed by a
|
||||
/// conditional affectation.
|
||||
|
@ -120,9 +121,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
|
|||
span,
|
||||
"`if _ { .. } else { .. }` is an expression",
|
||||
|db| {
|
||||
db.span_suggestion(span,
|
||||
"it is more idiomatic to write",
|
||||
sug);
|
||||
db.span_suggestion_with_applicability(
|
||||
span,
|
||||
"it is more idiomatic to write",
|
||||
sug,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
if !mutability.is_empty() {
|
||||
db.note("you might not need `mut` at all");
|
||||
}
|
||||
|
|
|
@ -1196,7 +1196,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx
|
|||
expr.span,
|
||||
"this range is empty so this for loop will never run",
|
||||
|db| {
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
arg.span,
|
||||
"consider using the following if you are attempting to iterate over this \
|
||||
range in reverse",
|
||||
|
@ -1206,6 +1206,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx
|
|||
dots = dots,
|
||||
start = start_snippet
|
||||
),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -228,16 +228,23 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr
|
|||
snippet(cx, binding.pat.span, "_"),
|
||||
snippet(cx, var_arg.span, "_"),
|
||||
snippet(cx, reduced_expr_span, "_"));
|
||||
db.span_suggestion(stmt.span, "try this", suggestion);
|
||||
db.span_suggestion_with_applicability(
|
||||
stmt.span,
|
||||
"try this",
|
||||
suggestion,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
} else {
|
||||
let suggestion = format!("if let {0}({1}) = {2} {{ ... }}",
|
||||
variant,
|
||||
snippet(cx, binding.pat.span, "_"),
|
||||
snippet(cx, var_arg.span, "_"));
|
||||
db.span_suggestion_with_applicability(stmt.span,
|
||||
"try this",
|
||||
suggestion,
|
||||
Applicability::Unspecified);
|
||||
db.span_suggestion_with_applicability(
|
||||
stmt.span,
|
||||
"try this",
|
||||
suggestion,
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::utils::{expr_block, is_allowed, is_expn_of, match_qpath, match_type,
|
|||
remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty};
|
||||
use crate::utils::sugg::Sugg;
|
||||
use crate::consts::{constant, Constant};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for matches with a single arm where an `if let`
|
||||
/// will usually suffice.
|
||||
|
@ -339,7 +340,12 @@ fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Ex
|
|||
};
|
||||
|
||||
if let Some(sugg) = sugg {
|
||||
db.span_suggestion(expr.span, "consider using an if/else expression", sugg);
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"consider using an if/else expression",
|
||||
sugg,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_macro, i
|
|||
use crate::utils::paths;
|
||||
use crate::utils::sugg;
|
||||
use crate::consts::{constant, Constant};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Pass;
|
||||
|
@ -1127,8 +1128,18 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp
|
|||
let refs: String = iter::repeat('&').take(n + 1).collect();
|
||||
let derefs: String = iter::repeat('*').take(n).collect();
|
||||
let explicit = format!("{}{}::clone({})", refs, ty, snip);
|
||||
db.span_suggestion(expr.span, "try dereferencing it", format!("{}({}{}).clone()", refs, derefs, snip.deref()));
|
||||
db.span_suggestion(expr.span, "or try being explicit about what type to clone", explicit);
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"try dereferencing it",
|
||||
format!("{}({}{}).clone()", refs, derefs, snip.deref()),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"or try being explicit about what type to clone",
|
||||
explicit,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
},
|
||||
);
|
||||
return; // don't report clone_on_copy
|
||||
|
@ -1169,7 +1180,12 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp
|
|||
}
|
||||
span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |db| {
|
||||
if let Some((text, snip)) = snip {
|
||||
db.span_suggestion(expr.span, text, snip);
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
text,
|
||||
snip,
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1639,7 +1655,12 @@ fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr,
|
|||
let map_or_func_snippet = snippet(cx, map_or_args[2].span, "..");
|
||||
let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet);
|
||||
span_lint_and_then(cx, OPTION_MAP_OR_NONE, expr.span, msg, |db| {
|
||||
db.span_suggestion(expr.span, "try using and_then instead", hint);
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"try using and_then instead",
|
||||
hint,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant
|
|||
use crate::utils::sugg::Sugg;
|
||||
use crate::syntax::ast::{LitKind, CRATE_NODE_ID};
|
||||
use crate::consts::{constant, Constant};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for function arguments and let bindings denoted as
|
||||
/// `ref`.
|
||||
|
@ -294,12 +295,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
l.pat.span,
|
||||
"`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead",
|
||||
|db| {
|
||||
db.span_suggestion(s.span,
|
||||
"try",
|
||||
format!("let {name}{tyopt} = {initref};",
|
||||
name=snippet(cx, i.span, "_"),
|
||||
tyopt=tyopt,
|
||||
initref=initref));
|
||||
db.span_suggestion_with_applicability(
|
||||
s.span,
|
||||
"try",
|
||||
format!(
|
||||
"let {name}{tyopt} = {initref};",
|
||||
name=snippet(cx, i.span, "_"),
|
||||
tyopt=tyopt,
|
||||
initref=initref,
|
||||
),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -317,8 +323,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
"boolean short circuit operator in statement may be clearer using an explicit test",
|
||||
|db| {
|
||||
let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg };
|
||||
db.span_suggestion(s.span, "replace it with",
|
||||
format!("if {} {{ {}; }}", sugg, &snippet(cx, b.span, "..")));
|
||||
db.span_suggestion_with_applicability(
|
||||
s.span,
|
||||
"replace it with",
|
||||
format!(
|
||||
"if {} {{ {}; }}",
|
||||
sugg,
|
||||
&snippet(cx, b.span, ".."),
|
||||
),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -363,10 +377,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
let lhs = Sugg::hir(cx, left, "..");
|
||||
let rhs = Sugg::hir(cx, right, "..");
|
||||
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"consider comparing them within some error",
|
||||
format!("({}).abs() < error", lhs - rhs),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
db.span_note(expr.span, "std::f32::EPSILON and std::f64::EPSILON are available.");
|
||||
});
|
||||
|
@ -534,7 +549,12 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) {
|
|||
}
|
||||
}
|
||||
}
|
||||
db.span_suggestion(expr.span, "try", snip.to_string());
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"try",
|
||||
snip.to_string(),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::syntax::ast::*;
|
|||
use crate::syntax::source_map::Span;
|
||||
use crate::syntax::visit::FnKind;
|
||||
use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for structure field patterns bound to wildcards.
|
||||
///
|
||||
|
@ -307,7 +308,12 @@ impl EarlyLintPass for MiscEarly {
|
|||
"Try not to call a closure in the expression where it is declared.",
|
||||
|db| if decl.inputs.is_empty() {
|
||||
let hint = snippet(cx, block.span, "..").into_owned();
|
||||
db.span_suggestion(expr.span, "Try doing something like: ", hint);
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"Try doing something like: ",
|
||||
hint,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -392,15 +398,17 @@ impl MiscEarly {
|
|||
lit.span,
|
||||
"this is a decimal constant",
|
||||
|db| {
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
lit.span,
|
||||
"if you mean to use a decimal constant, remove the `0` to remove confusion",
|
||||
src.trim_left_matches(|c| c == '_' || c == '0').to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
lit.span,
|
||||
"if you mean to use an octal constant, use `0o`",
|
||||
format!("0o{}", src.trim_left_matches(|c| c == '_' || c == '0')),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::rustc::hir::{BindingAnnotation, Expr, ExprKind, MutImmutable, Pat, Pa
|
|||
use crate::rustc::ty;
|
||||
use crate::rustc::ty::adjustment::{Adjust, Adjustment};
|
||||
use crate::utils::{in_macro, snippet_opt, span_lint_and_then};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for address of operations (`&`) that are going to
|
||||
/// be dereferenced immediately by the compiler.
|
||||
|
@ -75,7 +76,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
|
|||
by the compiler",
|
||||
|db| {
|
||||
if let Some(snippet) = snippet_opt(cx, inner.span) {
|
||||
db.span_suggestion(e.span, "change this to", snippet);
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"change this to",
|
||||
snippet,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -103,7 +109,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
|
|||
"this pattern creates a reference to a reference",
|
||||
|db| {
|
||||
if let Some(snippet) = snippet_opt(cx, name.span) {
|
||||
db.span_suggestion(pat.span, "change this to", snippet);
|
||||
db.span_suggestion_with_applicability(
|
||||
pat.span,
|
||||
"change this to",
|
||||
snippet,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::rustc::{declare_tool_lint, lint_array};
|
|||
use if_chain::if_chain;
|
||||
use crate::rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind};
|
||||
use crate::utils::{in_macro, snippet, span_lint_and_then};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for useless borrowed references.
|
||||
///
|
||||
|
@ -77,7 +78,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef {
|
|||
"this pattern takes a reference on something that is being de-referenced",
|
||||
|db| {
|
||||
let hint = snippet(cx, spanned_name.span, "..").into_owned();
|
||||
db.span_suggestion(pat.span, "try removing the `&ref` part and just keep", hint);
|
||||
db.span_suggestion_with_applicability(
|
||||
pat.span,
|
||||
"try removing the `&ref` part and just keep",
|
||||
hint,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use crate::utils::{get_trait_def_id, implements_trait, in_macro, is_copy, is_sel
|
|||
snippet, snippet_opt, span_lint_and_then};
|
||||
use crate::utils::ptr::get_spans;
|
||||
use std::borrow::Cow;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for functions taking arguments by value, but not
|
||||
/// consuming them in its
|
||||
|
@ -227,19 +228,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
|
|||
}).unwrap());
|
||||
then {
|
||||
let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_"));
|
||||
db.span_suggestion(input.span,
|
||||
"consider changing the type to",
|
||||
slice_ty);
|
||||
db.span_suggestion_with_applicability(
|
||||
input.span,
|
||||
"consider changing the type to",
|
||||
slice_ty,
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
|
||||
for (span, suggestion) in clone_spans {
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
span,
|
||||
&snippet_opt(cx, span)
|
||||
.map_or(
|
||||
"change the call to".into(),
|
||||
|x| Cow::from(format!("change `{}` to", x)),
|
||||
),
|
||||
suggestion.into()
|
||||
suggestion.into(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -252,10 +257,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
|
|||
if match_type(cx, ty, &paths::STRING) {
|
||||
if let Some(clone_spans) =
|
||||
get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) {
|
||||
db.span_suggestion(input.span, "consider changing the type to", "&str".to_string());
|
||||
db.span_suggestion_with_applicability(
|
||||
input.span,
|
||||
"consider changing the type to",
|
||||
"&str".to_string(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
|
||||
for (span, suggestion) in clone_spans {
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
span,
|
||||
&snippet_opt(cx, span)
|
||||
.map_or(
|
||||
|
@ -263,6 +273,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
|
|||
|x| Cow::from(format!("change `{}` to", x))
|
||||
),
|
||||
suggestion.into(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::syntax::source_map::Span;
|
|||
use crate::utils::paths;
|
||||
use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then};
|
||||
use crate::utils::sugg::DiagnosticBuilderExt;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for types with a `fn new() -> Self` method and no
|
||||
/// implementation of
|
||||
|
@ -129,7 +130,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
|
|||
impl_item.span,
|
||||
&format!("you should consider deriving a `Default` implementation for `{}`", self_ty),
|
||||
|db| {
|
||||
db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]");
|
||||
db.suggest_item_with_attr(
|
||||
cx,
|
||||
sp,
|
||||
"try this",
|
||||
"#[derive(Default)]",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
span_lint_and_then(
|
||||
|
@ -143,6 +150,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
|
|||
item.span,
|
||||
"try this",
|
||||
&create_new_without_default_suggest_msg(self_ty),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::syntax::source_map::Span;
|
|||
use crate::syntax_pos::MultiSpan;
|
||||
use crate::utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty};
|
||||
use crate::utils::ptr::get_spans;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** This lint checks for function arguments of type `&String`
|
||||
/// or `&Vec` unless the references are mutable. It will also suggest you
|
||||
|
@ -181,16 +182,22 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id:
|
|||
with non-Vec-based slices.",
|
||||
|db| {
|
||||
if let Some(ref snippet) = ty_snippet {
|
||||
db.span_suggestion(arg.span, "change this to", format!("&[{}]", snippet));
|
||||
db.span_suggestion_with_applicability(
|
||||
arg.span,
|
||||
"change this to",
|
||||
format!("&[{}]", snippet),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
for (clonespan, suggestion) in spans {
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
clonespan,
|
||||
&snippet_opt(cx, clonespan).map_or(
|
||||
"change the call to".into(),
|
||||
|x| Cow::Owned(format!("change `{}` to", x)),
|
||||
),
|
||||
suggestion.into(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -204,15 +211,21 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id:
|
|||
arg.span,
|
||||
"writing `&String` instead of `&str` involves a new object where a slice will do.",
|
||||
|db| {
|
||||
db.span_suggestion(arg.span, "change this to", "&str".into());
|
||||
db.span_suggestion_with_applicability(
|
||||
arg.span,
|
||||
"change this to",
|
||||
"&str".into(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
for (clonespan, suggestion) in spans {
|
||||
db.span_suggestion_short(
|
||||
db.span_suggestion_short_with_applicability(
|
||||
clonespan,
|
||||
&snippet_opt(cx, clonespan).map_or(
|
||||
"change the call to".into(),
|
||||
|x| Cow::Owned(format!("change `{}` to", x)),
|
||||
),
|
||||
suggestion.into(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -239,7 +252,12 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id:
|
|||
arg.span,
|
||||
"using a reference to `Cow` is not recommended.",
|
||||
|db| {
|
||||
db.span_suggestion(arg.span, "change this to", "&".to_owned() + &r);
|
||||
db.span_suggestion_with_applicability(
|
||||
arg.span,
|
||||
"change this to",
|
||||
"&".to_owned() + &r,
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::syntax::ptr::P;
|
|||
|
||||
use crate::utils::{match_def_path, match_type, span_lint_and_then};
|
||||
use crate::utils::paths::*;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for expressions that could be replaced by the question mark operator
|
||||
///
|
||||
|
@ -70,10 +71,11 @@ impl QuestionMarkPass {
|
|||
|db| {
|
||||
let receiver_str = &Sugg::hir(cx, subject, "..");
|
||||
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"replace_it_with",
|
||||
format!("{}?;", receiver_str),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
}
|
||||
)
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::syntax::source_map::Spanned;
|
|||
use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then, snippet_opt};
|
||||
use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq};
|
||||
use crate::utils::sugg::Sugg;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for calling `.step_by(0)` on iterators,
|
||||
/// which never terminates.
|
||||
|
@ -150,13 +151,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
let end = Sugg::hir(cx, y, "y");
|
||||
if let Some(is_wrapped) = &snippet_opt(cx, expr.span) {
|
||||
if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') {
|
||||
db.span_suggestion(expr.span,
|
||||
"use",
|
||||
format!("({}..={})", start, end));
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"use",
|
||||
format!("({}..={})", start, end),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
db.span_suggestion(expr.span,
|
||||
"use",
|
||||
format!("{}..={}", start, end));
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"use",
|
||||
format!("{}..={}", start, end),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -177,9 +184,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
|db| {
|
||||
let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string());
|
||||
let end = Sugg::hir(cx, y, "y");
|
||||
db.span_suggestion(expr.span,
|
||||
"use",
|
||||
format!("{}..{}", start, end));
|
||||
db.span_suggestion_with_applicability(
|
||||
expr.span,
|
||||
"use",
|
||||
format!("{}..{}", start, end),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use if_chain::if_chain;
|
|||
use crate::syntax::ast;
|
||||
use crate::syntax::source_map::Span;
|
||||
use crate::syntax::visit::FnKind;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint};
|
||||
|
||||
|
@ -108,7 +109,12 @@ impl ReturnPass {
|
|||
}
|
||||
span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| {
|
||||
if let Some(snippet) = snippet_opt(cx, inner_span) {
|
||||
db.span_suggestion(ret_span, "remove `return` as shown", snippet);
|
||||
db.span_suggestion_with_applicability(
|
||||
ret_span,
|
||||
"remove `return` as shown",
|
||||
snippet,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use if_chain::if_chain;
|
|||
use crate::rustc::ty;
|
||||
use crate::utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq};
|
||||
use crate::utils::sugg::Sugg;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for manual swapping.
|
||||
///
|
||||
|
@ -136,7 +137,12 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) {
|
|||
&format!("this looks like you are swapping{} manually", what),
|
||||
|db| {
|
||||
if !sugg.is_empty() {
|
||||
db.span_suggestion(span, "try", sugg);
|
||||
db.span_suggestion_with_applicability(
|
||||
span,
|
||||
"try",
|
||||
sugg,
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
|
||||
if replace {
|
||||
db.note("or maybe you should use `std::mem::replace`?");
|
||||
|
@ -180,8 +186,16 @@ fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block) {
|
|||
&format!("this looks like you are trying to swap{}", what),
|
||||
|db| {
|
||||
if !what.is_empty() {
|
||||
db.span_suggestion(span, "try",
|
||||
format!("std::mem::swap({}, {})", lhs, rhs));
|
||||
db.span_suggestion_with_applicability(
|
||||
span,
|
||||
"try",
|
||||
format!(
|
||||
"std::mem::swap({}, {})",
|
||||
lhs,
|
||||
rhs,
|
||||
),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
db.note("or maybe you should use `std::mem::replace`?");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::borrow::Cow;
|
|||
use crate::syntax::ast;
|
||||
use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then};
|
||||
use crate::utils::{opt_def_id, sugg};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// **What it does:** Checks for transmutes that can't ever be correct on any
|
||||
/// architecture.
|
||||
|
@ -245,7 +246,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty)
|
||||
};
|
||||
|
||||
db.span_suggestion(e.span, "try", sugg.to_string());
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"try",
|
||||
sugg.to_string(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
),
|
||||
(&ty::Int(_), &ty::RawPtr(_)) | (&ty::Uint(_), &ty::RawPtr(_)) => {
|
||||
|
@ -255,7 +261,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
e.span,
|
||||
"transmute from an integer to a pointer",
|
||||
|db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
|
||||
db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string());
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"try",
|
||||
arg.as_ty(&to_ty.to_string()).to_string(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
)
|
||||
},
|
||||
|
@ -312,7 +323,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_ref_ty)))
|
||||
};
|
||||
|
||||
db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string());
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"try",
|
||||
sugg::make_unop(deref, arg).to_string(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
),
|
||||
(&ty::Int(ast::IntTy::I32), &ty::Char) |
|
||||
|
@ -328,10 +344,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
} else {
|
||||
arg
|
||||
};
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"consider using",
|
||||
format!("std::char::from_u32({}).unwrap()", arg.to_string()),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -353,7 +370,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
e.span,
|
||||
&format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
|
||||
|db| {
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"consider using",
|
||||
format!(
|
||||
|
@ -361,6 +378,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
postfix,
|
||||
snippet(cx, args[0].span, ".."),
|
||||
),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
)
|
||||
|
@ -380,7 +398,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
} else {
|
||||
sugg_paren.addr_deref()
|
||||
};
|
||||
db.span_suggestion(e.span, "try", sugg.to_string());
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"try",
|
||||
sugg.to_string(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -394,7 +417,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
"transmute from a pointer to a pointer",
|
||||
|db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
|
||||
let sugg = arg.as_ty(cx.tcx.mk_ptr(to_ty));
|
||||
db.span_suggestion(e.span, "try", sugg.to_string());
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"try",
|
||||
sugg.to_string(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
),
|
||||
(&ty::Int(ast::IntTy::I8), &ty::Bool) | (&ty::Uint(ast::UintTy::U8), &ty::Bool) => {
|
||||
|
@ -406,10 +434,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
|db| {
|
||||
let arg = sugg::Sugg::hir(cx, &args[0], "..");
|
||||
let zero = sugg::Sugg::NonParen(Cow::from("0"));
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"consider using",
|
||||
sugg::make_binop(ast::BinOpKind::Ne, &arg, &zero).to_string(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
)
|
||||
|
@ -432,10 +461,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
} else {
|
||||
arg
|
||||
};
|
||||
db.span_suggestion(
|
||||
db.span_suggestion_with_applicability(
|
||||
e.span,
|
||||
"consider using",
|
||||
format!("{}::from_bits({})", to_ty, arg.to_string()),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
)
|
||||
|
|
|
@ -575,7 +575,7 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>(
|
|||
sugg: String,
|
||||
) {
|
||||
span_lint_and_then(cx, lint, sp, msg, |db| {
|
||||
db.span_suggestion(sp, help, sugg);
|
||||
db.span_suggestion_with_applicability(sp, help, sugg, Applicability::Unspecified);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ use crate::syntax::util::parser::AssocOp;
|
|||
use crate::syntax::ast;
|
||||
use crate::utils::{higher, snippet, snippet_opt};
|
||||
use crate::syntax_pos::{BytePos, Pos};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
/// A helper type to build suggestion correctly handling parenthesis.
|
||||
pub enum Sugg<'a> {
|
||||
|
@ -461,7 +462,7 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> {
|
|||
/// ```rust,ignore
|
||||
/// db.suggest_item_with_attr(cx, item, "#[derive(Default)]");
|
||||
/// ```
|
||||
fn suggest_item_with_attr<D: Display + ?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D);
|
||||
fn suggest_item_with_attr<D: Display + ?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D, applicability: Applicability);
|
||||
|
||||
/// Suggest to add an item before another.
|
||||
///
|
||||
|
@ -475,7 +476,7 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> {
|
|||
/// bar();
|
||||
/// }");
|
||||
/// ```
|
||||
fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str);
|
||||
fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str, applicability: Applicability);
|
||||
|
||||
/// Suggest to completely remove an item.
|
||||
///
|
||||
|
@ -488,19 +489,24 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> {
|
|||
/// ```rust,ignore
|
||||
/// db.suggest_remove_item(cx, item, "remove this")
|
||||
/// ```
|
||||
fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str);
|
||||
fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability);
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> {
|
||||
fn suggest_item_with_attr<D: Display + ?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D) {
|
||||
fn suggest_item_with_attr<D: Display + ?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D, applicability: Applicability) {
|
||||
if let Some(indent) = indentation(cx, item) {
|
||||
let span = item.with_hi(item.lo());
|
||||
|
||||
self.span_suggestion(span, msg, format!("{}\n{}", attr, indent));
|
||||
self.span_suggestion_with_applicability(
|
||||
span,
|
||||
msg,
|
||||
format!("{}\n{}", attr, indent),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str) {
|
||||
fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str, applicability: Applicability) {
|
||||
if let Some(indent) = indentation(cx, item) {
|
||||
let span = item.with_hi(item.lo());
|
||||
|
||||
|
@ -517,11 +523,16 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error
|
|||
})
|
||||
.collect::<String>();
|
||||
|
||||
self.span_suggestion(span, msg, format!("{}\n{}", new_item, indent));
|
||||
self.span_suggestion_with_applicability(
|
||||
span,
|
||||
msg,
|
||||
format!("{}\n{}", new_item, indent),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str) {
|
||||
fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability) {
|
||||
let mut remove_span = item;
|
||||
let hi = cx.sess().source_map().next_point(remove_span).hi();
|
||||
let fmpos = cx.sess().source_map().lookup_byte_offset(hi);
|
||||
|
@ -534,6 +545,11 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error
|
|||
}
|
||||
}
|
||||
|
||||
self.span_suggestion(remove_span, msg, String::new());
|
||||
self.span_suggestion_with_applicability(
|
||||
remove_span,
|
||||
msg,
|
||||
String::new(),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue