Skip to content

Commit 9c9aa92

Browse files
committed
Auto merge of #9465 - Alexendoo:peekable-fp, r=flip1995
Fix `unused_peekable` closure and `f(&mut peekable)` false positives changelog: Fix [`unused_peekable`] false positive when peeked in a closure or called as `f(&mut peekable)` The `return`/`break` changes aren't part of the fix, they allow an earlier return in some cases. `break` is replaced with `return` for style purposes as they do the same thing in this case Fixes #9456 Fixes #9462
2 parents 826a893 + 86d18b5 commit 9c9aa92

File tree

2 files changed

+50
-19
lines changed

2 files changed

+50
-19
lines changed

clippy_lints/src/unused_peekable.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor};
66
use rustc_hir::lang_items::LangItem;
77
use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
88
use rustc_lint::{LateContext, LateLintPass};
9+
use rustc_middle::hir::nested_filter::OnlyBodies;
910
use rustc_session::{declare_lint_pass, declare_tool_lint};
1011
use rustc_span::sym;
1112

@@ -109,8 +110,14 @@ impl<'a, 'tcx> PeekableVisitor<'a, 'tcx> {
109110
}
110111
}
111112

112-
impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
113-
fn visit_expr(&mut self, ex: &'_ Expr<'_>) {
113+
impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
114+
type NestedFilter = OnlyBodies;
115+
116+
fn nested_visit_map(&mut self) -> Self::Map {
117+
self.cx.tcx.hir()
118+
}
119+
120+
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
114121
if self.found_peek_call {
115122
return;
116123
}
@@ -136,12 +143,11 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
136143
return;
137144
}
138145

139-
if args.iter().any(|arg| {
140-
matches!(arg.kind, ExprKind::Path(_)) && arg_is_mut_peekable(self.cx, arg)
141-
}) {
146+
if args.iter().any(|arg| arg_is_mut_peekable(self.cx, arg)) {
142147
self.found_peek_call = true;
143-
return;
144148
}
149+
150+
return;
145151
},
146152
// Catch anything taking a Peekable mutably
147153
ExprKind::MethodCall(
@@ -190,21 +196,21 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
190196
Node::Local(Local { init: Some(init), .. }) => {
191197
if arg_is_mut_peekable(self.cx, init) {
192198
self.found_peek_call = true;
193-
return;
194199
}
195200

196-
break;
201+
return;
197202
},
198-
Node::Stmt(stmt) => match stmt.kind {
199-
StmtKind::Expr(_) | StmtKind::Semi(_) => {},
200-
_ => {
201-
self.found_peek_call = true;
202-
return;
203-
},
203+
Node::Stmt(stmt) => {
204+
match stmt.kind {
205+
StmtKind::Local(_) | StmtKind::Item(_) => self.found_peek_call = true,
206+
StmtKind::Expr(_) | StmtKind::Semi(_) => {},
207+
}
208+
209+
return;
204210
},
205211
Node::Block(_) | Node::ExprField(_) => {},
206212
_ => {
207-
break;
213+
return;
208214
},
209215
}
210216
}

tests/ui/unused_peekable.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,22 @@ fn valid() {
5757
impl PeekableConsumer {
5858
fn consume(&self, _: Peekable<Empty<u32>>) {}
5959
fn consume_mut_ref(&self, _: &mut Peekable<Empty<u32>>) {}
60+
fn consume_assoc(_: Peekable<Empty<u32>>) {}
61+
fn consume_assoc_mut_ref(_: &mut Peekable<Empty<u32>>) {}
6062
}
61-
6263
let peekable_consumer = PeekableConsumer;
63-
let mut passed_along_to_method = std::iter::empty::<u32>().peekable();
64-
peekable_consumer.consume_mut_ref(&mut passed_along_to_method);
65-
peekable_consumer.consume(passed_along_to_method);
64+
65+
let peekable = std::iter::empty::<u32>().peekable();
66+
peekable_consumer.consume(peekable);
67+
68+
let mut peekable = std::iter::empty::<u32>().peekable();
69+
peekable_consumer.consume_mut_ref(&mut peekable);
70+
71+
let peekable = std::iter::empty::<u32>().peekable();
72+
PeekableConsumer::consume_assoc(peekable);
73+
74+
let mut peekable = std::iter::empty::<u32>().peekable();
75+
PeekableConsumer::consume_assoc_mut_ref(&mut peekable);
6676

6777
// `peek` called in another block
6878
let mut peekable_in_block = std::iter::empty::<u32>().peekable();
@@ -141,4 +151,19 @@ fn valid() {
141151
{
142152
peekable_last_expr.peek();
143153
}
154+
155+
let mut peek_in_closure = std::iter::empty::<u32>().peekable();
156+
let _ = || {
157+
let _ = peek_in_closure.peek();
158+
};
159+
160+
trait PeekTrait {}
161+
impl<I> PeekTrait for Peekable<I> where I: Iterator {}
162+
163+
let mut peekable = std::iter::empty::<u32>().peekable();
164+
let _dyn = &mut peekable as &mut dyn PeekTrait;
165+
166+
fn takes_dyn(_: &mut dyn PeekTrait) {}
167+
let mut peekable = std::iter::empty::<u32>().peekable();
168+
takes_dyn(&mut peekable);
144169
}

0 commit comments

Comments
 (0)