X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=clippy_lints%2Fsrc%2Flet_if_seq.rs;h=0594b73dd38378dd17f4821f639fb76ea8e4815a;hb=21da42ce29c33e4a33b215a93b19bf8b5f06228d;hp=d7bf8a1476817c28892be2a3033f120fb2585301;hpb=8164832c4b085dd10b404392ddcab7565280806c;p=rust.git diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index d7bf8a14768..0594b73dd38 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,23 +1,22 @@ -use crate::utils::{higher, qpath_res, snippet, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use clippy_utils::{path_to_local_id, visitors::LocalUsedVisitor}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::def::Res; -use rustc_hir::intravisit; use rustc_hir::BindingAnnotation; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { - /// **What it does:** Checks for variable declarations immediately followed by a + /// ### What it does + /// Checks for variable declarations immediately followed by a /// conditional affectation. /// - /// **Why is this bad?** This is not idiomatic Rust. + /// ### Why is this bad? + /// This is not idiomatic Rust. /// - /// **Known problems:** None. - /// - /// **Example:** + /// ### Example /// ```rust,ignore /// let foo; /// @@ -56,44 +55,44 @@ declare_lint_pass!(LetIfSeq => [USELESS_LET_IF_SEQ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { - fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block<'_>) { +impl<'tcx> LateLintPass<'tcx> for LetIfSeq { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { let mut it = block.stmts.iter().peekable(); while let Some(stmt) = it.next() { if_chain! { if let Some(expr) = it.peek(); - if let hir::StmtKind::Local(ref local) = stmt.kind; + if let hir::StmtKind::Local(local) = stmt.kind; if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind; - if let hir::StmtKind::Expr(ref if_) = expr.kind; - if let Some((ref cond, ref then, ref else_)) = higher::if_block(&if_); - if !used_in_expr(cx, canonical_id, cond); - if let hir::ExprKind::Block(ref then, _) = then.kind; + if let hir::StmtKind::Expr(if_) = expr.kind; + if let hir::ExprKind::If(hir::Expr { kind: hir::ExprKind::DropTemps(cond), ..}, then, else_) = if_.kind; + let mut used_visitor = LocalUsedVisitor::new(cx, canonical_id); + if !used_visitor.check_expr(cond); + if let hir::ExprKind::Block(then, _) = then.kind; if let Some(value) = check_assign(cx, canonical_id, &*then); - if !used_in_expr(cx, canonical_id, value); + if !used_visitor.check_expr(value); then { let span = stmt.span.to(if_.span); - let has_interior_mutability = !cx.tables.node_type(canonical_id).is_freeze( - cx.tcx, + let has_interior_mutability = !cx.typeck_results().node_type(canonical_id).is_freeze( + cx.tcx.at(span), cx.param_env, - span ); if has_interior_mutability { return; } - let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { - if let hir::ExprKind::Block(ref else_, _) = else_.kind { + let (default_multi_stmts, default) = if let Some(else_) = else_ { + if let hir::ExprKind::Block(else_, _) = else_.kind { if let Some(default) = check_assign(cx, canonical_id, else_) { (else_.stmts.len() > 1, default) - } else if let Some(ref default) = local.init { - (true, &**default) + } else if let Some(default) = local.init { + (true, default) } else { continue; } } else { continue; } - } else if let Some(ref default) = local.init { - (false, &**default) + } else if let Some(default) = local.init { + (false, default) } else { continue; }; @@ -137,58 +136,22 @@ fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block<'_ } } -struct UsedVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, - id: hir::HirId, - used: bool, -} - -impl<'a, 'tcx> intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> { - type Map = Map<'tcx>; - - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { - if_chain! { - if let hir::ExprKind::Path(ref qpath) = expr.kind; - if let Res::Local(local_id) = qpath_res(self.cx, qpath, expr.hir_id); - if self.id == local_id; - then { - self.used = true; - return; - } - } - intravisit::walk_expr(self, expr); - } - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { - intravisit::NestedVisitorMap::None - } -} - -fn check_assign<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_assign<'tcx>( + cx: &LateContext<'tcx>, decl: hir::HirId, block: &'tcx hir::Block<'_>, ) -> Option<&'tcx hir::Expr<'tcx>> { if_chain! { if block.expr.is_none(); if let Some(expr) = block.stmts.iter().last(); - if let hir::StmtKind::Semi(ref expr) = expr.kind; - if let hir::ExprKind::Assign(ref var, ref value, _) = expr.kind; - if let hir::ExprKind::Path(ref qpath) = var.kind; - if let Res::Local(local_id) = qpath_res(cx, qpath, var.hir_id); - if decl == local_id; + if let hir::StmtKind::Semi(expr) = expr.kind; + if let hir::ExprKind::Assign(var, value, _) = expr.kind; + if path_to_local_id(var, decl); then { - let mut v = UsedVisitor { - cx, - id: decl, - used: false, - }; - - for s in block.stmts.iter().take(block.stmts.len()-1) { - intravisit::walk_stmt(&mut v, s); + let mut v = LocalUsedVisitor::new(cx, decl); - if v.used { - return None; - } + if block.stmts.iter().take(block.stmts.len()-1).any(|stmt| v.check_stmt(stmt)) { + return None; } return Some(value); @@ -197,9 +160,3 @@ fn check_assign<'a, 'tcx>( None } - -fn used_in_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> bool { - let mut v = UsedVisitor { cx, id, used: false }; - intravisit::walk_expr(&mut v, expr); - v.used -}