summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/loops
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/loops')
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_find.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/missing_spin_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_collect.rs48
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs4
12 files changed, 90 insertions, 56 deletions
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
index 215c83a7e..09b2376d5 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
@@ -106,7 +106,7 @@ fn get_binding(pat: &Pat<'_>) -> Option<HirId> {
hir_id = None;
return;
}
- if let BindingAnnotation::Unannotated = annotation {
+ if let BindingAnnotation::NONE = annotation {
hir_id = Some(id);
}
});
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index b31015d19..3fc569af8 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -119,11 +119,9 @@ fn build_manual_memcpy_suggestion<'tcx>(
let print_limit = |end: &Expr<'_>, end_str: &str, base: &Expr<'_>, sugg: MinifyingSugg<'static>| {
if_chain! {
- if let ExprKind::MethodCall(method, len_args, _) = end.kind;
+ if let ExprKind::MethodCall(method, recv, [], _) = end.kind;
if method.ident.name == sym::len;
- if len_args.len() == 1;
- if let Some(arg) = len_args.get(0);
- if path_to_local(arg) == path_to_local(base);
+ if path_to_local(recv) == path_to_local(base);
then {
if sugg.to_string() == end_str {
sugg::EMPTY.into()
@@ -343,10 +341,8 @@ fn get_slice_like_element_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Opti
fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
if_chain! {
- if let ExprKind::MethodCall(method, args, _) = expr.kind;
+ if let ExprKind::MethodCall(method, arg, [], _) = expr.kind;
if method.ident.name == sym::clone;
- if args.len() == 1;
- if let Some(arg) = args.get(0);
then { arg } else { expr }
}
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/missing_spin_loop.rs b/src/tools/clippy/clippy_lints/src/loops/missing_spin_loop.rs
index 0696afa39..8412875b1 100644
--- a/src/tools/clippy/clippy_lints/src/loops/missing_spin_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/missing_spin_loop.rs
@@ -33,7 +33,7 @@ fn unpack_cond<'tcx>(cond: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>) {
if_chain! {
if let ExprKind::Block(Block { stmts: [], expr: None, ..}, _) = body.kind;
- if let ExprKind::MethodCall(method, [callee, ..], _) = unpack_cond(cond).kind;
+ if let ExprKind::MethodCall(method, callee, ..) = unpack_cond(cond).kind;
if [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name);
if let ty::Adt(def, _substs) = cx.typeck_results().expr_ty(callee).kind();
if cx.tcx.is_diagnostic_item(sym::AtomicBool, def.did());
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index ed270bd49..74f3bda9f 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -742,7 +742,7 @@ fn check_for_loop<'tcx>(
fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) {
let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
- if let ExprKind::MethodCall(method, [self_arg], _) = arg.kind {
+ if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind {
let method_name = method.ident.as_str();
// check for looping over x.iter() or x.iter_mut(), could use &x or &mut x
match method_name {
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index aedf3810b..fce2d5463 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -44,7 +44,7 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId>
if_chain! {
if let Some(hir_id) = path_to_local(bound);
if let Node::Pat(pat) = cx.tcx.hir().get(hir_id);
- if let PatKind::Binding(BindingAnnotation::Mutable, ..) = pat.kind;
+ if let PatKind::Binding(BindingAnnotation::MUT, ..) = pat.kind;
then {
return Some(hir_id);
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
index ddaffc751..6e6faa79a 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
@@ -1,5 +1,6 @@
use super::NEEDLESS_COLLECT;
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
+use clippy_utils::higher;
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_diagnostic_item;
@@ -24,11 +25,11 @@ pub(super) fn check<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
}
fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
if_chain! {
- if let ExprKind::MethodCall(method, args, _) = expr.kind;
- if let ExprKind::MethodCall(chain_method, _, _) = args[0].kind;
- if chain_method.ident.name == sym!(collect) && is_trait_method(cx, &args[0], sym::Iterator);
+ if let ExprKind::MethodCall(method, receiver, args, _) = expr.kind;
+ if let ExprKind::MethodCall(chain_method, ..) = receiver.kind;
+ if chain_method.ident.name == sym!(collect) && is_trait_method(cx, receiver, sym::Iterator);
then {
- let ty = cx.typeck_results().expr_ty(&args[0]);
+ let ty = cx.typeck_results().expr_ty(receiver);
let mut applicability = Applicability::MaybeIncorrect;
let is_empty_sugg = "next().is_none()".to_string();
let method_name = method.ident.name.as_str();
@@ -40,7 +41,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
"len" => "count()".to_string(),
"is_empty" => is_empty_sugg,
"contains" => {
- let contains_arg = snippet_with_applicability(cx, args[1].span, "??", &mut applicability);
+ let contains_arg = snippet_with_applicability(cx, args[0].span, "??", &mut applicability);
let (arg, pred) = contains_arg
.strip_prefix('&')
.map_or(("&x", &*contains_arg), |s| ("x", s));
@@ -79,7 +80,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
if let StmtKind::Local(local) = stmt.kind;
if let PatKind::Binding(_, id, ..) = local.pat.kind;
if let Some(init_expr) = local.init;
- if let ExprKind::MethodCall(method_name, &[ref iter_source], ..) = init_expr.kind;
+ if let ExprKind::MethodCall(method_name, iter_source, [], ..) = init_expr.kind;
if method_name.ident.name == sym!(collect) && is_trait_method(cx, init_expr, sym::Iterator);
let ty = cx.typeck_results().expr_ty(init_expr);
if is_type_diagnostic_item(cx, ty, sym::Vec) ||
@@ -184,16 +185,25 @@ struct IterFunctionVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> {
fn visit_block(&mut self, block: &'tcx Block<'tcx>) {
for (expr, hir_id) in block.stmts.iter().filter_map(get_expr_and_hir_id_from_stmt) {
+ if check_loop_kind(expr).is_some() {
+ continue;
+ }
self.visit_block_expr(expr, hir_id);
}
if let Some(expr) = block.expr {
- self.visit_block_expr(expr, None);
+ if let Some(loop_kind) = check_loop_kind(expr) {
+ if let LoopKind::Conditional(block_expr) = loop_kind {
+ self.visit_block_expr(block_expr, None);
+ }
+ } else {
+ self.visit_block_expr(expr, None);
+ }
}
}
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
// Check function calls on our collection
- if let ExprKind::MethodCall(method_name, [recv, args @ ..], _) = &expr.kind {
+ if let ExprKind::MethodCall(method_name, recv, [args @ ..], _) = &expr.kind {
if method_name.ident.name == sym!(collect) && is_trait_method(self.cx, expr, sym::Iterator) {
self.current_mutably_captured_ids = get_captured_ids(self.cx, self.cx.typeck_results().expr_ty(recv));
self.visit_expr(recv);
@@ -264,6 +274,28 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> {
}
}
+enum LoopKind<'tcx> {
+ Conditional(&'tcx Expr<'tcx>),
+ Loop,
+}
+
+fn check_loop_kind<'tcx>(expr: &Expr<'tcx>) -> Option<LoopKind<'tcx>> {
+ if let Some(higher::WhileLet { let_expr, .. }) = higher::WhileLet::hir(expr) {
+ return Some(LoopKind::Conditional(let_expr));
+ }
+ if let Some(higher::While { condition, .. }) = higher::While::hir(expr) {
+ return Some(LoopKind::Conditional(condition));
+ }
+ if let Some(higher::ForLoop { arg, .. }) = higher::ForLoop::hir(expr) {
+ return Some(LoopKind::Conditional(arg));
+ }
+ if let ExprKind::Loop { .. } = expr.kind {
+ return Some(LoopKind::Loop);
+ }
+
+ None
+}
+
impl<'tcx> IterFunctionVisitor<'_, 'tcx> {
fn visit_block_expr(&mut self, expr: &'tcx Expr<'tcx>, hir_id: Option<HirId>) {
self.current_statement_hir_id = hir_id;
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index a7ef562b2..8ab640051 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -188,10 +188,9 @@ pub(super) fn check<'tcx>(
fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool {
if_chain! {
- if let ExprKind::MethodCall(method, len_args, _) = expr.kind;
- if len_args.len() == 1;
+ if let ExprKind::MethodCall(method, recv, [], _) = expr.kind;
if method.ident.name == sym::len;
- if let ExprKind::Path(QPath::Resolved(_, path)) = len_args[0].kind;
+ if let ExprKind::Path(QPath::Resolved(_, path)) = recv.kind;
if path.segments.len() == 1;
if path.segments[0].ident.name == var;
then {
@@ -302,7 +301,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if_chain! {
// a range index op
- if let ExprKind::MethodCall(meth, [args_0, args_1, ..], _) = &expr.kind;
+ if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind;
if (meth.ident.name == sym::index && match_trait_method(self.cx, expr, &paths::INDEX))
|| (meth.ident.name == sym::index_mut && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
if !self.check(args_1, args_0, expr);
@@ -357,9 +356,12 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
self.visit_expr(expr);
}
},
- ExprKind::MethodCall(_, args, _) => {
+ ExprKind::MethodCall(_, receiver, args, _) => {
let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
- for (ty, expr) in iter::zip(self.cx.tcx.fn_sig(def_id).inputs().skip_binder(), args) {
+ for (ty, expr) in iter::zip(
+ self.cx.tcx.fn_sig(def_id).inputs().skip_binder(),
+ std::iter::once(receiver).chain(args.iter()),
+ ) {
self.prefer_mutable = false;
if let ty::Ref(_, _, mutbl) = *ty.kind() {
if mutbl == Mutability::Mut {
@@ -371,7 +373,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
},
ExprKind::Closure(&Closure { body, .. }) => {
let body = self.cx.tcx.hir().body(body);
- self.visit_expr(&body.value);
+ self.visit_expr(body.value);
},
_ => walk_expr(self, expr),
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index 32de20f65..116e589ca 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -120,8 +120,9 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
| ExprKind::Repeat(e, _)
| ExprKind::DropTemps(e) => never_loop_expr(e, main_loop_id),
ExprKind::Let(let_expr) => never_loop_expr(let_expr.init, main_loop_id),
- ExprKind::Array(es) | ExprKind::MethodCall(_, es, _) | ExprKind::Tup(es) => {
- never_loop_expr_all(&mut es.iter(), main_loop_id)
+ ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(&mut es.iter(), main_loop_id),
+ ExprKind::MethodCall(_, receiver, es, _) => {
+ never_loop_expr_all(&mut std::iter::once(receiver).chain(es.iter()), main_loop_id)
},
ExprKind::Struct(_, fields, base) => {
let fields = never_loop_expr_all(&mut fields.iter().map(|f| f.expr), main_loop_id);
@@ -178,9 +179,9 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
never_loop_expr(expr, main_loop_id)
},
- InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter(), main_loop_id),
+ InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter().copied(), main_loop_id),
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
- never_loop_expr_all(&mut once(in_expr).chain(out_expr.iter()), main_loop_id)
+ never_loop_expr_all(&mut once(*in_expr).chain(out_expr.iter().copied()), main_loop_id)
},
InlineAsmOperand::Const { .. }
| InlineAsmOperand::SymFn { .. }
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index 1439f1f4c..aeefe6e33 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -7,7 +7,7 @@ use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Node, Pat, PatKind, Stmt, StmtKind};
+use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Mutability, Node, Pat, PatKind, Stmt, StmtKind};
use rustc_lint::LateContext;
use rustc_span::symbol::sym;
use std::iter::Iterator;
@@ -65,7 +65,7 @@ pub(super) fn check<'tcx>(
if_chain! {
if let Node::Pat(pat) = node;
if let PatKind::Binding(bind_ann, ..) = pat.kind;
- if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable);
+ if !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut));
let parent_node = cx.tcx.hir().get_parent_node(hir_id);
if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node);
if let Some(init) = parent_let_expr.init;
@@ -180,10 +180,9 @@ fn get_vec_push<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) -> Option<(&
if_chain! {
// Extract method being called
if let StmtKind::Semi(semi_stmt) = &stmt.kind;
- if let ExprKind::MethodCall(path, args, _) = &semi_stmt.kind;
+ if let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind;
// Figure out the parameters for the method call
- if let Some(self_expr) = args.get(0);
- if let Some(pushed_item) = args.get(1);
+ if let Some(pushed_item) = args.get(0);
// Check that the method being called is push() on a Vec
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec);
if path.ident.name.as_str() == "push";
diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
index a0bd7ad0a..f4b47808d 100644
--- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
@@ -35,32 +35,29 @@ pub(super) fn check<'tcx>(
) => (arg, "&mut "),
ExprKind::MethodCall(
method,
- [
- Expr {
- kind: ExprKind::Array([arg]),
- ..
- },
- ],
+ Expr {
+ kind: ExprKind::Array([arg]),
+ ..
+ },
+ [],
_,
) if method.ident.name == rustc_span::sym::iter => (arg, "&"),
ExprKind::MethodCall(
method,
- [
- Expr {
- kind: ExprKind::Array([arg]),
- ..
- },
- ],
+ Expr {
+ kind: ExprKind::Array([arg]),
+ ..
+ },
+ [],
_,
) if method.ident.name.as_str() == "iter_mut" => (arg, "&mut "),
ExprKind::MethodCall(
method,
- [
- Expr {
- kind: ExprKind::Array([arg]),
- ..
- },
- ],
+ Expr {
+ kind: ExprKind::Array([arg]),
+ ..
+ },
+ [],
_,
) if method.ident.name == rustc_span::sym::into_iter => (arg, ""),
// Only check for arrays edition 2021 or later, as this case will trigger a compiler error otherwise.
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
index ca617859d..735d704a4 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
@@ -11,7 +11,14 @@ use rustc_lint::LateContext;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) {
let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) {
([stmt, stmts @ ..], expr) => {
- if let StmtKind::Local(&Local { init: Some(e), els: None, .. }) | StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind {
+ if let StmtKind::Local(&Local {
+ init: Some(e),
+ els: None,
+ ..
+ })
+ | StmtKind::Semi(e)
+ | StmtKind::Expr(e) = stmt.kind
+ {
(e, !stmts.is_empty() || expr.is_some())
} else {
return;
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
index e9e215e66..deb21894f 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let Res::Def(_, pat_did) = pat_path.res;
if match_def_path(cx, pat_did, &paths::OPTION_SOME);
// check for call to `Iterator::next`
- if let ExprKind::MethodCall(method_name, [iter_expr], _) = let_expr.kind;
+ if let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind;
if method_name.ident.name == sym::next;
if is_trait_method(cx, let_expr, sym::Iterator);
if let Some(iter_expr_struct) = try_parse_iter_expr(cx, iter_expr);
@@ -356,7 +356,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
after_loop: false,
used_iter: false,
};
- v.visit_expr(&cx.tcx.hir().body(cx.enclosing_body.unwrap()).value);
+ v.visit_expr(cx.tcx.hir().body(cx.enclosing_body.unwrap()).value);
v.used_iter
}
}