mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 21:23:56 +00:00
don't lint field_reassign when field in closure
This commit makes the ContainsName struct visit all interior expressions, which means that ContainsName will return true even if `name` is used in a closure within `expr`.
This commit is contained in:
parent
a85e480dd1
commit
8de011fdf7
5 changed files with 46 additions and 8 deletions
|
@ -525,7 +525,11 @@ fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbo
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&&(_, name)| !name.as_str().starts_with('_'))
|
.filter(|&&(_, name)| !name.as_str().starts_with('_'))
|
||||||
.any(|&(_, name)| {
|
.any(|&(_, name)| {
|
||||||
let mut walker = ContainsName { name, result: false };
|
let mut walker = ContainsName {
|
||||||
|
name,
|
||||||
|
result: false,
|
||||||
|
cx,
|
||||||
|
};
|
||||||
|
|
||||||
// Scan block
|
// Scan block
|
||||||
block
|
block
|
||||||
|
|
|
@ -170,7 +170,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
|
||||||
// find out if and which field was set by this `consecutive_statement`
|
// find out if and which field was set by this `consecutive_statement`
|
||||||
if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
|
if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
|
||||||
// interrupt and cancel lint if assign_rhs references the original binding
|
// interrupt and cancel lint if assign_rhs references the original binding
|
||||||
if contains_name(binding_name, assign_rhs) {
|
if contains_name(binding_name, assign_rhs, cx) {
|
||||||
cancel_lint = true;
|
cancel_lint = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ pub(super) fn check<'tcx>(
|
||||||
|
|
||||||
let skip = if starts_at_zero {
|
let skip = if starts_at_zero {
|
||||||
String::new()
|
String::new()
|
||||||
} else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start) {
|
} else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start, cx) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
format!(".skip({})", snippet(cx, start.span, ".."))
|
format!(".skip({})", snippet(cx, start.span, ".."))
|
||||||
|
@ -109,7 +109,7 @@ pub(super) fn check<'tcx>(
|
||||||
|
|
||||||
if is_len_call(end, indexed) || is_end_eq_array_len(cx, end, limits, indexed_ty) {
|
if is_len_call(end, indexed) || is_end_eq_array_len(cx, end, limits, indexed_ty) {
|
||||||
String::new()
|
String::new()
|
||||||
} else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr) {
|
} else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr, cx) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
match limits {
|
match limits {
|
||||||
|
|
|
@ -116,6 +116,8 @@ use crate::consts::{constant, Constant};
|
||||||
use crate::ty::{can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, ty_is_fn_once_param};
|
use crate::ty::{can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, ty_is_fn_once_param};
|
||||||
use crate::visitors::for_each_expr;
|
use crate::visitors::for_each_expr;
|
||||||
|
|
||||||
|
use rustc_middle::hir::nested_filter;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! extract_msrv_attr {
|
macro_rules! extract_msrv_attr {
|
||||||
($context:ident) => {
|
($context:ident) => {
|
||||||
|
@ -1253,22 +1255,33 @@ pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ContainsName {
|
pub struct ContainsName<'a, 'tcx> {
|
||||||
|
pub cx: &'a LateContext<'tcx>,
|
||||||
pub name: Symbol,
|
pub name: Symbol,
|
||||||
pub result: bool,
|
pub result: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for ContainsName {
|
impl<'a, 'tcx> Visitor<'tcx> for ContainsName<'a, 'tcx> {
|
||||||
|
type NestedFilter = nested_filter::All;
|
||||||
|
|
||||||
fn visit_name(&mut self, name: Symbol) {
|
fn visit_name(&mut self, name: Symbol) {
|
||||||
if self.name == name {
|
if self.name == name {
|
||||||
self.result = true;
|
self.result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn nested_visit_map(&mut self) -> Self::Map {
|
||||||
|
self.cx.tcx.hir()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if an `Expr` contains a certain name.
|
/// Checks if an `Expr` contains a certain name.
|
||||||
pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
|
pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool {
|
||||||
let mut cn = ContainsName { name, result: false };
|
let mut cn = ContainsName {
|
||||||
|
name,
|
||||||
|
result: false,
|
||||||
|
cx,
|
||||||
|
};
|
||||||
cn.visit_expr(expr);
|
cn.visit_expr(expr);
|
||||||
cn.result
|
cn.result
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,3 +247,24 @@ mod issue6312 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Collection {
|
||||||
|
items: Vec<i32>,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Collection {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
items: vec![1, 2, 3],
|
||||||
|
len: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::redundant_closure_call)]
|
||||||
|
fn issue10136() {
|
||||||
|
let mut c = Collection::default();
|
||||||
|
// don't lint, since c.items was used to calculate this value
|
||||||
|
c.len = (|| c.items.len())();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue