From 8c0e4d5ccf8be995273f8b1e0e217906ec4b1dc4 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sun, 10 Jan 2021 17:51:43 -0600 Subject: [PATCH] Rewrite shadow lint --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/shadow.rs | 423 +++++++++++-------------------------- tests/ui/map_clone.fixed | 14 +- tests/ui/map_clone.rs | 14 +- tests/ui/shadow.rs | 113 ++++++---- tests/ui/shadow.stderr | 220 ++++++++++++++----- 6 files changed, 379 insertions(+), 407 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d43ce4a87c66f..4e21b03217dfa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -324,7 +324,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(same_name_method::SameNameMethod)); store.register_late_pass(|| Box::new(map_clone::MapClone)); store.register_late_pass(|| Box::new(map_err_ignore::MapErrIgnore)); - store.register_late_pass(|| Box::new(shadow::Shadow)); + store.register_late_pass(|| Box::new(shadow::Shadow::default())); store.register_late_pass(|| Box::new(unit_types::UnitTypes)); store.register_late_pass(|| Box::new(loops::Loops)); store.register_late_pass(|| Box::new(main_recursion::MainRecursion::default())); diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index c17acfc8be7b9..2ca7c18800ee2 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,17 +1,14 @@ -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::source::snippet; -use clippy_utils::{contains_name, higher, iter_input_pats}; -use rustc_hir::intravisit::FnKind; -use rustc_hir::{ - Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind, - UnOp, -}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; -use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; -use rustc_span::symbol::Symbol; +use clippy_utils::visitors::is_local_used; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def::Res; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::hir_id::ItemLocalId; +use rustc_hir::{Block, Body, BodyOwnerKind, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, UnOp}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::{Span, Symbol}; declare_clippy_lint! { /// ### What it does @@ -23,10 +20,6 @@ declare_clippy_lint! { /// code. Still, some may opt to avoid it in their code base, they can set this /// lint to `Warn`. /// - /// ### Known problems - /// This lint, as the other shadowing related lints, - /// currently only catches very simple patterns. - /// /// ### Example /// ```rust /// # let x = 1; @@ -52,10 +45,6 @@ declare_clippy_lint! { /// because a value may be bound to different things depending on position in /// the code. /// - /// ### Known problems - /// This lint, as the other shadowing related lints, - /// currently only catches very simple patterns. - /// /// ### Example /// ```rust /// let x = 2; @@ -83,12 +72,6 @@ declare_clippy_lint! { /// any place in the code. This can be alleviated by either giving more specific /// names to bindings or introducing more scopes to contain the bindings. /// - /// ### Known problems - /// This lint, as the other shadowing related lints, - /// currently only catches very simple patterns. Note that - /// `allow`/`warn`/`deny`/`forbid` attributes only work on the function level - /// for this lint. - /// /// ### Example /// ```rust /// # let y = 1; @@ -106,301 +89,147 @@ declare_clippy_lint! { "rebinding a name without even using the original value" } -declare_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]); +#[derive(Default)] +pub(crate) struct Shadow { + bindings: Vec>>, +} + +impl_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]); impl<'tcx> LateLintPass<'tcx> for Shadow { - fn check_fn( - &mut self, - cx: &LateContext<'tcx>, - _: FnKind<'tcx>, - decl: &'tcx FnDecl<'_>, - body: &'tcx Body<'_>, - _: Span, - _: HirId, - ) { - if in_external_macro(cx.sess(), body.value.span) { + fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { + let (id, ident) = match pat.kind { + PatKind::Binding(_, hir_id, ident, _) => (hir_id, ident), + _ => return, + }; + if ident.span.from_expansion() || ident.span.is_dummy() { return; } - check_fn(cx, decl, body); - } -} + let HirId { owner, local_id } = id; + + // get (or insert) the list of items for this owner and symbol + let data = self.bindings.last_mut().unwrap(); + let items_with_name = data.entry(ident.name).or_default(); -fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>) { - let mut bindings = Vec::with_capacity(decl.inputs.len()); - for arg in iter_input_pats(decl, body) { - if let PatKind::Binding(.., ident, _) = arg.pat.kind { - bindings.push((ident.name, ident.span)); + // check other bindings with the same name, most recently seen first + for &prev in items_with_name.iter().rev() { + if prev == local_id { + // repeated binding in an `Or` pattern + return; + } + + if is_shadow(cx, owner, prev, local_id) { + let prev_hir_id = HirId { owner, local_id: prev }; + lint_shadow(cx, pat, prev_hir_id, ident.span); + // only lint against the "nearest" shadowed binding + break; + } } + // store the binding + items_with_name.push(local_id); } - check_expr(cx, &body.value, &mut bindings); -} -fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Symbol, Span)>) { - let len = bindings.len(); - for stmt in block.stmts { - match stmt.kind { - StmtKind::Local(local) => check_local(cx, local, bindings), - StmtKind::Expr(e) | StmtKind::Semi(e) => check_expr(cx, e, bindings), - StmtKind::Item(..) => {}, + fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { + let hir = cx.tcx.hir(); + if !matches!(hir.body_owner_kind(hir.body_owner(body.id())), BodyOwnerKind::Closure) { + self.bindings.push(FxHashMap::default()); } } - if let Some(o) = block.expr { - check_expr(cx, o, bindings); - } - bindings.truncate(len); -} -fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Symbol, Span)>) { - if in_external_macro(cx.sess(), local.span) { - return; - } - if higher::is_from_for_desugar(local) { - return; - } - let Local { - pat, - ref ty, - ref init, - span, - .. - } = *local; - if let Some(t) = *ty { - check_ty(cx, t, bindings); - } - if let Some(o) = *init { - check_expr(cx, o, bindings); - check_pat(cx, pat, Some(o), span, bindings); - } else { - check_pat(cx, pat, None, span, bindings); + fn check_body_post(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { + let hir = cx.tcx.hir(); + if !matches!(hir.body_owner_kind(hir.body_owner(body.id())), BodyOwnerKind::Closure) { + self.bindings.pop(); + } } } -fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool { - let var_ty = cx.typeck_results().node_type_opt(pat_id); - var_ty.map_or(false, |var_ty| !matches!(var_ty.kind(), ty::Adt(..))) +fn is_shadow(cx: &LateContext<'_>, owner: LocalDefId, first: ItemLocalId, second: ItemLocalId) -> bool { + let scope_tree = cx.tcx.region_scope_tree(owner.to_def_id()); + let first_scope = scope_tree.var_scope(first); + let second_scope = scope_tree.var_scope(second); + scope_tree.is_subscope_of(second_scope, first_scope) } -fn check_pat<'tcx>( - cx: &LateContext<'tcx>, - pat: &'tcx Pat<'_>, - init: Option<&'tcx Expr<'_>>, - span: Span, - bindings: &mut Vec<(Symbol, Span)>, -) { - // TODO: match more stuff / destructuring - match pat.kind { - PatKind::Binding(.., ident, ref inner) => { - let name = ident.name; - if is_binding(cx, pat.hir_id) { - let mut new_binding = true; - for tup in bindings.iter_mut() { - if tup.0 == name { - lint_shadow(cx, name, span, pat.span, init, tup.1); - tup.1 = ident.span; - new_binding = false; - break; - } - } - if new_binding { - bindings.push((name, ident.span)); - } - } - if let Some(p) = *inner { - check_pat(cx, p, init, span, bindings); - } - }, - PatKind::Struct(_, pfields, _) => { - if let Some(init_struct) = init { - if let ExprKind::Struct(_, efields, _) = init_struct.kind { - for field in pfields { - let name = field.ident.name; - let efield = efields - .iter() - .find_map(|f| if f.ident.name == name { Some(&*f.expr) } else { None }); - check_pat(cx, field.pat, efield, span, bindings); - } - } else { - for field in pfields { - check_pat(cx, field.pat, init, span, bindings); - } - } - } else { - for field in pfields { - check_pat(cx, field.pat, None, span, bindings); - } - } +fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span) { + let (lint, msg) = match find_init(cx, pat.hir_id) { + Some(expr) if is_self_shadow(cx, pat, expr, shadowed) => { + let msg = format!( + "`{}` is shadowed by itself in `{}`", + snippet(cx, pat.span, "_"), + snippet(cx, expr.span, "..") + ); + (SHADOW_SAME, msg) }, - PatKind::Tuple(inner, _) => { - if let Some(init_tup) = init { - if let ExprKind::Tup(tup) = init_tup.kind { - for (i, p) in inner.iter().enumerate() { - check_pat(cx, p, Some(&tup[i]), p.span, bindings); - } - } else { - for p in inner { - check_pat(cx, p, init, span, bindings); - } - } - } else { - for p in inner { - check_pat(cx, p, None, span, bindings); - } - } + Some(expr) if is_local_used(cx, expr, shadowed) => { + let msg = format!( + "`{}` is shadowed by `{}` which reuses the original value", + snippet(cx, pat.span, "_"), + snippet(cx, expr.span, "..") + ); + (SHADOW_REUSE, msg) }, - PatKind::Box(inner) => { - if let Some(initp) = init { - if let ExprKind::Box(inner_init) = initp.kind { - check_pat(cx, inner, Some(inner_init), span, bindings); - } else { - check_pat(cx, inner, init, span, bindings); - } - } else { - check_pat(cx, inner, init, span, bindings); - } + _ => { + let msg = format!("`{}` shadows a previous, unrelated binding", snippet(cx, pat.span, "_")); + (SHADOW_UNRELATED, msg) }, - PatKind::Ref(inner, _) => check_pat(cx, inner, init, span, bindings), - // PatVec(Vec>, Option>, Vec>), - _ => (), - } + }; + span_lint_and_note( + cx, + lint, + span, + &msg, + Some(cx.tcx.hir().span(shadowed)), + "previous binding is here", + ); } -fn lint_shadow<'tcx>( - cx: &LateContext<'tcx>, - name: Symbol, - span: Span, - pattern_span: Span, - init: Option<&'tcx Expr<'_>>, - prev_span: Span, -) { - if let Some(expr) = init { - if is_self_shadow(name, expr) { - span_lint_and_then( - cx, - SHADOW_SAME, - span, - &format!( - "`{}` is shadowed by itself in `{}`", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..") - ), - |diag| { - diag.span_note(prev_span, "previous binding is here"); - }, - ); - } else if contains_name(name, expr) { - span_lint_and_then( - cx, - SHADOW_REUSE, - pattern_span, - &format!( - "`{}` is shadowed by `{}` which reuses the original value", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..") - ), - |diag| { - diag.span_note(prev_span, "previous binding is here"); - }, - ); - } else { - span_lint_and_then( - cx, - SHADOW_UNRELATED, - pattern_span, - &format!("`{}` is being shadowed", snippet(cx, pattern_span, "_")), - |diag| { - diag.span_note(prev_span, "previous binding is here"); +/// Returns true if the expression is a simple transformation of a local binding such as `&x` +fn is_self_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, mut expr: &Expr<'_>, hir_id: HirId) -> bool { + let hir = cx.tcx.hir(); + let is_direct_binding = hir + .parent_iter(pat.hir_id) + .map_while(|(_id, node)| match node { + Node::Pat(pat) => Some(pat), + _ => None, + }) + .all(|pat| matches!(pat.kind, PatKind::Ref(..) | PatKind::Or(_))); + if !is_direct_binding { + return false; + } + loop { + expr = match expr.kind { + ExprKind::Box(e) + | ExprKind::AddrOf(_, _, e) + | ExprKind::Block( + &Block { + stmts: [], + expr: Some(e), + .. }, - ); + _, + ) + | ExprKind::Unary(UnOp::Deref, e) => e, + ExprKind::Path(QPath::Resolved(None, path)) => break path.res == Res::Local(hir_id), + _ => break false, } - } else { - span_lint_and_then( - cx, - SHADOW_UNRELATED, - span, - &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")), - |diag| { - diag.span_note(prev_span, "previous binding is here"); - }, - ); - } -} - -fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Symbol, Span)>) { - if in_external_macro(cx.sess(), expr.span) { - return; - } - match expr.kind { - ExprKind::Unary(_, e) | ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) | ExprKind::Box(e) => { - check_expr(cx, e, bindings); - }, - ExprKind::Block(block, _) | ExprKind::Loop(block, ..) => check_block(cx, block, bindings), - // ExprKind::Call - // ExprKind::MethodCall - ExprKind::Array(v) | ExprKind::Tup(v) => { - for e in v { - check_expr(cx, e, bindings); - } - }, - ExprKind::If(cond, then, ref otherwise) => { - check_expr(cx, cond, bindings); - check_expr(cx, then, bindings); - if let Some(o) = *otherwise { - check_expr(cx, o, bindings); - } - }, - ExprKind::Match(init, arms, _) => { - check_expr(cx, init, bindings); - let len = bindings.len(); - for arm in arms { - check_pat(cx, arm.pat, Some(init), arm.pat.span, bindings); - // This is ugly, but needed to get the right type - if let Some(ref guard) = arm.guard { - match guard { - Guard::If(if_expr) => check_expr(cx, if_expr, bindings), - Guard::IfLet(guard_pat, guard_expr) => { - check_pat(cx, guard_pat, Some(*guard_expr), guard_pat.span, bindings); - check_expr(cx, guard_expr, bindings); - }, - } - } - check_expr(cx, arm.body, bindings); - bindings.truncate(len); - } - }, - _ => (), - } -} - -fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Symbol, Span)>) { - match ty.kind { - TyKind::Slice(sty) => check_ty(cx, sty, bindings), - TyKind::Array(fty, ref anon_const) => { - check_ty(cx, fty, bindings); - check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings); - }, - TyKind::Ptr(MutTy { ty: mty, .. }) | TyKind::Rptr(_, MutTy { ty: mty, .. }) => check_ty(cx, mty, bindings), - TyKind::Tup(tup) => { - for t in tup { - check_ty(cx, t, bindings); - } - }, - TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings), - _ => (), } } -fn is_self_shadow(name: Symbol, expr: &Expr<'_>) -> bool { - match expr.kind { - ExprKind::Box(inner) | ExprKind::AddrOf(_, _, inner) => is_self_shadow(name, inner), - ExprKind::Block(block, _) => { - block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e)) - }, - ExprKind::Unary(op, inner) => (UnOp::Deref == op) && is_self_shadow(name, inner), - ExprKind::Path(QPath::Resolved(_, path)) => path_eq_name(name, path), - _ => false, +/// Finds the "init" expression for a pattern: `let = ;` or +/// `match { .., => .., .. }` +fn find_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> { + for (_, node) in cx.tcx.hir().parent_iter(hir_id) { + let init = match node { + Node::Arm(_) | Node::Pat(_) => continue, + Node::Expr(expr) => match expr.kind { + ExprKind::Match(e, _, _) => Some(e), + _ => None, + }, + Node::Local(local) => local.init, + _ => None, + }; + return init; } -} - -fn path_eq_name(name: Symbol, path: &Path<'_>) -> bool { - !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.name == name + None } diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index 178d8705c2f02..0860dcf8e0ddb 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -1,11 +1,11 @@ // run-rustfix -#![warn(clippy::all, clippy::pedantic)] -#![allow(clippy::iter_cloned_collect)] -#![allow(clippy::clone_on_copy, clippy::redundant_clone)] -#![allow(clippy::let_underscore_drop)] -#![allow(clippy::missing_docs_in_private_items)] -#![allow(clippy::redundant_closure_for_method_calls)] -#![allow(clippy::many_single_char_names)] +#![warn(clippy::map_clone)] +#![allow( + clippy::clone_on_copy, + clippy::iter_cloned_collect, + clippy::many_single_char_names, + clippy::redundant_clone +)] fn main() { let _: Vec = vec![5_i8; 6].iter().copied().collect(); diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index c73d81713b8a3..b6987336834b8 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -1,11 +1,11 @@ // run-rustfix -#![warn(clippy::all, clippy::pedantic)] -#![allow(clippy::iter_cloned_collect)] -#![allow(clippy::clone_on_copy, clippy::redundant_clone)] -#![allow(clippy::let_underscore_drop)] -#![allow(clippy::missing_docs_in_private_items)] -#![allow(clippy::redundant_closure_for_method_calls)] -#![allow(clippy::many_single_char_names)] +#![warn(clippy::map_clone)] +#![allow( + clippy::clone_on_copy, + clippy::iter_cloned_collect, + clippy::many_single_char_names, + clippy::redundant_clone +)] fn main() { let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index e366c75335c20..02e838456d0b5 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,54 +1,77 @@ -#![warn( - clippy::all, - clippy::pedantic, - clippy::shadow_same, - clippy::shadow_reuse, - clippy::shadow_unrelated -)] -#![allow( - unused_parens, - unused_variables, - clippy::manual_unwrap_or, - clippy::missing_docs_in_private_items, - clippy::single_match -)] - -fn id(x: T) -> T { - x +#![warn(clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)] + +fn shadow_same() { + let x = 1; + let x = x; + let mut x = &x; + let x = &mut x; + let x = *x; } -#[must_use] -fn first(x: (isize, isize)) -> isize { - x.0 +fn shadow_reuse() -> Option<()> { + let x = ([[0]], ()); + let x = x.0; + let x = x[0]; + let [x] = x; + let x = Some(x); + let x = foo(x); + let x = || x; + let x = Some(1).map(|_| x)?; + None } -fn main() { - let mut x = 1; - let x = &mut x; - let x = { x }; - let x = (&*x); - let x = { *x + 1 }; - let x = id(x); - let x = (1, x); - let x = first(x); - let y = 1; - let x = y; - - let x; - x = 42; - - let o = Some(1_u8); - - if let Some(p) = o { - assert_eq!(1, p); +fn shadow_unrelated() { + let x = 1; + let x = 2; +} + +fn syntax() { + fn f(x: u32) { + let x = 1; + } + let x = 1; + match Some(1) { + Some(1) => {}, + Some(x) => { + let x = 1; + }, + _ => {}, } - match o { - Some(p) => p, // no error, because the p above is in its own scope - None => 0, + if let Some(x) = Some(1) {} + while let Some(x) = Some(1) {} + let _ = |[x]: [u32; 1]| { + let x = 1; }; +} - match (x, o) { - (1, Some(a)) | (a, Some(1)) => (), // no error though `a` appears twice - _ => (), +fn negative() { + match Some(1) { + Some(x) if x == 1 => {}, + Some(x) => {}, + None => {}, } + match [None, Some(1)] { + [Some(x), None] | [None, Some(x)] => {}, + _ => {}, + } + if let Some(x) = Some(1) { + let y = 1; + } else { + let x = 1; + let y = 1; + } + let x = 1; + #[allow(clippy::shadow_unrelated)] + let x = 1; +} + +fn foo(_: T) {} + +fn question_mark() -> Option<()> { + let val = 1; + // `?` expands with a `val` binding + None?; + None } + +fn main() {} diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index 2383974901874..8b60e072c9342 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -1,113 +1,233 @@ -error: `x` is shadowed by itself in `&mut x` - --> $DIR/shadow.rs:27:5 +error: `x` is shadowed by itself in `x` + --> $DIR/shadow.rs:5:9 | -LL | let x = &mut x; - | ^^^^^^^^^^^^^^^ +LL | let x = x; + | ^ | = note: `-D clippy::shadow-same` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:26:13 + --> $DIR/shadow.rs:4:9 | -LL | let mut x = 1; - | ^ +LL | let x = 1; + | ^ -error: `x` is shadowed by itself in `{ x }` - --> $DIR/shadow.rs:28:5 +error: `mut x` is shadowed by itself in `&x` + --> $DIR/shadow.rs:6:13 | -LL | let x = { x }; - | ^^^^^^^^^^^^^^ +LL | let mut x = &x; + | ^ | note: previous binding is here - --> $DIR/shadow.rs:27:9 + --> $DIR/shadow.rs:5:9 + | +LL | let x = x; + | ^ + +error: `x` is shadowed by itself in `&mut x` + --> $DIR/shadow.rs:7:9 | LL | let x = &mut x; | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:6:9 + | +LL | let mut x = &x; + | ^^^^^ -error: `x` is shadowed by itself in `(&*x)` - --> $DIR/shadow.rs:29:5 +error: `x` is shadowed by itself in `*x` + --> $DIR/shadow.rs:8:9 | -LL | let x = (&*x); - | ^^^^^^^^^^^^^^ +LL | let x = *x; + | ^ | note: previous binding is here - --> $DIR/shadow.rs:28:9 + --> $DIR/shadow.rs:7:9 | -LL | let x = { x }; +LL | let x = &mut x; | ^ -error: `x` is shadowed by `{ *x + 1 }` which reuses the original value - --> $DIR/shadow.rs:30:9 +error: `x` is shadowed by `x.0` which reuses the original value + --> $DIR/shadow.rs:13:9 | -LL | let x = { *x + 1 }; +LL | let x = x.0; | ^ | = note: `-D clippy::shadow-reuse` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:29:9 + --> $DIR/shadow.rs:12:9 | -LL | let x = (&*x); +LL | let x = ([[0]], ()); | ^ -error: `x` is shadowed by `id(x)` which reuses the original value - --> $DIR/shadow.rs:31:9 +error: `x` is shadowed by `x[0]` which reuses the original value + --> $DIR/shadow.rs:14:9 | -LL | let x = id(x); +LL | let x = x[0]; | ^ | note: previous binding is here - --> $DIR/shadow.rs:30:9 + --> $DIR/shadow.rs:13:9 | -LL | let x = { *x + 1 }; +LL | let x = x.0; | ^ -error: `x` is shadowed by `(1, x)` which reuses the original value - --> $DIR/shadow.rs:32:9 +error: `x` is shadowed by `x` which reuses the original value + --> $DIR/shadow.rs:15:10 + | +LL | let [x] = x; + | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:14:9 | -LL | let x = (1, x); +LL | let x = x[0]; + | ^ + +error: `x` is shadowed by `Some(x)` which reuses the original value + --> $DIR/shadow.rs:16:9 + | +LL | let x = Some(x); + | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:15:10 + | +LL | let [x] = x; + | ^ + +error: `x` is shadowed by `foo(x)` which reuses the original value + --> $DIR/shadow.rs:17:9 + | +LL | let x = foo(x); | ^ | note: previous binding is here - --> $DIR/shadow.rs:31:9 + --> $DIR/shadow.rs:16:9 | -LL | let x = id(x); +LL | let x = Some(x); | ^ -error: `x` is shadowed by `first(x)` which reuses the original value - --> $DIR/shadow.rs:33:9 +error: `x` is shadowed by `|| x` which reuses the original value + --> $DIR/shadow.rs:18:9 | -LL | let x = first(x); +LL | let x = || x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:32:9 + --> $DIR/shadow.rs:17:9 | -LL | let x = (1, x); +LL | let x = foo(x); | ^ -error: `x` is being shadowed - --> $DIR/shadow.rs:35:9 +error: `x` is shadowed by `Some(1).map(|_| x)?` which reuses the original value + --> $DIR/shadow.rs:19:9 | -LL | let x = y; +LL | let x = Some(1).map(|_| x)?; + | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:18:9 + | +LL | let x = || x; + | ^ + +error: `x` shadows a previous, unrelated binding + --> $DIR/shadow.rs:25:9 + | +LL | let x = 2; | ^ | = note: `-D clippy::shadow-unrelated` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:33:9 + --> $DIR/shadow.rs:24:9 | -LL | let x = first(x); +LL | let x = 1; | ^ -error: `x` shadows a previous declaration - --> $DIR/shadow.rs:37:5 +error: `x` shadows a previous, unrelated binding + --> $DIR/shadow.rs:30:13 | -LL | let x; - | ^^^^^^ +LL | let x = 1; + | ^ | note: previous binding is here - --> $DIR/shadow.rs:35:9 + --> $DIR/shadow.rs:29:10 | -LL | let x = y; +LL | fn f(x: u32) { + | ^ + +error: `x` shadows a previous, unrelated binding + --> $DIR/shadow.rs:35:14 + | +LL | Some(x) => { + | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:32:9 + | +LL | let x = 1; | ^ -error: aborting due to 9 previous errors +error: `x` shadows a previous, unrelated binding + --> $DIR/shadow.rs:36:17 + | +LL | let x = 1; + | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:35:14 + | +LL | Some(x) => { + | ^ + +error: `x` shadows a previous, unrelated binding + --> $DIR/shadow.rs:40:17 + | +LL | if let Some(x) = Some(1) {} + | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:32:9 + | +LL | let x = 1; + | ^ + +error: `x` shadows a previous, unrelated binding + --> $DIR/shadow.rs:41:20 + | +LL | while let Some(x) = Some(1) {} + | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:32:9 + | +LL | let x = 1; + | ^ + +error: `x` shadows a previous, unrelated binding + --> $DIR/shadow.rs:42:15 + | +LL | let _ = |[x]: [u32; 1]| { + | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:32:9 + | +LL | let x = 1; + | ^ + +error: `x` shadows a previous, unrelated binding + --> $DIR/shadow.rs:43:13 + | +LL | let x = 1; + | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:42:15 + | +LL | let _ = |[x]: [u32; 1]| { + | ^ + +error: aborting due to 19 previous errors