mirror of
https://github.com/rust-lang/rust-clippy
synced 2025-02-17 06:28:42 +00:00
Merge pull request #3459 from flip1995/sugg_appl
Add Applicability to suggestion lints: Take 2
This commit is contained in:
commit
b2601beb35
33 changed files with 547 additions and 297 deletions
|
@ -532,6 +532,7 @@ impl EarlyLintPass for CfgAttrPass {
|
|||
"`cfg_attr` is deprecated for rustfmt and got replaced by tool_attributes",
|
||||
"use",
|
||||
format!("{}rustfmt::skip]", attr_style),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,15 @@
|
|||
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use if_chain::if_chain;
|
||||
use crate::rustc::ty;
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::ast::{Name, UintTy};
|
||||
use crate::utils::{contains_name, get_pat_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg,
|
||||
walk_ptrs_ty};
|
||||
use crate::utils::{
|
||||
contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability,
|
||||
span_lint_and_sugg, walk_ptrs_ty,
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
|
||||
/// **What it does:** Checks for naive byte counts
|
||||
///
|
||||
|
@ -89,14 +92,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
|
|||
} else {
|
||||
&filter_args[0]
|
||||
};
|
||||
span_lint_and_sugg(cx,
|
||||
NAIVE_BYTECOUNT,
|
||||
expr.span,
|
||||
"You appear to be counting bytes the naive way",
|
||||
"Consider using the bytecount crate",
|
||||
format!("bytecount::count({}, {})",
|
||||
snippet(cx, haystack.span, ".."),
|
||||
snippet(cx, needle.span, "..")));
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
NAIVE_BYTECOUNT,
|
||||
expr.span,
|
||||
"You appear to be counting bytes the naive way",
|
||||
"Consider using the bytecount crate",
|
||||
format!("bytecount::count({}, {})",
|
||||
snippet_with_applicability(cx, haystack.span, "..", &mut applicability),
|
||||
snippet_with_applicability(cx, needle.span, "..", &mut applicability)),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ use crate::rustc::{declare_tool_lint, lint_array};
|
|||
use if_chain::if_chain;
|
||||
use crate::syntax::ast;
|
||||
|
||||
use crate::utils::{in_macro, snippet_block, span_lint_and_sugg, span_lint_and_then};
|
||||
use crate::utils::{in_macro, snippet_block, snippet_block_with_applicability, span_lint_and_sugg, span_lint_and_then};
|
||||
use crate::utils::sugg::Sugg;
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
|
@ -128,12 +128,16 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) {
|
|||
then {
|
||||
match else_.node {
|
||||
ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => {
|
||||
span_lint_and_sugg(cx,
|
||||
COLLAPSIBLE_IF,
|
||||
block.span,
|
||||
"this `else { if .. }` block can be collapsed",
|
||||
"try",
|
||||
snippet_block(cx, else_.span, "..").into_owned());
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
COLLAPSIBLE_IF,
|
||||
block.span,
|
||||
"this `else { if .. }` block can be collapsed",
|
||||
"try",
|
||||
snippet_block_with_applicability(cx, else_.span, "..", &mut applicability).into_owned(),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use if_chain::if_chain;
|
||||
use crate::rustc::ty::TyKind;
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use if_chain::if_chain;
|
||||
|
||||
use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg};
|
||||
|
||||
|
@ -80,7 +81,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess {
|
|||
expr.span,
|
||||
&format!("Calling {} is more clear than this expression", replacement),
|
||||
"try",
|
||||
replacement);
|
||||
replacement,
|
||||
Applicability::Unspecified, // First resolve the TODO above
|
||||
);
|
||||
}
|
||||
},
|
||||
QPath::TypeRelative(..) => {},
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::source_map::Span;
|
||||
|
||||
use crate::utils::{snippet, span_lint_and_sugg, SpanlessEq};
|
||||
use crate::utils::{snippet_with_applicability, span_lint_and_sugg, SpanlessEq};
|
||||
|
||||
/// **What it does:** Checks for double comparions that could be simpified to a single expression.
|
||||
///
|
||||
|
@ -70,12 +71,19 @@ impl<'a, 'tcx> Pass {
|
|||
}
|
||||
macro_rules! lint_double_comparison {
|
||||
($op:tt) => {{
|
||||
let lhs_str = snippet(cx, llhs.span, "");
|
||||
let rhs_str = snippet(cx, lrhs.span, "");
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let lhs_str = snippet_with_applicability(cx, llhs.span, "", &mut applicability);
|
||||
let rhs_str = snippet_with_applicability(cx, lrhs.span, "", &mut applicability);
|
||||
let sugg = format!("{} {} {}", lhs_str, stringify!($op), rhs_str);
|
||||
span_lint_and_sugg(cx, DOUBLE_COMPARISONS, span,
|
||||
"This binary expression can be simplified",
|
||||
"try", sugg);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
DOUBLE_COMPARISONS,
|
||||
span,
|
||||
"This binary expression can be simplified",
|
||||
"try",
|
||||
sugg,
|
||||
applicability,
|
||||
);
|
||||
}}
|
||||
}
|
||||
match (op, lkind, rkind) {
|
||||
|
|
|
@ -11,12 +11,13 @@
|
|||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use if_chain::if_chain;
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::source_map::Spanned;
|
||||
use if_chain::if_chain;
|
||||
|
||||
use crate::consts::{constant, Constant};
|
||||
use crate::utils::paths;
|
||||
use crate::utils::{match_type, snippet, span_lint_and_sugg, walk_ptrs_ty};
|
||||
use crate::utils::{match_type, snippet_with_applicability, span_lint_and_sugg, walk_ptrs_ty};
|
||||
|
||||
/// **What it does:** Checks for calculation of subsecond microseconds or milliseconds
|
||||
/// from other `Duration` methods.
|
||||
|
@ -60,13 +61,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec {
|
|||
("subsec_nanos", 1_000) => "subsec_micros",
|
||||
_ => return,
|
||||
};
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
DURATION_SUBSEC,
|
||||
expr.span,
|
||||
&format!("Calling `{}()` is more concise than this calculation", suggested_fn),
|
||||
"try",
|
||||
format!("{}.{}()", snippet(cx, args[0].span, "_"), suggested_fn),
|
||||
format!("{}.{}()", snippet_with_applicability(cx, args[0].span, "_", &mut applicability), suggested_fn),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_ex
|
|||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::syntax::ast::*;
|
||||
|
||||
use crate::utils::span_lint_and_sugg;
|
||||
use crate::utils::span_help_and_lint;
|
||||
|
||||
/// **What it does:** Checks for usage of if expressions with an `else if` branch,
|
||||
/// but without a final `else` branch.
|
||||
|
@ -66,13 +66,12 @@ impl EarlyLintPass for ElseIfWithoutElse {
|
|||
|
||||
while let ExprKind::If(_, _, Some(ref els)) = item.node {
|
||||
if let ExprKind::If(_, _, None) = els.node {
|
||||
span_lint_and_sugg(
|
||||
span_help_and_lint(
|
||||
cx,
|
||||
ELSE_IF_WITHOUT_ELSE,
|
||||
els.span,
|
||||
"if expression with an `else if`, but without a final `else`",
|
||||
"add an `else` block here",
|
||||
String::new()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,15 +10,16 @@
|
|||
|
||||
use crate::rustc::hir;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use if_chain::if_chain;
|
||||
use crate::rustc::ty::TyKind;
|
||||
use std::f32;
|
||||
use std::f64;
|
||||
use std::fmt;
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::ast::*;
|
||||
use crate::syntax_pos::symbol::Symbol;
|
||||
use crate::utils::span_lint_and_sugg;
|
||||
use if_chain::if_chain;
|
||||
use std::f32;
|
||||
use std::f64;
|
||||
use std::fmt;
|
||||
|
||||
/// **What it does:** Checks for float literals with a precision greater
|
||||
/// than that supported by the underlying type
|
||||
|
@ -68,6 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision {
|
|||
"float has excessive precision",
|
||||
"consider changing the type or truncating it to",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,11 @@
|
|||
// except according to those terms.
|
||||
|
||||
|
||||
use super::utils::{get_arg_name, match_var, remove_blocks, snippet, span_lint_and_sugg};
|
||||
use super::utils::{get_arg_name, match_var, remove_blocks, snippet_with_applicability, span_lint_and_sugg};
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use if_chain::if_chain;
|
||||
|
||||
/// **What it does:** Checks for matches being used to destructure a single-variant enum
|
||||
|
@ -71,6 +72,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
if match_var(body, arg);
|
||||
|
||||
then {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
INFALLIBLE_DESTRUCTURING_MATCH,
|
||||
|
@ -80,10 +82,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
"try this",
|
||||
format!(
|
||||
"let {}({}) = {};",
|
||||
snippet(cx, variant_name.span, ".."),
|
||||
snippet(cx, local.pat.span, ".."),
|
||||
snippet(cx, target.span, ".."),
|
||||
snippet_with_applicability(cx, variant_name.span, "..", &mut applicability),
|
||||
snippet_with_applicability(cx, local.pat.span, "..", &mut applicability),
|
||||
snippet_with_applicability(cx, target.span, "..", &mut applicability),
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,13 @@
|
|||
use crate::rustc::hir::def_id::DefId;
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc::ty;
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_data_structures::fx::FxHashSet;
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::ast::{Lit, LitKind, Name};
|
||||
use crate::syntax::source_map::{Span, Spanned};
|
||||
use crate::utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_sugg, walk_ptrs_ty};
|
||||
use crate::utils::{get_item_name, in_macro, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty};
|
||||
|
||||
/// **What it does:** Checks for getting the length of something via `.len()`
|
||||
/// just to compare to zero, and suggests using `.is_empty()` where applicable.
|
||||
|
@ -223,7 +224,15 @@ fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr, lit: &Expr, op
|
|||
}
|
||||
}
|
||||
|
||||
fn check_len(cx: &LateContext<'_, '_>, span: Span, method_name: Name, args: &[Expr], lit: &Lit, op: &str, compare_to: u32) {
|
||||
fn check_len(
|
||||
cx: &LateContext<'_, '_>,
|
||||
span: Span,
|
||||
method_name: Name,
|
||||
args: &[Expr],
|
||||
lit: &Lit,
|
||||
op: &str,
|
||||
compare_to: u32,
|
||||
) {
|
||||
if let Spanned {
|
||||
node: LitKind::Int(lit, _),
|
||||
..
|
||||
|
@ -235,13 +244,15 @@ fn check_len(cx: &LateContext<'_, '_>, span: Span, method_name: Name, args: &[Ex
|
|||
}
|
||||
|
||||
if method_name == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
LEN_ZERO,
|
||||
span,
|
||||
&format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
|
||||
"using `is_empty` is clearer and more explicit",
|
||||
format!("{}{}.is_empty()", op, snippet(cx, args[0].span, "_")),
|
||||
format!("{}{}.is_empty()", op, snippet_with_applicability(cx, args[0].span, "_", &mut applicability)),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::ast::*;
|
||||
use crate::syntax_pos;
|
||||
use crate::utils::{snippet_opt, span_lint_and_sugg};
|
||||
|
@ -300,6 +301,7 @@ impl WarningType {
|
|||
"mistyped literal suffix",
|
||||
"did you mean to write",
|
||||
grouping_hint.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
),
|
||||
WarningType::UnreadableLiteral => span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -308,6 +310,7 @@ impl WarningType {
|
|||
"long literal lacking separators",
|
||||
"consider",
|
||||
grouping_hint.to_owned(),
|
||||
Applicability::MachineApplicable,
|
||||
),
|
||||
WarningType::LargeDigitGroups => span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -316,6 +319,7 @@ impl WarningType {
|
|||
"digit groups should be smaller",
|
||||
"consider",
|
||||
grouping_hint.to_owned(),
|
||||
Applicability::MachineApplicable,
|
||||
),
|
||||
WarningType::InconsistentDigitGrouping => span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -324,6 +328,7 @@ impl WarningType {
|
|||
"digits grouped inconsistently by underscores",
|
||||
"consider",
|
||||
grouping_hint.to_owned(),
|
||||
Applicability::MachineApplicable,
|
||||
),
|
||||
WarningType::DecimalRepresentation => span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -332,6 +337,7 @@ impl WarningType {
|
|||
"integer literal has a better hexadecimal representation",
|
||||
"consider",
|
||||
grouping_hint.to_owned(),
|
||||
Applicability::MachineApplicable,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -35,10 +35,12 @@ use crate::utils::{in_macro, sugg, sext};
|
|||
use crate::utils::usage::mutated_variables;
|
||||
use crate::consts::{constant, Constant};
|
||||
|
||||
use crate::utils::{get_enclosing_block, get_parent_expr, higher, is_integer_literal, is_refutable,
|
||||
last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt,
|
||||
span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, SpanlessEq};
|
||||
use crate::utils::paths;
|
||||
use crate::utils::{
|
||||
get_enclosing_block, get_parent_expr, higher, is_integer_literal, is_refutable, last_path_segment,
|
||||
match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt, snippet_with_applicability,
|
||||
span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, SpanlessEq,
|
||||
};
|
||||
|
||||
/// **What it does:** Checks for for-loops that manually copy items between
|
||||
/// slices that could be optimized by having a memcpy.
|
||||
|
@ -501,6 +503,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
// 1) it was ugly with big bodies;
|
||||
// 2) it was not indented properly;
|
||||
// 3) it wasn’t very smart (see #675).
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
WHILE_LET_LOOP,
|
||||
|
@ -509,9 +512,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
"try",
|
||||
format!(
|
||||
"while let {} = {} {{ .. }}",
|
||||
snippet(cx, arms[0].pats[0].span, ".."),
|
||||
snippet(cx, matchexpr.span, "..")
|
||||
snippet_with_applicability(cx, arms[0].pats[0].span, "..", &mut applicability),
|
||||
snippet_with_applicability(cx, matchexpr.span, "..", &mut applicability),
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -549,6 +553,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
"this loop could be written as a `for` loop",
|
||||
"try",
|
||||
format!("for {} in {} {{ .. }}", loop_var, iterator),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1004,7 +1009,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
|
|||
let big_sugg = manual_copies
|
||||
.into_iter()
|
||||
.map(|(dst_var, src_var)| {
|
||||
let start_str = Offset::positive(snippet_opt(cx, start.span).unwrap_or_else(|| "".into()));
|
||||
let start_str = Offset::positive(snippet(cx, start.span, "").to_string());
|
||||
let dst_offset = print_sum(&start_str, &dst_var.offset);
|
||||
let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name);
|
||||
let src_offset = print_sum(&start_str, &src_var.offset);
|
||||
|
@ -1027,6 +1032,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
|
|||
"it looks like you're manually copying between slices",
|
||||
"try replacing the loop by",
|
||||
big_sugg,
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1302,7 +1308,8 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx
|
|||
}
|
||||
|
||||
fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr], arg: &Expr, method_name: &str) {
|
||||
let object = snippet(cx, args[0].span, "_");
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability);
|
||||
let muta = if method_name == "iter_mut" {
|
||||
"mut "
|
||||
} else {
|
||||
|
@ -1316,6 +1323,7 @@ fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr], arg: &Expr, method_
|
|||
iteration methods",
|
||||
"to write this more concisely, try",
|
||||
format!("&{}{}", muta, object),
|
||||
applicability,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1345,7 +1353,8 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex
|
|||
_ => lint_iter_method(cx, args, arg, method_name),
|
||||
};
|
||||
} else {
|
||||
let object = snippet(cx, args[0].span, "_");
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
EXPLICIT_INTO_ITER_LOOP,
|
||||
|
@ -1354,6 +1363,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex
|
|||
iteration methods`",
|
||||
"to write this more concisely, try",
|
||||
object.to_string(),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
} else if method_name == "next" && match_trait_method(cx, arg, &paths::ITERATOR) {
|
||||
|
|
|
@ -11,15 +11,12 @@
|
|||
use crate::rustc::hir;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::ast::Ident;
|
||||
use crate::syntax::source_map::Span;
|
||||
use crate::utils::paths;
|
||||
use crate::utils::{
|
||||
in_macro, match_trait_method, match_type,
|
||||
remove_blocks, snippet,
|
||||
span_lint_and_sugg,
|
||||
};
|
||||
use crate::utils::{in_macro, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg};
|
||||
use if_chain::if_chain;
|
||||
use crate::syntax::ast::Ident;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Pass;
|
||||
|
@ -95,13 +92,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, name: Ident, path: &hir::Expr) {
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(None, ref path)) = path.node {
|
||||
if path.segments.len() == 1 && path.segments[0].ident == name {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MAP_CLONE,
|
||||
replace,
|
||||
"You are using an explicit closure for cloning elements",
|
||||
"Consider calling the dedicated `cloned` method",
|
||||
format!("{}.cloned()", snippet(cx, root, "..")),
|
||||
format!("{}.cloned()", snippet_with_applicability(cx, root, "..", &mut applicability)),
|
||||
applicability,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use crate::syntax::ast::LitKind;
|
|||
use crate::syntax::source_map::Span;
|
||||
use crate::utils::paths;
|
||||
use crate::utils::{expr_block, in_macro, is_allowed, is_expn_of, match_qpath, match_type,
|
||||
multispan_sugg, remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then,
|
||||
multispan_sugg, remove_blocks, snippet, snippet_with_applicability, 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};
|
||||
|
@ -268,8 +268,9 @@ fn report_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms:
|
|||
snippet(cx, arms[0].pats[0].span, ".."),
|
||||
snippet(cx, ex.span, ".."),
|
||||
expr_block(cx, &arms[0].body, None, ".."),
|
||||
els_str
|
||||
els_str,
|
||||
),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -477,13 +478,15 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &
|
|||
};
|
||||
if let Some(rb) = arm_ref {
|
||||
let suggestion = if rb == BindingAnnotation::Ref { "as_ref" } else { "as_mut" };
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MATCH_AS_REF,
|
||||
expr.span,
|
||||
&format!("use {}() instead", suggestion),
|
||||
"try this",
|
||||
format!("{}.{}()", snippet(cx, ex.span, "_"), suggestion)
|
||||
format!("{}.{}()", snippet_with_applicability(cx, ex.span, "_", &mut applicability), suggestion),
|
||||
applicability,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
use crate::rustc::hir::{Expr, ExprKind, MutMutable, QPath};
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::utils::{match_def_path, match_qpath, opt_def_id, paths, snippet, span_lint_and_sugg};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::utils::{match_def_path, match_qpath, opt_def_id, paths, snippet_with_applicability, span_lint_and_sugg};
|
||||
use if_chain::if_chain;
|
||||
|
||||
/// **What it does:** Checks for `mem::replace()` on an `Option` with
|
||||
|
@ -79,13 +80,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace {
|
|||
_ => return,
|
||||
};
|
||||
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MEM_REPLACE_OPTION_WITH_NONE,
|
||||
expr.span,
|
||||
"replacing an `Option` with `None`",
|
||||
"consider `Option::take()` instead",
|
||||
format!("{}.take()", snippet(cx, replaced_path.span, ""))
|
||||
format!("{}.take()", snippet_with_applicability(cx, replaced_path.span, "", &mut applicability)),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,9 @@ use crate::utils::sugg;
|
|||
use crate::utils::{
|
||||
get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty,
|
||||
iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type,
|
||||
match_var, method_calls, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, snippet_with_macro_callsite, span_lint,
|
||||
span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq,
|
||||
match_var, method_calls, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet,
|
||||
snippet_with_macro_callsite, snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then,
|
||||
span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq,
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
use matches::matches;
|
||||
|
@ -1035,13 +1036,15 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa
|
|||
};
|
||||
|
||||
if implements_trait(cx, arg_ty, default_trait_id, &[]) {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
OR_FUN_CALL,
|
||||
span,
|
||||
&format!("use of `{}` followed by a call to `{}`", name, path),
|
||||
"try this",
|
||||
format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_")),
|
||||
format!("{}.unwrap_or_default()", snippet_with_applicability(cx, self_expr.span, "_", &mut applicability)),
|
||||
applicability,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
@ -1111,6 +1114,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa
|
|||
&format!("use of `{}` followed by a function call", name),
|
||||
"try this",
|
||||
format!("{}_{}({})", name, suffix, sugg),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1153,11 +1157,15 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
|
|||
None
|
||||
}
|
||||
|
||||
fn generate_format_arg_snippet(cx: &LateContext<'_, '_>, a: &hir::Expr) -> String {
|
||||
fn generate_format_arg_snippet(
|
||||
cx: &LateContext<'_, '_>,
|
||||
a: &hir::Expr,
|
||||
applicability: &mut Applicability,
|
||||
) -> String {
|
||||
if let hir::ExprKind::AddrOf(_, ref format_arg) = a.node {
|
||||
if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.node {
|
||||
if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.node {
|
||||
return snippet(cx, format_arg_expr_tup[0].span, "..").into_owned();
|
||||
return snippet_with_applicability(cx, format_arg_expr_tup[0].span, "..", applicability).into_owned();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1208,11 +1216,12 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
|
|||
let span_replace_word = method_span.with_hi(span.hi());
|
||||
|
||||
if let Some(format_args) = extract_format_args(arg) {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let args_len = format_args.len();
|
||||
let args: Vec<String> = format_args
|
||||
.into_iter()
|
||||
.take(args_len - 1)
|
||||
.map(|a| generate_format_arg_snippet(cx, a))
|
||||
.map(|a| generate_format_arg_snippet(cx, a, &mut applicability))
|
||||
.collect();
|
||||
|
||||
let sugg = args.join(", ");
|
||||
|
@ -1224,12 +1233,14 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
|
|||
&format!("use of `{}` followed by a function call", name),
|
||||
"try this",
|
||||
format!("unwrap_or_else({} panic!({}))", closure, sugg),
|
||||
applicability,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let sugg: Cow<'_, _> = snippet(cx, arg.span, "..");
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let sugg: Cow<'_, _> = snippet_with_applicability(cx, arg.span, "..", &mut applicability);
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -1238,6 +1249,7 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
|
|||
&format!("use of `{}` followed by a function call", name),
|
||||
"try this",
|
||||
format!("unwrap_or_else({} {{ let msg = {}; panic!(msg) }}))", closure, sugg),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1354,6 +1366,7 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::
|
|||
"using '.clone()' on a ref-counted pointer",
|
||||
"try this",
|
||||
format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet(cx, arg.span, "_")),
|
||||
Applicability::Unspecified, // Sometimes unnecessary ::<_> after Rc/Arc/Weak
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1372,6 +1385,7 @@ fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::E
|
|||
return;
|
||||
};
|
||||
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
STRING_EXTEND_CHARS,
|
||||
|
@ -1380,10 +1394,11 @@ fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::E
|
|||
"try this",
|
||||
format!(
|
||||
"{}.push_str({}{})",
|
||||
snippet(cx, args[0].span, "_"),
|
||||
snippet_with_applicability(cx, args[0].span, "_", &mut applicability),
|
||||
ref_str,
|
||||
snippet(cx, target.span, "_")
|
||||
snippet_with_applicability(cx, target.span, "_", &mut applicability)
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1460,12 +1475,13 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args:
|
|||
let next_point = cx.sess().source_map().next_point(fold_args[0].span);
|
||||
let fold_span = next_point.with_hi(fold_args[2].span.hi() + BytePos(1));
|
||||
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let sugg = if replacement_has_args {
|
||||
format!(
|
||||
".{replacement}(|{s}| {r})",
|
||||
replacement = replacement_method_name,
|
||||
s = second_arg_ident,
|
||||
r = snippet(cx, right_expr.span, "EXPR"),
|
||||
r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability),
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
|
@ -1482,6 +1498,7 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args:
|
|||
"this `.fold` can be written more succinctly using another method",
|
||||
"try",
|
||||
sugg,
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1545,9 +1562,10 @@ fn lint_iter_nth(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::E
|
|||
fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir::Expr], is_mut: bool) {
|
||||
// Note: we don't want to lint `get_mut().unwrap` for HashMap or BTreeMap,
|
||||
// because they do not implement `IndexMut`
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let expr_ty = cx.tables.expr_ty(&get_args[0]);
|
||||
let get_args_str = if get_args.len() > 1 {
|
||||
snippet(cx, get_args[1].span, "_")
|
||||
snippet_with_applicability(cx, get_args[1].span, "_", &mut applicability)
|
||||
} else {
|
||||
return; // not linting on a .get().unwrap() chain or variant
|
||||
};
|
||||
|
@ -1586,9 +1604,10 @@ fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir::
|
|||
format!(
|
||||
"{}{}[{}]",
|
||||
borrow_str,
|
||||
snippet(cx, get_args[0].span, "_"),
|
||||
snippet_with_applicability(cx, get_args[0].span, "_", &mut applicability),
|
||||
get_args_str
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2004,22 +2023,26 @@ fn lint_chars_cmp(
|
|||
if let Some(segment) = single_segment_path(qpath);
|
||||
if segment.ident.name == "Some";
|
||||
then {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let self_ty = walk_ptrs_ty(cx.tables.expr_ty_adjusted(&args[0][0]));
|
||||
|
||||
if self_ty.sty != ty::Str {
|
||||
return false;
|
||||
}
|
||||
|
||||
span_lint_and_sugg(cx,
|
||||
lint,
|
||||
info.expr.span,
|
||||
&format!("you should use the `{}` method", suggest),
|
||||
"like this",
|
||||
format!("{}{}.{}({})",
|
||||
if info.eq { "" } else { "!" },
|
||||
snippet(cx, args[0][0].span, "_"),
|
||||
suggest,
|
||||
snippet(cx, arg_char[0].span, "_")));
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
lint,
|
||||
info.expr.span,
|
||||
&format!("you should use the `{}` method", suggest),
|
||||
"like this",
|
||||
format!("{}{}.{}({})",
|
||||
if info.eq { "" } else { "!" },
|
||||
snippet_with_applicability(cx, args[0][0].span, "_", &mut applicability),
|
||||
suggest,
|
||||
snippet_with_applicability(cx, arg_char[0].span, "_", &mut applicability)),
|
||||
applicability,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2035,10 +2058,10 @@ fn lint_chars_next_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprIn
|
|||
|
||||
/// Checks for the `CHARS_LAST_CMP` lint.
|
||||
fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool {
|
||||
if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_NEXT_CMP, "ends_with") {
|
||||
if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") {
|
||||
true
|
||||
} else {
|
||||
lint_chars_cmp(cx, info, &["chars", "next_back"], CHARS_NEXT_CMP, "ends_with")
|
||||
lint_chars_cmp(cx, info, &["chars", "next_back"], CHARS_LAST_CMP, "ends_with")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2055,6 +2078,7 @@ fn lint_chars_cmp_with_unwrap<'a, 'tcx>(
|
|||
if let hir::ExprKind::Lit(ref lit) = info.other.node;
|
||||
if let ast::LitKind::Char(c) = lit.node;
|
||||
then {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
lint,
|
||||
|
@ -2063,9 +2087,10 @@ fn lint_chars_cmp_with_unwrap<'a, 'tcx>(
|
|||
"like this",
|
||||
format!("{}{}.{}('{}')",
|
||||
if info.eq { "" } else { "!" },
|
||||
snippet(cx, args[0][0].span, "_"),
|
||||
snippet_with_applicability(cx, args[0][0].span, "_", &mut applicability),
|
||||
suggest,
|
||||
c)
|
||||
c),
|
||||
applicability,
|
||||
);
|
||||
|
||||
return true;
|
||||
|
@ -2096,7 +2121,8 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx h
|
|||
if let ast::LitKind::Str(r, _) = lit.node;
|
||||
if r.as_str().len() == 1;
|
||||
then {
|
||||
let snip = snippet(cx, arg.span, "..");
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let snip = snippet_with_applicability(cx, arg.span, "..", &mut applicability);
|
||||
let hint = format!("'{}'", &snip[1..snip.len() - 1]);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -2105,6 +2131,7 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx h
|
|||
"single-character string constant used as pattern",
|
||||
"try using a char instead",
|
||||
hint,
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2122,13 +2149,15 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_re
|
|||
let (base_res_ty, res_depth) = walk_ptrs_ty_depth(res_ty);
|
||||
let (base_rcv_ty, rcv_depth) = walk_ptrs_ty_depth(rcv_ty);
|
||||
if base_rcv_ty == base_res_ty && rcv_depth >= res_depth {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
USELESS_ASREF,
|
||||
expr.span,
|
||||
&format!("this call to `{}` does nothing", call_name),
|
||||
"try this",
|
||||
snippet(cx, recvr.span, "_").into_owned(),
|
||||
snippet_with_applicability(cx, recvr.span, "_", &mut applicability).to_string(),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2193,7 +2222,8 @@ fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: ty::T
|
|||
kind,
|
||||
),
|
||||
"call directly",
|
||||
method_name.to_owned(),
|
||||
method_name.to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,13 +12,14 @@
|
|||
//!
|
||||
//! This lint is **warn** by default
|
||||
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::ast::LitKind;
|
||||
use crate::syntax::source_map::Spanned;
|
||||
use crate::utils::{in_macro, snippet, span_lint, span_lint_and_sugg};
|
||||
use crate::utils::sugg::Sugg;
|
||||
use crate::utils::{in_macro, snippet_with_applicability, span_lint, span_lint_and_sugg};
|
||||
|
||||
/// **What it does:** Checks for expressions of the form `if c { true } else {
|
||||
/// false }`
|
||||
|
@ -73,7 +74,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
|
|||
use self::Expression::*;
|
||||
if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.node {
|
||||
let reduce = |ret, not| {
|
||||
let snip = Sugg::hir(cx, pred, "<predicate>");
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let snip = Sugg::hir_with_applicability(cx, pred, "<predicate>", &mut applicability);
|
||||
let snip = if not { !snip } else { snip };
|
||||
|
||||
let hint = if ret {
|
||||
|
@ -89,6 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
|
|||
"this if-then-else expression returns a bool literal",
|
||||
"you can reduce it to",
|
||||
hint,
|
||||
applicability,
|
||||
);
|
||||
};
|
||||
if let ExprKind::Block(ref then_block, _) = then_block.node {
|
||||
|
@ -140,31 +143,34 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
|
|||
}
|
||||
|
||||
if let ExprKind::Binary(Spanned { node: BinOpKind::Eq, .. }, ref left_side, ref right_side) = e.node {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
|
||||
(Bool(true), Other) => {
|
||||
let hint = snippet(cx, right_side.span, "..").into_owned();
|
||||
let hint = snippet_with_applicability(cx, right_side.span, "..", &mut applicability);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
BOOL_COMPARISON,
|
||||
e.span,
|
||||
"equality checks against true are unnecessary",
|
||||
"try simplifying it as shown",
|
||||
hint,
|
||||
hint.to_string(),
|
||||
applicability,
|
||||
);
|
||||
},
|
||||
(Other, Bool(true)) => {
|
||||
let hint = snippet(cx, left_side.span, "..").into_owned();
|
||||
let hint = snippet_with_applicability(cx, left_side.span, "..", &mut applicability);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
BOOL_COMPARISON,
|
||||
e.span,
|
||||
"equality checks against true are unnecessary",
|
||||
"try simplifying it as shown",
|
||||
hint,
|
||||
hint.to_string(),
|
||||
applicability,
|
||||
);
|
||||
},
|
||||
(Bool(false), Other) => {
|
||||
let hint = Sugg::hir(cx, right_side, "..");
|
||||
let hint = Sugg::hir_with_applicability(cx, right_side, "..", &mut applicability);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
BOOL_COMPARISON,
|
||||
|
@ -172,10 +178,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
|
|||
"equality checks against false can be replaced by a negation",
|
||||
"try simplifying it as shown",
|
||||
(!hint).to_string(),
|
||||
applicability,
|
||||
);
|
||||
},
|
||||
(Other, Bool(false)) => {
|
||||
let hint = Sugg::hir(cx, left_side, "..");
|
||||
let hint = Sugg::hir_with_applicability(cx, left_side, "..", &mut applicability);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
BOOL_COMPARISON,
|
||||
|
@ -183,6 +190,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
|
|||
"equality checks against false can be replaced by a negation",
|
||||
"try simplifying it as shown",
|
||||
(!hint).to_string(),
|
||||
applicability,
|
||||
);
|
||||
},
|
||||
_ => (),
|
||||
|
|
|
@ -8,10 +8,11 @@
|
|||
// except according to those terms.
|
||||
|
||||
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc::hir::def::Def;
|
||||
use crate::rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource};
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sugg};
|
||||
use std::ops::Deref;
|
||||
|
||||
|
@ -131,6 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
"statement can be reduced",
|
||||
"replace it with",
|
||||
snippet,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
|
||||
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::syntax::source_map::Spanned;
|
||||
use crate::utils::{in_macro, snippet, span_lint_and_sugg};
|
||||
use crate::utils::{in_macro, snippet_with_applicability, span_lint_and_sugg};
|
||||
|
||||
/// **What it does:** Checks for operations where precedence may be unclear
|
||||
/// and suggests to add parentheses. Currently it catches the following:
|
||||
|
@ -53,7 +54,7 @@ impl EarlyLintPass for Precedence {
|
|||
}
|
||||
|
||||
if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.node {
|
||||
let span_sugg = |expr: &Expr, sugg| {
|
||||
let span_sugg = |expr: &Expr, sugg, appl| {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
PRECEDENCE,
|
||||
|
@ -61,39 +62,41 @@ impl EarlyLintPass for Precedence {
|
|||
"operator precedence can trip the unwary",
|
||||
"consider parenthesizing your expression",
|
||||
sugg,
|
||||
appl,
|
||||
);
|
||||
};
|
||||
|
||||
if !is_bit_op(op) {
|
||||
return;
|
||||
}
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
match (is_arith_expr(left), is_arith_expr(right)) {
|
||||
(true, true) => {
|
||||
let sugg = format!(
|
||||
"({}) {} ({})",
|
||||
snippet(cx, left.span, ".."),
|
||||
snippet_with_applicability(cx, left.span, "..", &mut applicability),
|
||||
op.to_string(),
|
||||
snippet(cx, right.span, "..")
|
||||
snippet_with_applicability(cx, right.span, "..", &mut applicability)
|
||||
);
|
||||
span_sugg(expr, sugg);
|
||||
span_sugg(expr, sugg, applicability);
|
||||
},
|
||||
(true, false) => {
|
||||
let sugg = format!(
|
||||
"({}) {} {}",
|
||||
snippet(cx, left.span, ".."),
|
||||
snippet_with_applicability(cx, left.span, "..", &mut applicability),
|
||||
op.to_string(),
|
||||
snippet(cx, right.span, "..")
|
||||
snippet_with_applicability(cx, right.span, "..", &mut applicability)
|
||||
);
|
||||
span_sugg(expr, sugg);
|
||||
span_sugg(expr, sugg, applicability);
|
||||
},
|
||||
(false, true) => {
|
||||
let sugg = format!(
|
||||
"{} {} ({})",
|
||||
snippet(cx, left.span, ".."),
|
||||
snippet_with_applicability(cx, left.span, "..", &mut applicability),
|
||||
op.to_string(),
|
||||
snippet(cx, right.span, "..")
|
||||
snippet_with_applicability(cx, right.span, "..", &mut applicability)
|
||||
);
|
||||
span_sugg(expr, sugg);
|
||||
span_sugg(expr, sugg, applicability);
|
||||
},
|
||||
(false, false) => (),
|
||||
}
|
||||
|
@ -105,13 +108,15 @@ impl EarlyLintPass for Precedence {
|
|||
if let ExprKind::Lit(ref lit) = slf.node {
|
||||
match lit.node {
|
||||
LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
PRECEDENCE,
|
||||
expr.span,
|
||||
"unary minus has lower precedence than method call",
|
||||
"consider adding parentheses to clarify your intent",
|
||||
format!("-({})", snippet(cx, rhs.span, "..")),
|
||||
format!("-({})", snippet_with_applicability(cx, rhs.span, "..", &mut applicability)),
|
||||
applicability,
|
||||
);
|
||||
},
|
||||
_ => (),
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
|
||||
use crate::rustc::{declare_tool_lint, hir, lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::utils;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -69,7 +70,15 @@ impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass {
|
|||
|
||||
let msg = format!("use of `{}` with a `usize` casted to an `isize`", method);
|
||||
if let Some(sugg) = build_suggestion(cx, method, receiver_expr, cast_lhs_expr) {
|
||||
utils::span_lint_and_sugg(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg, "try", sugg);
|
||||
utils::span_lint_and_sugg(
|
||||
cx,
|
||||
PTR_OFFSET_WITH_CAST,
|
||||
expr.span,
|
||||
&msg,
|
||||
"try",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
utils::span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,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::{span_lint_and_sugg};
|
||||
|
||||
|
@ -58,13 +59,14 @@ impl EarlyLintPass for RedundantFieldNames {
|
|||
}
|
||||
if let ExprKind::Path(None, path) = &field.expr.node {
|
||||
if path.segments.len() == 1 && path.segments[0].ident == field.ident {
|
||||
span_lint_and_sugg (
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
REDUNDANT_FIELD_NAMES,
|
||||
field.span,
|
||||
"redundant field names in struct initialization",
|
||||
"replace it with",
|
||||
field.ident.to_string()
|
||||
field.ident.to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
// except according to those terms.
|
||||
|
||||
|
||||
use crate::syntax::ast::{Expr, ExprKind, UnOp};
|
||||
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::{Expr, ExprKind, UnOp};
|
||||
use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
|
||||
use if_chain::if_chain;
|
||||
use crate::utils::{snippet, span_lint_and_sugg};
|
||||
|
||||
/// **What it does:** Checks for usage of `*&` and `*&mut` in expressions.
|
||||
///
|
||||
|
@ -54,13 +55,15 @@ impl EarlyLintPass for Pass {
|
|||
if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.node;
|
||||
if let ExprKind::AddrOf(_, ref addrof_target) = without_parens(deref_target).node;
|
||||
then {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
DEREF_ADDROF,
|
||||
e.span,
|
||||
"immediately dereferencing a reference",
|
||||
"try this",
|
||||
format!("{}", snippet(cx, addrof_target.span, "_")),
|
||||
format!("{}", snippet_with_applicability(cx, addrof_target.span, "_", &mut applicability)),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +103,7 @@ impl EarlyLintPass for DerefPass {
|
|||
if let ExprKind::Paren(ref parened) = object.node;
|
||||
if let ExprKind::AddrOf(_, ref inner) = parened.node;
|
||||
then {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
REF_IN_DEREF,
|
||||
|
@ -108,9 +112,10 @@ impl EarlyLintPass for DerefPass {
|
|||
"try this",
|
||||
format!(
|
||||
"{}.{}",
|
||||
snippet(cx, inner.span, "_"),
|
||||
snippet(cx, field_name.span, "_")
|
||||
)
|
||||
snippet_with_applicability(cx, inner.span, "_", &mut applicability),
|
||||
snippet_with_applicability(cx, field_name.span, "_", &mut applicability)
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
// except according to those terms.
|
||||
|
||||
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use if_chain::if_chain;
|
||||
use crate::rustc::hir;
|
||||
use crate::rustc::hir::def::Def;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::utils::{match_def_path, span_lint_and_sugg};
|
||||
use if_chain::if_chain;
|
||||
|
||||
/// **What it does:** Checks for usage of `ATOMIC_X_INIT`, `ONCE_INIT`, and
|
||||
/// `uX/iX::MIN/MAX`.
|
||||
|
@ -61,6 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts {
|
|||
&format!("using `{}`", const_path.last().expect("empty path")),
|
||||
"try this",
|
||||
repl_snip.to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::source_map::Spanned;
|
||||
use crate::utils::SpanlessEq;
|
||||
use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty};
|
||||
|
@ -164,7 +165,7 @@ impl LintPass for StringLitAsBytes {
|
|||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||
use crate::syntax::ast::{LitKind, StrStyle};
|
||||
use crate::utils::{in_macro, snippet};
|
||||
use crate::utils::{in_macro, snippet, snippet_with_applicability};
|
||||
|
||||
if let ExprKind::MethodCall(ref path, _, ref args) = e.node {
|
||||
if path.ident.name == "as_bytes" {
|
||||
|
@ -177,6 +178,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
|
|||
} else {
|
||||
format!("\"{}\"", lit_content.as_str())
|
||||
};
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
if callsite.starts_with("include_str!") {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -184,7 +186,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
|
|||
e.span,
|
||||
"calling `as_bytes()` on `include_str!(..)`",
|
||||
"consider using `include_bytes!(..)` instead",
|
||||
snippet(cx, args[0].span, r#""foo""#).replacen("include_str", "include_bytes", 1),
|
||||
snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability).replacen(
|
||||
"include_str",
|
||||
"include_bytes",
|
||||
1,
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
} else if callsite == expanded
|
||||
&& lit_content.as_str().chars().all(|c| c.is_ascii())
|
||||
|
@ -196,7 +203,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
|
|||
e.span,
|
||||
"calling `as_bytes()` on a string literal",
|
||||
"consider using a byte string literal instead",
|
||||
format!("b{}", snippet(cx, args[0].span, r#""foo""#)),
|
||||
format!(
|
||||
"b{}",
|
||||
snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability)
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,21 +10,21 @@
|
|||
|
||||
use std::cmp;
|
||||
|
||||
use matches::matches;
|
||||
use crate::rustc::hir;
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::hir::intravisit::FnKind;
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use if_chain::if_chain;
|
||||
use crate::rustc::ty::TyKind;
|
||||
use crate::rustc::ty::FnSig;
|
||||
use crate::rustc::session::config::Config as SessionConfig;
|
||||
use crate::rustc_target::spec::abi::Abi;
|
||||
use crate::rustc::ty::{FnSig, TyKind};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::rustc_target::abi::LayoutOf;
|
||||
use crate::rustc_target::spec::abi::Abi;
|
||||
use crate::syntax::ast::NodeId;
|
||||
use crate::syntax_pos::Span;
|
||||
use crate::utils::{in_macro, is_copy, is_self_ty, span_lint_and_sugg, snippet};
|
||||
use crate::utils::{in_macro, is_copy, is_self_ty, snippet, span_lint_and_sugg};
|
||||
use if_chain::if_chain;
|
||||
use matches::matches;
|
||||
|
||||
/// **What it does:** Checks for functions taking arguments by reference, where
|
||||
/// the argument type is `Copy` and small enough to be more efficient to always
|
||||
|
@ -141,7 +141,9 @@ impl<'a, 'tcx> TriviallyCopyPassByRef {
|
|||
input.span,
|
||||
"this argument is passed by reference, but would be more efficient if passed by value",
|
||||
"consider passing by value instead",
|
||||
value_type);
|
||||
value_type,
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,28 +10,31 @@
|
|||
|
||||
#![allow(clippy::default_hash_types)]
|
||||
|
||||
use crate::consts::{constant, Constant};
|
||||
use crate::reexport::*;
|
||||
use crate::rustc::hir;
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use if_chain::if_chain;
|
||||
use crate::rustc::ty::{self, Ty, TyCtxt, TypeckTables};
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
|
||||
use crate::rustc::ty::layout::LayoutOf;
|
||||
use crate::rustc::ty::{self, Ty, TyCtxt, TypeckTables};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::rustc_target::spec::abi::Abi;
|
||||
use crate::rustc_typeck::hir_ty_to_ty;
|
||||
use crate::syntax::ast::{FloatTy, IntTy, UintTy};
|
||||
use crate::syntax::errors::DiagnosticBuilder;
|
||||
use crate::syntax::source_map::Span;
|
||||
use crate::utils::paths;
|
||||
use crate::utils::{
|
||||
clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment,
|
||||
match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt,
|
||||
snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext,
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeMap;
|
||||
use std::borrow::Cow;
|
||||
use crate::syntax::ast::{FloatTy, IntTy, UintTy};
|
||||
use crate::syntax::source_map::Span;
|
||||
use crate::syntax::errors::DiagnosticBuilder;
|
||||
use crate::rustc_target::spec::abi::Abi;
|
||||
use crate::utils::{comparisons, differing_macro_contexts, higher, in_constant, in_macro, last_path_segment, match_def_path, match_path,
|
||||
match_type, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint,
|
||||
span_lint_and_sugg, span_lint_and_then, clip, unsext, sext, int_bits};
|
||||
use crate::utils::paths;
|
||||
use crate::consts::{constant, Constant};
|
||||
|
||||
/// Handles all the linting of funky types
|
||||
pub struct TypePass;
|
||||
|
@ -331,19 +334,22 @@ fn check_ty_rptr(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool, lt:
|
|||
let ltopt = if lt.is_elided() {
|
||||
String::new()
|
||||
} else {
|
||||
format!("{} ", lt.name.ident().name.as_str())
|
||||
format!("{} ", lt.name.ident().as_str())
|
||||
};
|
||||
let mutopt = if mut_ty.mutbl == Mutability::MutMutable {
|
||||
"mut "
|
||||
} else {
|
||||
""
|
||||
};
|
||||
span_lint_and_sugg(cx,
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
BORROWED_BOX,
|
||||
ast_ty.span,
|
||||
"you seem to be trying to use `&Box<T>`. Consider using just `&T`",
|
||||
"try",
|
||||
format!("&{}{}{}", ltopt, mutopt, &snippet(cx, inner.span, ".."))
|
||||
format!("&{}{}{}", ltopt, mutopt, &snippet_with_applicability(cx, inner.span, "..", &mut applicability)),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
return; // don't recurse into the type
|
||||
}
|
||||
|
@ -537,6 +543,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg {
|
|||
"passing a unit value to a function",
|
||||
"if you intended to pass a unit value, use a unit literal instead",
|
||||
"()".to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -856,6 +863,7 @@ fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_fro
|
|||
if in_constant(cx, expr.id) { return }
|
||||
// The suggestion is to use a function call, so if the original expression
|
||||
// has parens on the outside, they are no longer needed.
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let opt = snippet_opt(cx, op.span);
|
||||
let sugg = if let Some(ref snip) = opt {
|
||||
if should_strip_parens(op, snip) {
|
||||
|
@ -864,6 +872,7 @@ fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_fro
|
|||
snip.as_str()
|
||||
}
|
||||
} else {
|
||||
applicability = Applicability::HasPlaceholders;
|
||||
".."
|
||||
};
|
||||
|
||||
|
@ -874,6 +883,7 @@ fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_fro
|
|||
&format!("casting {} to {} may become silently lossy if types change", cast_from, cast_to),
|
||||
"try",
|
||||
format!("{}::from({})", cast_to, sugg),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1093,7 +1103,8 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex
|
|||
}
|
||||
match cast_from.sty {
|
||||
ty::FnDef(..) | ty::FnPtr(_) => {
|
||||
let from_snippet = snippet(cx, cast_expr.span, "x");
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);
|
||||
|
||||
let to_nbits = int_ty_to_nbits(cast_to, cx.tcx);
|
||||
if to_nbits < cx.tcx.data_layout.pointer_size.bits() {
|
||||
|
@ -1103,7 +1114,8 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex
|
|||
expr.span,
|
||||
&format!("casting function pointer `{}` to `{}`, which truncates the value", from_snippet, cast_to),
|
||||
"try",
|
||||
format!("{} as usize", from_snippet)
|
||||
format!("{} as usize", from_snippet),
|
||||
applicability,
|
||||
);
|
||||
|
||||
} else if cast_to.sty != ty::Uint(UintTy::Usize) {
|
||||
|
@ -1113,7 +1125,8 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex
|
|||
expr.span,
|
||||
&format!("casting function pointer `{}` to `{}`", from_snippet, cast_to),
|
||||
"try",
|
||||
format!("{} as usize", from_snippet)
|
||||
format!("{} as usize", from_snippet),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -8,15 +8,16 @@
|
|||
// except according to those terms.
|
||||
|
||||
|
||||
use crate::utils::{in_macro, span_lint_and_sugg};
|
||||
use if_chain::if_chain;
|
||||
use crate::rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor};
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::ty;
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::syntax_pos::symbol::keywords::SelfType;
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::ast::NodeId;
|
||||
use crate::syntax_pos::symbol::keywords::SelfType;
|
||||
use crate::utils::{in_macro, span_lint_and_sugg};
|
||||
use if_chain::if_chain;
|
||||
|
||||
/// **What it does:** Checks for unnecessary repetition of structure name when a
|
||||
/// replacement with `Self` is applicable.
|
||||
|
@ -70,6 +71,7 @@ fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) {
|
|||
"unnecessary structure name repetition",
|
||||
"use the applicable keyword",
|
||||
"Self".to_owned(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ use crate::rustc::hir::*;
|
|||
use crate::rustc::hir::def::Def;
|
||||
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use crate::syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name};
|
||||
use crate::syntax::source_map::Span;
|
||||
|
@ -281,6 +282,7 @@ impl EarlyLintPass for DefaultHashTypes {
|
|||
&msg,
|
||||
"use",
|
||||
replace.to_string(),
|
||||
Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,44 +7,48 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use crate::reexport::*;
|
||||
use matches::matches;
|
||||
use if_chain::if_chain;
|
||||
use crate::rustc::hir;
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||
use crate::rustc::hir::def::Def;
|
||||
use crate::rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||
use crate::rustc::hir::intravisit::{NestedVisitorMap, Visitor};
|
||||
use crate::rustc::hir::Node;
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, Level, Lint, LintContext};
|
||||
use crate::rustc::session::Session;
|
||||
use crate::rustc::traits;
|
||||
use crate::rustc::ty::{self, Binder, Ty, TyCtxt, layout::{self, IntegerExt}, subst::Kind};
|
||||
use crate::rustc::ty::{
|
||||
self,
|
||||
layout::{self, IntegerExt},
|
||||
subst::Kind,
|
||||
Binder, Ty, TyCtxt,
|
||||
};
|
||||
use crate::rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart};
|
||||
use crate::syntax::ast::{self, LitKind};
|
||||
use crate::syntax::attr;
|
||||
use crate::syntax::errors::DiagnosticBuilder;
|
||||
use crate::syntax::source_map::{Span, DUMMY_SP};
|
||||
use crate::syntax::symbol::{keywords, Symbol};
|
||||
use if_chain::if_chain;
|
||||
use matches::matches;
|
||||
use std::borrow::Cow;
|
||||
use std::env;
|
||||
use std::mem;
|
||||
use std::str::FromStr;
|
||||
use std::rc::Rc;
|
||||
use crate::syntax::ast::{self, LitKind};
|
||||
use crate::syntax::attr;
|
||||
use crate::syntax::source_map::{Span, DUMMY_SP};
|
||||
use crate::syntax::errors::DiagnosticBuilder;
|
||||
use crate::syntax::symbol::{keywords, Symbol};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub mod camel_case;
|
||||
|
||||
pub mod author;
|
||||
pub mod comparisons;
|
||||
pub mod conf;
|
||||
pub mod constants;
|
||||
mod hir_utils;
|
||||
pub mod paths;
|
||||
pub mod sugg;
|
||||
pub mod inspector;
|
||||
pub mod internal_lints;
|
||||
pub mod author;
|
||||
pub mod paths;
|
||||
pub mod ptr;
|
||||
pub mod sugg;
|
||||
pub mod usage;
|
||||
pub use self::hir_utils::{SpanlessEq, SpanlessHash};
|
||||
|
||||
|
@ -101,11 +105,7 @@ pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) ->
|
|||
|
||||
tcx.push_item_path(&mut apb, def_id, false);
|
||||
|
||||
apb.names.len() == path.len()
|
||||
&& apb.names
|
||||
.into_iter()
|
||||
.zip(path.iter())
|
||||
.all(|(a, &b)| *a == *b)
|
||||
apb.names.len() == path.len() && apb.names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b)
|
||||
}
|
||||
|
||||
/// Check if type is struct, enum or union type with given def path.
|
||||
|
@ -137,12 +137,9 @@ pub fn match_var(expr: &Expr, var: Name) -> bool {
|
|||
false
|
||||
}
|
||||
|
||||
|
||||
pub fn last_path_segment(path: &QPath) -> &PathSegment {
|
||||
match *path {
|
||||
QPath::Resolved(_, ref path) => path.segments
|
||||
.last()
|
||||
.expect("A path must have at least one segment"),
|
||||
QPath::Resolved(_, ref path) => path.segments.last().expect("A path must have at least one segment"),
|
||||
QPath::TypeRelative(_, ref seg) => seg,
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +163,8 @@ pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool {
|
|||
QPath::Resolved(_, ref path) => match_path(path, segments),
|
||||
QPath::TypeRelative(ref ty, ref segment) => match ty.node {
|
||||
TyKind::Path(ref inner_path) => {
|
||||
!segments.is_empty() && match_qpath(inner_path, &segments[..(segments.len() - 1)])
|
||||
!segments.is_empty()
|
||||
&& match_qpath(inner_path, &segments[..(segments.len() - 1)])
|
||||
&& segment.ident.name == segments[segments.len() - 1]
|
||||
},
|
||||
_ => false,
|
||||
|
@ -199,9 +197,7 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool {
|
|||
/// Get the definition associated to a path.
|
||||
pub fn path_to_def(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<def::Def> {
|
||||
let crates = cx.tcx.crates();
|
||||
let krate = crates
|
||||
.iter()
|
||||
.find(|&&krate| cx.tcx.crate_name(krate) == path[0]);
|
||||
let krate = crates.iter().find(|&&krate| cx.tcx.crate_name(krate) == path[0]);
|
||||
if let Some(krate) = krate {
|
||||
let krate = DefId {
|
||||
krate: *krate,
|
||||
|
@ -254,10 +250,17 @@ pub fn implements_trait<'a, 'tcx>(
|
|||
ty_params: &[Kind<'tcx>],
|
||||
) -> bool {
|
||||
let ty = cx.tcx.erase_regions(&ty);
|
||||
let obligation =
|
||||
cx.tcx
|
||||
.predicate_for_trait_def(cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params);
|
||||
cx.tcx.infer_ctxt().enter(|infcx| infcx.predicate_must_hold(&obligation))
|
||||
let obligation = cx.tcx.predicate_for_trait_def(
|
||||
cx.param_env,
|
||||
traits::ObligationCause::dummy(),
|
||||
trait_id,
|
||||
0,
|
||||
ty,
|
||||
ty_params,
|
||||
);
|
||||
cx.tcx
|
||||
.infer_ctxt()
|
||||
.enter(|infcx| infcx.predicate_must_hold(&obligation))
|
||||
}
|
||||
|
||||
/// Check whether this type implements Drop.
|
||||
|
@ -326,14 +329,14 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a
|
|||
Some(matched)
|
||||
}
|
||||
|
||||
|
||||
/// Get the name of the item the expression is in, if available.
|
||||
pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr) -> Option<Name> {
|
||||
let parent_id = cx.tcx.hir.get_parent(expr.id);
|
||||
match cx.tcx.hir.find(parent_id) {
|
||||
Some(Node::Item(&Item { ref name, .. })) => Some(*name),
|
||||
Some(Node::TraitItem(&TraitItem { ident, .. })) |
|
||||
Some(Node::ImplItem(&ImplItem { ident, .. })) => Some(ident.name),
|
||||
Some(Node::TraitItem(&TraitItem { ident, .. })) | Some(Node::ImplItem(&ImplItem { ident, .. })) => {
|
||||
Some(ident.name)
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -366,15 +369,11 @@ impl<'tcx> Visitor<'tcx> for ContainsName {
|
|||
|
||||
/// check if an `Expr` contains a certain name
|
||||
pub fn contains_name(name: Name, expr: &Expr) -> bool {
|
||||
let mut cn = ContainsName {
|
||||
name,
|
||||
result: false,
|
||||
};
|
||||
let mut cn = ContainsName { name, result: false };
|
||||
cn.visit_expr(expr);
|
||||
cn.result
|
||||
}
|
||||
|
||||
|
||||
/// Convert a span to a code snippet if available, otherwise use default.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -385,6 +384,32 @@ pub fn snippet<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str)
|
|||
snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
|
||||
}
|
||||
|
||||
/// Same as `snippet`, but it adapts the applicability level by following rules:
|
||||
///
|
||||
/// - Applicability level `Unspecified` will never be changed.
|
||||
/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
|
||||
/// - If the default value is used and the applicability level is `MachineApplicable`, change it to
|
||||
/// `HasPlaceholders`
|
||||
pub fn snippet_with_applicability<'a, 'b, T: LintContext<'b>>(
|
||||
cx: &T,
|
||||
span: Span,
|
||||
default: &'a str,
|
||||
applicability: &mut Applicability,
|
||||
) -> Cow<'a, str> {
|
||||
if *applicability != Applicability::Unspecified && in_macro(span) {
|
||||
*applicability = Applicability::MaybeIncorrect;
|
||||
}
|
||||
snippet_opt(cx, span).map_or_else(
|
||||
|| {
|
||||
if *applicability == Applicability::MachineApplicable {
|
||||
*applicability = Applicability::HasPlaceholders;
|
||||
}
|
||||
Cow::Borrowed(default)
|
||||
},
|
||||
From::from,
|
||||
)
|
||||
}
|
||||
|
||||
/// Same as `snippet`, but should only be used when it's clear that the input span is
|
||||
/// not a macro argument.
|
||||
pub fn snippet_with_macro_callsite<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
|
||||
|
@ -411,6 +436,18 @@ pub fn snippet_block<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'
|
|||
trim_multiline(snip, true)
|
||||
}
|
||||
|
||||
/// Same as `snippet_block`, but adapts the applicability level by the rules of
|
||||
/// `snippet_with_applicabiliy`.
|
||||
pub fn snippet_block_with_applicability<'a, 'b, T: LintContext<'b>>(
|
||||
cx: &T,
|
||||
span: Span,
|
||||
default: &'a str,
|
||||
applicability: &mut Applicability,
|
||||
) -> Cow<'a, str> {
|
||||
let snip = snippet_with_applicability(cx, span, default, applicability);
|
||||
trim_multiline(snip, true)
|
||||
}
|
||||
|
||||
/// Returns a new Span that covers the full last line of the given Span
|
||||
pub fn last_line_of_span<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Span {
|
||||
let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
|
||||
|
@ -431,8 +468,7 @@ pub fn expr_block<'a, 'b, T: LintContext<'b>>(
|
|||
let string = option.unwrap_or_default();
|
||||
if in_macro(expr.span) {
|
||||
Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default)))
|
||||
}
|
||||
else if let ExprKind::Block(_, _) = expr.node {
|
||||
} else if let ExprKind::Block(_, _) = expr.node {
|
||||
Cow::Owned(format!("{}{}", code, string))
|
||||
} else if string.is_empty() {
|
||||
Cow::Owned(format!("{{ {} }}", code))
|
||||
|
@ -450,19 +486,15 @@ pub fn trim_multiline(s: Cow<'_, str>, ignore_first: bool) -> Cow<'_, str> {
|
|||
}
|
||||
|
||||
fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, ch: char) -> Cow<'_, str> {
|
||||
let x = s.lines()
|
||||
let x = s
|
||||
.lines()
|
||||
.skip(ignore_first as usize)
|
||||
.filter_map(|l| {
|
||||
if l.is_empty() {
|
||||
None
|
||||
} else {
|
||||
// ignore empty lines
|
||||
Some(
|
||||
l.char_indices()
|
||||
.find(|&(_, x)| x != ch)
|
||||
.unwrap_or((l.len(), ch))
|
||||
.0,
|
||||
)
|
||||
Some(l.char_indices().find(|&(_, x)| x != ch).unwrap_or((l.len(), ch)).0)
|
||||
}
|
||||
})
|
||||
.min()
|
||||
|
@ -505,7 +537,8 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext<'_, '_>, e: &Expr) -> Option<&'c
|
|||
|
||||
pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeId) -> Option<&'tcx Block> {
|
||||
let map = &cx.tcx.hir;
|
||||
let enclosing_node = map.get_enclosing_scope(node)
|
||||
let enclosing_node = map
|
||||
.get_enclosing_scope(node)
|
||||
.and_then(|enclosing_id| map.find(enclosing_id));
|
||||
if let Some(node) = enclosing_node {
|
||||
match node {
|
||||
|
@ -513,7 +546,8 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI
|
|||
Node::Item(&Item {
|
||||
node: ItemKind::Fn(_, _, _, eid),
|
||||
..
|
||||
}) | Node::ImplItem(&ImplItem {
|
||||
})
|
||||
| Node::ImplItem(&ImplItem {
|
||||
node: ImplItemKind::Method(_, eid),
|
||||
..
|
||||
}) => match cx.tcx.hir.body(eid).value.node {
|
||||
|
@ -617,7 +651,8 @@ pub fn span_lint_node_and_then(
|
|||
/// Add a span lint with a suggestion on how to fix it.
|
||||
///
|
||||
/// These suggestions can be parsed by rustfix to allow it to automatically fix your code.
|
||||
/// In the example below, `help` is `"try"` and `sugg` is the suggested replacement `".any(|x| x > 2)"`.
|
||||
/// In the example below, `help` is `"try"` and `sugg` is the suggested replacement `".any(|x| x >
|
||||
/// 2)"`.
|
||||
///
|
||||
/// ```ignore
|
||||
/// error: This `.fold` can be more succinctly expressed as `.any`
|
||||
|
@ -635,9 +670,10 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>(
|
|||
msg: &str,
|
||||
help: &str,
|
||||
sugg: String,
|
||||
applicability: Applicability,
|
||||
) {
|
||||
span_lint_and_then(cx, lint, sp, msg, |db| {
|
||||
db.span_suggestion_with_applicability(sp, help, sugg, Applicability::Unspecified);
|
||||
db.span_suggestion_with_applicability(sp, help, sugg, applicability);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -652,18 +688,12 @@ where
|
|||
I: IntoIterator<Item = (Span, String)>,
|
||||
{
|
||||
let sugg = CodeSuggestion {
|
||||
substitutions: vec![
|
||||
Substitution {
|
||||
parts: sugg.into_iter()
|
||||
.map(|(span, snippet)| {
|
||||
SubstitutionPart {
|
||||
snippet,
|
||||
span,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
],
|
||||
substitutions: vec![Substitution {
|
||||
parts: sugg
|
||||
.into_iter()
|
||||
.map(|(span, snippet)| SubstitutionPart { snippet, span })
|
||||
.collect(),
|
||||
}],
|
||||
msg: help_msg,
|
||||
show_code_when_inline: true,
|
||||
applicability: Applicability::Unspecified,
|
||||
|
@ -729,9 +759,7 @@ impl LimitStack {
|
|||
Self { stack: vec![limit] }
|
||||
}
|
||||
pub fn limit(&self) -> u64 {
|
||||
*self.stack
|
||||
.last()
|
||||
.expect("there should always be a value in the stack")
|
||||
*self.stack.last().expect("there should always be a value in the stack")
|
||||
}
|
||||
pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) {
|
||||
let stack = &mut self.stack;
|
||||
|
@ -744,10 +772,11 @@ impl LimitStack {
|
|||
}
|
||||
|
||||
pub fn get_attr<'a>(attrs: &'a [ast::Attribute], name: &'static str) -> impl Iterator<Item = &'a ast::Attribute> {
|
||||
attrs.iter().filter(move |attr|
|
||||
attr.path.segments.len() == 2 &&
|
||||
attr.path.segments[0].ident.to_string() == "clippy" &&
|
||||
attr.path.segments[1].ident.to_string() == name)
|
||||
attrs.iter().filter(move |attr| {
|
||||
attr.path.segments.len() == 2
|
||||
&& attr.path.segments[0].ident.to_string() == "clippy"
|
||||
&& attr.path.segments[1].ident.to_string() == name
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) {
|
||||
|
@ -769,7 +798,8 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'
|
|||
/// See also `is_direct_expn_of`.
|
||||
pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
|
||||
loop {
|
||||
let span_name_span = span.ctxt()
|
||||
let span_name_span = span
|
||||
.ctxt()
|
||||
.outer()
|
||||
.expn_info()
|
||||
.map(|ei| (ei.format.name(), ei.call_site));
|
||||
|
@ -792,7 +822,8 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
|
|||
/// `bar!` by
|
||||
/// `is_direct_expn_of`.
|
||||
pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
|
||||
let span_name_span = span.ctxt()
|
||||
let span_name_span = span
|
||||
.ctxt()
|
||||
.outer()
|
||||
.expn_info()
|
||||
.map(|ei| (ei.format.name(), ei.call_site));
|
||||
|
@ -855,23 +886,23 @@ pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat) -> bool {
|
|||
PatKind::Lit(..) | PatKind::Range(..) => true,
|
||||
PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
|
||||
PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)),
|
||||
PatKind::Struct(ref qpath, ref fields, _) => if is_enum_variant(cx, qpath, pat.hir_id) {
|
||||
true
|
||||
} else {
|
||||
are_refutable(cx, fields.iter().map(|field| &*field.node.pat))
|
||||
PatKind::Struct(ref qpath, ref fields, _) => {
|
||||
if is_enum_variant(cx, qpath, pat.hir_id) {
|
||||
true
|
||||
} else {
|
||||
are_refutable(cx, fields.iter().map(|field| &*field.node.pat))
|
||||
}
|
||||
},
|
||||
PatKind::TupleStruct(ref qpath, ref pats, _) => if is_enum_variant(cx, qpath, pat.hir_id) {
|
||||
true
|
||||
} else {
|
||||
are_refutable(cx, pats.iter().map(|pat| &**pat))
|
||||
PatKind::TupleStruct(ref qpath, ref pats, _) => {
|
||||
if is_enum_variant(cx, qpath, pat.hir_id) {
|
||||
true
|
||||
} else {
|
||||
are_refutable(cx, pats.iter().map(|pat| &**pat))
|
||||
}
|
||||
},
|
||||
PatKind::Slice(ref head, ref middle, ref tail) => {
|
||||
are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat))
|
||||
},
|
||||
PatKind::Slice(ref head, ref middle, ref tail) => are_refutable(
|
||||
cx,
|
||||
head.iter()
|
||||
.chain(middle)
|
||||
.chain(tail.iter())
|
||||
.map(|pat| &**pat),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -903,32 +934,37 @@ pub fn remove_blocks(expr: &Expr) -> &Expr {
|
|||
|
||||
pub fn opt_def_id(def: Def) -> Option<DefId> {
|
||||
match def {
|
||||
Def::Fn(id) |
|
||||
Def::Mod(id) |
|
||||
Def::Static(id, _) |
|
||||
Def::Variant(id) |
|
||||
Def::VariantCtor(id, ..) |
|
||||
Def::Enum(id) |
|
||||
Def::TyAlias(id) |
|
||||
Def::AssociatedTy(id) |
|
||||
Def::TyParam(id) |
|
||||
Def::ForeignTy(id) |
|
||||
Def::Struct(id) |
|
||||
Def::StructCtor(id, ..) |
|
||||
Def::Union(id) |
|
||||
Def::Trait(id) |
|
||||
Def::TraitAlias(id) |
|
||||
Def::Method(id) |
|
||||
Def::Const(id) |
|
||||
Def::AssociatedConst(id) |
|
||||
Def::Macro(id, ..) |
|
||||
Def::Existential(id) |
|
||||
Def::AssociatedExistential(id) |
|
||||
Def::SelfCtor(id)
|
||||
=> Some(id),
|
||||
Def::Fn(id)
|
||||
| Def::Mod(id)
|
||||
| Def::Static(id, _)
|
||||
| Def::Variant(id)
|
||||
| Def::VariantCtor(id, ..)
|
||||
| Def::Enum(id)
|
||||
| Def::TyAlias(id)
|
||||
| Def::AssociatedTy(id)
|
||||
| Def::TyParam(id)
|
||||
| Def::ForeignTy(id)
|
||||
| Def::Struct(id)
|
||||
| Def::StructCtor(id, ..)
|
||||
| Def::Union(id)
|
||||
| Def::Trait(id)
|
||||
| Def::TraitAlias(id)
|
||||
| Def::Method(id)
|
||||
| Def::Const(id)
|
||||
| Def::AssociatedConst(id)
|
||||
| Def::Macro(id, ..)
|
||||
| Def::Existential(id)
|
||||
| Def::AssociatedExistential(id)
|
||||
| Def::SelfCtor(id) => Some(id),
|
||||
|
||||
Def::Upvar(..) | Def::Local(_) | Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) |
|
||||
Def::ToolMod | Def::NonMacroAttr{..} | Def::Err => None,
|
||||
Def::Upvar(..)
|
||||
| Def::Local(_)
|
||||
| Def::Label(..)
|
||||
| Def::PrimTy(..)
|
||||
| Def::SelfTy(..)
|
||||
| Def::ToolMod
|
||||
| Def::NonMacroAttr { .. }
|
||||
| Def::Err => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1019,7 +1055,9 @@ pub fn get_arg_name(pat: &Pat) -> Option<ast::Name> {
|
|||
}
|
||||
|
||||
pub fn int_bits(tcx: TyCtxt<'_, '_, '_>, ity: ast::IntTy) -> u64 {
|
||||
layout::Integer::from_attr(&tcx, attr::IntType::SignedInt(ity)).size().bits()
|
||||
layout::Integer::from_attr(&tcx, attr::IntType::SignedInt(ity))
|
||||
.size()
|
||||
.bits()
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_wrap)]
|
||||
|
@ -1038,7 +1076,9 @@ pub fn unsext(tcx: TyCtxt<'_, '_, '_>, u: i128, ity: ast::IntTy) -> u128 {
|
|||
|
||||
/// clip unused bytes
|
||||
pub fn clip(tcx: TyCtxt<'_, '_, '_>, u: u128, ity: ast::UintTy) -> u128 {
|
||||
let bits = layout::Integer::from_attr(&tcx, attr::IntType::UnsignedInt(ity)).size().bits();
|
||||
let bits = layout::Integer::from_attr(&tcx, attr::IntType::UnsignedInt(ity))
|
||||
.size()
|
||||
.bits();
|
||||
let amt = 128 - bits;
|
||||
(u << amt) >> amt
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ use crate::syntax::parse::token;
|
|||
use crate::syntax::print::pprust::token_to_string;
|
||||
use crate::syntax::util::parser::AssocOp;
|
||||
use crate::syntax::ast;
|
||||
use crate::utils::{higher, snippet, snippet_opt};
|
||||
use crate::utils::{higher, in_macro, snippet, snippet_opt};
|
||||
use crate::syntax_pos::{BytePos, Pos};
|
||||
use crate::rustc_errors::Applicability;
|
||||
|
||||
|
@ -96,6 +96,29 @@ impl<'a> Sugg<'a> {
|
|||
Self::hir_opt(cx, expr).unwrap_or_else(|| Sugg::NonParen(Cow::Borrowed(default)))
|
||||
}
|
||||
|
||||
/// Same as `hir`, but it adapts the applicability level by following rules:
|
||||
///
|
||||
/// - Applicability level `Unspecified` will never be changed.
|
||||
/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
|
||||
/// - If the default value is used and the applicability level is `MachineApplicable`, change it to
|
||||
/// `HasPlaceholders`
|
||||
pub fn hir_with_applicability(
|
||||
cx: &LateContext<'_, '_>,
|
||||
expr: &hir::Expr,
|
||||
default: &'a str,
|
||||
applicability: &mut Applicability,
|
||||
) -> Self {
|
||||
if *applicability != Applicability::Unspecified && in_macro(expr.span) {
|
||||
*applicability = Applicability::MaybeIncorrect;
|
||||
}
|
||||
Self::hir_opt(cx, expr).unwrap_or_else(|| {
|
||||
if *applicability == Applicability::MachineApplicable {
|
||||
*applicability = Applicability::HasPlaceholders;
|
||||
}
|
||||
Sugg::NonParen(Cow::Borrowed(default))
|
||||
})
|
||||
}
|
||||
|
||||
/// Prepare a suggestion from an expression.
|
||||
pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self {
|
||||
use crate::syntax::ast::RangeLimits;
|
||||
|
|
|
@ -8,14 +8,15 @@
|
|||
// except according to those terms.
|
||||
|
||||
|
||||
use crate::consts::constant;
|
||||
use crate::rustc::hir::*;
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use if_chain::if_chain;
|
||||
use crate::rustc::ty::{self, Ty};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::source_map::Span;
|
||||
use crate::utils::{higher, is_copy, snippet, span_lint_and_sugg};
|
||||
use crate::consts::constant;
|
||||
use crate::utils::{higher, is_copy, snippet_with_applicability, span_lint_and_sugg};
|
||||
use if_chain::if_chain;
|
||||
|
||||
/// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would
|
||||
/// be possible.
|
||||
|
@ -76,10 +77,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
}
|
||||
|
||||
fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let snippet = match *vec_args {
|
||||
higher::VecArgs::Repeat(elem, len) => {
|
||||
if constant(cx, cx.tables, len).is_some() {
|
||||
format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len"))
|
||||
format!(
|
||||
"&[{}; {}]",
|
||||
snippet_with_applicability(cx, elem.span, "elem", &mut applicability),
|
||||
snippet_with_applicability(cx, len.span, "len", &mut applicability)
|
||||
)
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -87,7 +93,7 @@ fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecA
|
|||
higher::VecArgs::Vec(args) => if let Some(last) = args.iter().last() {
|
||||
let span = args[0].span.to(last.span);
|
||||
|
||||
format!("&[{}]", snippet(cx, span, ".."))
|
||||
format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability))
|
||||
} else {
|
||||
"&[]".into()
|
||||
},
|
||||
|
@ -100,6 +106,7 @@ fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecA
|
|||
"useless use of `vec!`",
|
||||
"you can use a slice directly",
|
||||
snippet,
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
// except according to those terms.
|
||||
|
||||
|
||||
use crate::utils::{snippet, span_lint, span_lint_and_sugg};
|
||||
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use std::borrow::Cow;
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::ast::*;
|
||||
use crate::syntax::parse::{parser, token};
|
||||
use crate::syntax::tokenstream::{ThinTokenStream, TokenStream};
|
||||
use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg};
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// **What it does:** This lint warns when you use `println!("")` to
|
||||
/// print a newline.
|
||||
|
@ -199,6 +200,7 @@ impl EarlyLintPass for Pass {
|
|||
"using `println!(\"\")`",
|
||||
"replace it with",
|
||||
"println!()".to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -237,9 +239,14 @@ impl EarlyLintPass for Pass {
|
|||
let check_tts = check_tts(cx, &mac.node.tts, true);
|
||||
if let Some(fmtstr) = check_tts.0 {
|
||||
if fmtstr == "" {
|
||||
let suggestion = check_tts
|
||||
.1
|
||||
.map_or(Cow::Borrowed("v"), |expr| snippet(cx, expr.span, "v"));
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let suggestion = check_tts.1.map_or_else(
|
||||
move || {
|
||||
applicability = Applicability::HasPlaceholders;
|
||||
Cow::Borrowed("v")
|
||||
},
|
||||
move |expr| snippet_with_applicability(cx, expr.span, "v", &mut applicability),
|
||||
);
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -248,6 +255,7 @@ impl EarlyLintPass for Pass {
|
|||
format!("using `writeln!({}, \"\")`", suggestion).as_str(),
|
||||
"replace it with",
|
||||
format!("writeln!({})", suggestion),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -255,6 +263,20 @@ impl EarlyLintPass for Pass {
|
|||
}
|
||||
}
|
||||
|
||||
/// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
|
||||
/// options. The first part of the tuple is `format_str` of the macros. The secund part of the tuple
|
||||
/// is in the `write[ln]!` case the expression the `format_str` should be written to.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// Calling this function on
|
||||
/// ```rust,ignore
|
||||
/// writeln!(buf, "string to write: {}", something)
|
||||
/// ```
|
||||
/// will return
|
||||
/// ```rust,ignore
|
||||
/// (Some("string to write: {}"), Some(buf))
|
||||
/// ```
|
||||
fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> (Option<String>, Option<Expr>) {
|
||||
use crate::fmt_macros::*;
|
||||
let tts = TokenStream::from(tts.clone());
|
||||
|
|
|
@ -5,9 +5,10 @@ error: if expression with an `else if`, but without a final `else`
|
|||
| ____________^
|
||||
52 | | println!("else if");
|
||||
53 | | }
|
||||
| |_____^ help: add an `else` block here
|
||||
| |_____^
|
||||
|
|
||||
= note: `-D clippy::else-if-without-else` implied by `-D warnings`
|
||||
= help: add an `else` block here
|
||||
|
||||
error: if expression with an `else if`, but without a final `else`
|
||||
--> $DIR/else_if_without_else.rs:59:12
|
||||
|
@ -16,7 +17,9 @@ error: if expression with an `else if`, but without a final `else`
|
|||
| ____________^
|
||||
60 | | println!("else if 2");
|
||||
61 | | }
|
||||
| |_____^ help: add an `else` block here
|
||||
| |_____^
|
||||
|
|
||||
= help: add an `else` block here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue