diff options
| author | Alex Macleod <alex@macleod.io> | 2022-09-11 12:17:51 +0000 |
|---|---|---|
| committer | Alex Macleod <alex@macleod.io> | 2022-09-11 12:40:52 +0000 |
| commit | 86d18b50ed64fa5dd6313d595ad4c53d6eb610a2 (patch) | |
| tree | 5ced1edf727cbfe4d36b4a36c19d0f6497c83ec6 | |
| parent | c8c2a234b3a04dc41626ab2e06c43f66b26042a9 (diff) | |
| download | rust-86d18b50ed64fa5dd6313d595ad4c53d6eb610a2.tar.gz rust-86d18b50ed64fa5dd6313d595ad4c53d6eb610a2.zip | |
Fix `unused_peekable` closure and `f(&mut peekable)` false positives
| -rw-r--r-- | clippy_lints/src/unused_peekable.rs | 36 | ||||
| -rw-r--r-- | tests/ui/unused_peekable.rs | 33 |
2 files changed, 50 insertions, 19 deletions
diff --git a/clippy_lints/src/unused_peekable.rs b/clippy_lints/src/unused_peekable.rs index cfc181e435b..13b08df16a5 100644 --- a/clippy_lints/src/unused_peekable.rs +++ b/clippy_lints/src/unused_peekable.rs @@ -6,6 +6,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::lang_items::LangItem; use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; @@ -109,8 +110,14 @@ impl<'a, 'tcx> PeekableVisitor<'a, 'tcx> { } } -impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> { - fn visit_expr(&mut self, ex: &'_ Expr<'_>) { +impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> { + type NestedFilter = OnlyBodies; + + fn nested_visit_map(&mut self) -> Self::Map { + self.cx.tcx.hir() + } + + fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { if self.found_peek_call { return; } @@ -136,12 +143,11 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> { return; } - if args.iter().any(|arg| { - matches!(arg.kind, ExprKind::Path(_)) && arg_is_mut_peekable(self.cx, arg) - }) { + if args.iter().any(|arg| arg_is_mut_peekable(self.cx, arg)) { self.found_peek_call = true; - return; } + + return; }, // Catch anything taking a Peekable mutably ExprKind::MethodCall( @@ -190,21 +196,21 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> { Node::Local(Local { init: Some(init), .. }) => { if arg_is_mut_peekable(self.cx, init) { self.found_peek_call = true; - return; } - break; + return; }, - Node::Stmt(stmt) => match stmt.kind { - StmtKind::Expr(_) | StmtKind::Semi(_) => {}, - _ => { - self.found_peek_call = true; - return; - }, + Node::Stmt(stmt) => { + match stmt.kind { + StmtKind::Local(_) | StmtKind::Item(_) => self.found_peek_call = true, + StmtKind::Expr(_) | StmtKind::Semi(_) => {}, + } + + return; }, Node::Block(_) | Node::ExprField(_) => {}, _ => { - break; + return; }, } } diff --git a/tests/ui/unused_peekable.rs b/tests/ui/unused_peekable.rs index 153457e3671..7374dfdf92e 100644 --- a/tests/ui/unused_peekable.rs +++ b/tests/ui/unused_peekable.rs @@ -57,12 +57,22 @@ fn valid() { impl PeekableConsumer { fn consume(&self, _: Peekable<Empty<u32>>) {} fn consume_mut_ref(&self, _: &mut Peekable<Empty<u32>>) {} + fn consume_assoc(_: Peekable<Empty<u32>>) {} + fn consume_assoc_mut_ref(_: &mut Peekable<Empty<u32>>) {} } - let peekable_consumer = PeekableConsumer; - let mut passed_along_to_method = std::iter::empty::<u32>().peekable(); - peekable_consumer.consume_mut_ref(&mut passed_along_to_method); - peekable_consumer.consume(passed_along_to_method); + + let peekable = std::iter::empty::<u32>().peekable(); + peekable_consumer.consume(peekable); + + let mut peekable = std::iter::empty::<u32>().peekable(); + peekable_consumer.consume_mut_ref(&mut peekable); + + let peekable = std::iter::empty::<u32>().peekable(); + PeekableConsumer::consume_assoc(peekable); + + let mut peekable = std::iter::empty::<u32>().peekable(); + PeekableConsumer::consume_assoc_mut_ref(&mut peekable); // `peek` called in another block let mut peekable_in_block = std::iter::empty::<u32>().peekable(); @@ -141,4 +151,19 @@ fn valid() { { peekable_last_expr.peek(); } + + let mut peek_in_closure = std::iter::empty::<u32>().peekable(); + let _ = || { + let _ = peek_in_closure.peek(); + }; + + trait PeekTrait {} + impl<I> PeekTrait for Peekable<I> where I: Iterator {} + + let mut peekable = std::iter::empty::<u32>().peekable(); + let _dyn = &mut peekable as &mut dyn PeekTrait; + + fn takes_dyn(_: &mut dyn PeekTrait) {} + let mut peekable = std::iter::empty::<u32>().peekable(); + takes_dyn(&mut peekable); } |
