Auto merge of #8466 - tamaroning:fix_reduntant_closure, r=Manishearth

False positive redundant_closure when using ref pattern in closure params

fixes #8460
Fixed [redundant_closure] so that closures of which params bound as `ref` or `ref mut ` doesn't trigger the lint.
(e.g. `|ref x| some_expr` doesn't trigger the lint.)
changelog: none
This commit is contained in:
bors 2022-02-23 18:26:30 +00:00
commit 042892a081
3 changed files with 45 additions and 0 deletions

View file

@ -10,6 +10,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, ExprKind, Param, PatKind, Unsafety};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
use rustc_middle::ty::binding::BindingMode;
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, ClosureKind, Ty, TypeFoldable};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -169,11 +170,17 @@ fn check_inputs(cx: &LateContext<'_>, params: &[Param<'_>], call_args: &[Expr<'_
if params.len() != call_args.len() {
return false;
}
let binding_modes = cx.typeck_results().pat_binding_modes();
std::iter::zip(params, call_args).all(|(param, arg)| {
match param.pat.kind {
PatKind::Binding(_, id, ..) if path_to_local_id(arg, id) => {},
_ => return false,
}
// checks that parameters are not bound as `ref` or `ref mut`
if let Some(BindingMode::BindByReference(_)) = binding_modes.get(param.pat.hir_id) {
return false;
}
match *cx.typeck_results().expr_adjustments(arg) {
[] => true,
[

View file

@ -256,3 +256,22 @@ fn arc_fp() {
(0..5).map(|n| arc(n));
Some(4).map(|n| ref_arc(n));
}
// #8460 Don't replace closures with params bounded as `ref`
mod bind_by_ref {
struct A;
struct B;
impl From<&A> for B {
fn from(A: &A) -> Self {
B
}
}
fn test() {
// should not lint
Some(A).map(|a| B::from(&a));
// should not lint
Some(A).map(|ref a| B::from(a));
}
}

View file

@ -256,3 +256,22 @@ fn arc_fp() {
(0..5).map(|n| arc(n));
Some(4).map(|n| ref_arc(n));
}
// #8460 Don't replace closures with params bounded as `ref`
mod bind_by_ref {
struct A;
struct B;
impl From<&A> for B {
fn from(A: &A) -> Self {
B
}
}
fn test() {
// should not lint
Some(A).map(|a| B::from(&a));
// should not lint
Some(A).map(|ref a| B::from(a));
}
}