mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-15 01:17:16 +00:00
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:
commit
042892a081
3 changed files with 45 additions and 0 deletions
|
@ -10,6 +10,7 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::{Expr, ExprKind, Param, PatKind, Unsafety};
|
use rustc_hir::{Expr, ExprKind, Param, PatKind, Unsafety};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
|
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
|
||||||
|
use rustc_middle::ty::binding::BindingMode;
|
||||||
use rustc_middle::ty::subst::Subst;
|
use rustc_middle::ty::subst::Subst;
|
||||||
use rustc_middle::ty::{self, ClosureKind, Ty, TypeFoldable};
|
use rustc_middle::ty::{self, ClosureKind, Ty, TypeFoldable};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
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() {
|
if params.len() != call_args.len() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
let binding_modes = cx.typeck_results().pat_binding_modes();
|
||||||
std::iter::zip(params, call_args).all(|(param, arg)| {
|
std::iter::zip(params, call_args).all(|(param, arg)| {
|
||||||
match param.pat.kind {
|
match param.pat.kind {
|
||||||
PatKind::Binding(_, id, ..) if path_to_local_id(arg, id) => {},
|
PatKind::Binding(_, id, ..) if path_to_local_id(arg, id) => {},
|
||||||
_ => return false,
|
_ => 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) {
|
match *cx.typeck_results().expr_adjustments(arg) {
|
||||||
[] => true,
|
[] => true,
|
||||||
[
|
[
|
||||||
|
|
|
@ -256,3 +256,22 @@ fn arc_fp() {
|
||||||
(0..5).map(|n| arc(n));
|
(0..5).map(|n| arc(n));
|
||||||
Some(4).map(|n| ref_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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -256,3 +256,22 @@ fn arc_fp() {
|
||||||
(0..5).map(|n| arc(n));
|
(0..5).map(|n| arc(n));
|
||||||
Some(4).map(|n| ref_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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue