about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/copies.rs6
-rw-r--r--clippy_lints/src/default.rs2
-rw-r--r--clippy_lints/src/loops/needless_range_loop.rs4
-rw-r--r--clippy_utils/src/lib.rs21
-rw-r--r--tests/ui/field_reassign_with_default.rs21
5 files changed, 46 insertions, 8 deletions
diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs
index 0e3d9317590..f10c35cde52 100644
--- a/clippy_lints/src/copies.rs
+++ b/clippy_lints/src/copies.rs
@@ -525,7 +525,11 @@ fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbo
             .iter()
             .filter(|&&(_, name)| !name.as_str().starts_with('_'))
             .any(|&(_, name)| {
-                let mut walker = ContainsName { name, result: false };
+                let mut walker = ContainsName {
+                    name,
+                    result: false,
+                    cx,
+                };
 
                 // Scan block
                 block
diff --git a/clippy_lints/src/default.rs b/clippy_lints/src/default.rs
index 7f937de1dd3..55f6121a09d 100644
--- a/clippy_lints/src/default.rs
+++ b/clippy_lints/src/default.rs
@@ -170,7 +170,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
                 // 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) {
                     // 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;
                         break;
                     }
diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs
index 27ba27202bf..3bca93d80aa 100644
--- a/clippy_lints/src/loops/needless_range_loop.rs
+++ b/clippy_lints/src/loops/needless_range_loop.rs
@@ -81,7 +81,7 @@ pub(super) fn check<'tcx>(
 
                 let skip = if starts_at_zero {
                     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;
                 } else {
                     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) {
                         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;
                     } else {
                         match limits {
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 43e2d1ec826..46769cf2392 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -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::visitors::for_each_expr;
 
+use rustc_middle::hir::nested_filter;
+
 #[macro_export]
 macro_rules! extract_msrv_attr {
     ($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 result: bool,
 }
 
-impl<'tcx> Visitor<'tcx> for ContainsName {
+impl<'a, 'tcx> Visitor<'tcx> for ContainsName<'a, 'tcx> {
+    type NestedFilter = nested_filter::OnlyBodies;
+
     fn visit_name(&mut self, name: Symbol) {
         if self.name == name {
             self.result = true;
         }
     }
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
+    }
 }
 
 /// Checks if an `Expr` contains a certain name.
-pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
-    let mut cn = ContainsName { name, result: false };
+pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool {
+    let mut cn = ContainsName {
+        name,
+        result: false,
+        cx,
+    };
     cn.visit_expr(expr);
     cn.result
 }
diff --git a/tests/ui/field_reassign_with_default.rs b/tests/ui/field_reassign_with_default.rs
index 7367910eaa1..1f989bb1220 100644
--- a/tests/ui/field_reassign_with_default.rs
+++ b/tests/ui/field_reassign_with_default.rs
@@ -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())();
+}