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
This commit is contained in:
commit
9c9aa92898
@ -6,6 +6,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor};
|
|||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
|
use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
|
||||||
@ -109,8 +110,14 @@ impl<'a, 'tcx> PeekableVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
|
impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
|
||||||
fn visit_expr(&mut self, ex: &'_ Expr<'_>) {
|
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 {
|
if self.found_peek_call {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -136,12 +143,11 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.iter().any(|arg| {
|
if args.iter().any(|arg| arg_is_mut_peekable(self.cx, arg)) {
|
||||||
matches!(arg.kind, ExprKind::Path(_)) && arg_is_mut_peekable(self.cx, arg)
|
|
||||||
}) {
|
|
||||||
self.found_peek_call = true;
|
self.found_peek_call = true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
},
|
},
|
||||||
// Catch anything taking a Peekable mutably
|
// Catch anything taking a Peekable mutably
|
||||||
ExprKind::MethodCall(
|
ExprKind::MethodCall(
|
||||||
@ -190,21 +196,21 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
|
|||||||
Node::Local(Local { init: Some(init), .. }) => {
|
Node::Local(Local { init: Some(init), .. }) => {
|
||||||
if arg_is_mut_peekable(self.cx, init) {
|
if arg_is_mut_peekable(self.cx, init) {
|
||||||
self.found_peek_call = true;
|
self.found_peek_call = true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
},
|
},
|
||||||
Node::Stmt(stmt) => match stmt.kind {
|
Node::Stmt(stmt) => {
|
||||||
StmtKind::Expr(_) | StmtKind::Semi(_) => {},
|
match stmt.kind {
|
||||||
_ => {
|
StmtKind::Local(_) | StmtKind::Item(_) => self.found_peek_call = true,
|
||||||
self.found_peek_call = true;
|
StmtKind::Expr(_) | StmtKind::Semi(_) => {},
|
||||||
return;
|
}
|
||||||
},
|
|
||||||
|
return;
|
||||||
},
|
},
|
||||||
Node::Block(_) | Node::ExprField(_) => {},
|
Node::Block(_) | Node::ExprField(_) => {},
|
||||||
_ => {
|
_ => {
|
||||||
break;
|
return;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,12 +57,22 @@ fn valid() {
|
|||||||
impl PeekableConsumer {
|
impl PeekableConsumer {
|
||||||
fn consume(&self, _: Peekable<Empty<u32>>) {}
|
fn consume(&self, _: Peekable<Empty<u32>>) {}
|
||||||
fn consume_mut_ref(&self, _: &mut 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 peekable_consumer = PeekableConsumer;
|
||||||
let mut passed_along_to_method = std::iter::empty::<u32>().peekable();
|
|
||||||
peekable_consumer.consume_mut_ref(&mut passed_along_to_method);
|
let peekable = std::iter::empty::<u32>().peekable();
|
||||||
peekable_consumer.consume(passed_along_to_method);
|
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
|
// `peek` called in another block
|
||||||
let mut peekable_in_block = std::iter::empty::<u32>().peekable();
|
let mut peekable_in_block = std::iter::empty::<u32>().peekable();
|
||||||
@ -141,4 +151,19 @@ fn valid() {
|
|||||||
{
|
{
|
||||||
peekable_last_expr.peek();
|
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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user