diff options
| author | Philipp Krones <hello@philkrones.com> | 2024-10-18 13:44:06 +0200 |
|---|---|---|
| committer | Philipp Krones <hello@philkrones.com> | 2024-10-18 13:44:06 +0200 |
| commit | fea5e77da1dedea3a64711cb1b75c141e72ba248 (patch) | |
| tree | 56cd01b028792c518439c83fa9db698b8350f184 /clippy_lints/src/loops | |
| parent | c512a221c23f3f7b98a38ab5fd81784b318d1663 (diff) | |
Merge commit 'a109190d7060236e655fc75533373fa274ec5343' into clippy-subtree-update
Diffstat (limited to 'clippy_lints/src/loops')
| -rw-r--r-- | clippy_lints/src/loops/infinite_loop.rs | 19 | ||||
| -rw-r--r-- | clippy_lints/src/loops/manual_while_let_some.rs | 11 | ||||
| -rw-r--r-- | clippy_lints/src/loops/same_item_push.rs | 6 |
3 files changed, 25 insertions, 11 deletions
diff --git a/clippy_lints/src/loops/infinite_loop.rs b/clippy_lints/src/loops/infinite_loop.rs index 858e3be5093..e25c03db534 100644 --- a/clippy_lints/src/loops/infinite_loop.rs +++ b/clippy_lints/src/loops/infinite_loop.rs @@ -42,6 +42,7 @@ pub(super) fn check<'tcx>( let mut loop_visitor = LoopVisitor { cx, label, + inner_labels: label.into_iter().collect(), is_finite: false, loop_depth: 0, }; @@ -93,6 +94,7 @@ fn get_parent_fn_ret_ty<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option struct LoopVisitor<'hir, 'tcx> { cx: &'hir LateContext<'tcx>, label: Option<Label>, + inner_labels: Vec<Label>, loop_depth: usize, is_finite: bool, } @@ -108,11 +110,24 @@ impl<'hir> Visitor<'hir> for LoopVisitor<'hir, '_> { self.is_finite = true; } }, + ExprKind::Continue(hir::Destination { label, .. }) => { + // Check whether we are leaving this loop by continuing into an outer loop + // whose label we did not encounter. + if label.is_some_and(|label| !self.inner_labels.contains(&label)) { + self.is_finite = true; + } + }, ExprKind::Ret(..) => self.is_finite = true, - ExprKind::Loop(..) => { + ExprKind::Loop(_, label, _, _) => { + if let Some(label) = label { + self.inner_labels.push(*label); + } self.loop_depth += 1; walk_expr(self, ex); - self.loop_depth = self.loop_depth.saturating_sub(1); + self.loop_depth -= 1; + if label.is_some() { + self.inner_labels.pop(); + } }, _ => { // Calls to a function that never return diff --git a/clippy_lints/src/loops/manual_while_let_some.rs b/clippy_lints/src/loops/manual_while_let_some.rs index 7476a87267f..4473a3343c7 100644 --- a/clippy_lints/src/loops/manual_while_let_some.rs +++ b/clippy_lints/src/loops/manual_while_let_some.rs @@ -47,8 +47,9 @@ fn report_lint(cx: &LateContext<'_>, pop_span: Span, pop_stmt_kind: PopStmt<'_>, ); } -fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: Symbol) -> bool { - if let ExprKind::MethodCall(..) = expr.kind +fn match_method_call<const ARGS_COUNT: usize>(cx: &LateContext<'_>, expr: &Expr<'_>, method: Symbol) -> bool { + if let ExprKind::MethodCall(_, _, args, _) = expr.kind + && args.len() == ARGS_COUNT && let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { cx.tcx.is_diagnostic_item(method, id) @@ -58,9 +59,9 @@ fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: Symbol) -> b } fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr<'_>) -> bool { - if (match_method_call(cx, expr, sym::option_unwrap) || match_method_call(cx, expr, sym::option_expect)) + if (match_method_call::<0>(cx, expr, sym::option_unwrap) || match_method_call::<1>(cx, expr, sym::option_expect)) && let ExprKind::MethodCall(_, unwrap_recv, ..) = expr.kind - && match_method_call(cx, unwrap_recv, sym::vec_pop) + && match_method_call::<0>(cx, unwrap_recv, sym::vec_pop) && let ExprKind::MethodCall(_, pop_recv, ..) = unwrap_recv.kind { // make sure they're the same `Vec` @@ -96,7 +97,7 @@ fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &E pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, full_cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>, loop_span: Span) { if let ExprKind::Unary(UnOp::Not, cond) = full_cond.kind && let ExprKind::MethodCall(_, is_empty_recv, _, _) = cond.kind - && match_method_call(cx, cond, sym::vec_is_empty) + && match_method_call::<0>(cx, cond, sym::vec_is_empty) && let ExprKind::Block(body, _) = body.kind && let Some(stmt) = body.stmts.first() { diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs index f8659897ffe..d255fea3af2 100644 --- a/clippy_lints/src/loops/same_item_push.rs +++ b/clippy_lints/src/loops/same_item_push.rs @@ -172,10 +172,8 @@ fn get_vec_push<'tcx>( stmt: &'tcx Stmt<'_>, ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, SyntaxContext)> { if let StmtKind::Semi(semi_stmt) = &stmt.kind - // Extract method being called - && let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind - // Figure out the parameters for the method call - && let Some(pushed_item) = args.first() + // Extract method being called and figure out the parameters for the method call + && let ExprKind::MethodCall(path, self_expr, [pushed_item], _) = &semi_stmt.kind // Check that the method being called is push() on a Vec && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec) && path.ident.name.as_str() == "push" |
