From 4dff4df57711b1da61dcbc361b02c6becdefe035 Mon Sep 17 00:00:00 2001 From: mcarton Date: Thu, 30 Jun 2016 00:08:43 +0200 Subject: [PATCH] Move more functions to `utils::higher` --- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/loops.rs | 4 ++-- clippy_lints/src/mut_mut.rs | 4 ++-- clippy_lints/src/shadow.rs | 4 ++-- clippy_lints/src/types.rs | 4 ++-- clippy_lints/src/utils/higher.rs | 33 +++++++++++++++++++++++++++ clippy_lints/src/utils/mod.rs | 38 ++------------------------------ clippy_lints/src/vec.rs | 4 ++-- 8 files changed, 46 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index aa6dd46cf0b..cee18337ba1 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -156,7 +156,7 @@ fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Exp } } -/// Match `if` or `else if` expressions and return the `then` and `else` block. +/// Match `if` or `if let` expressions and return the `then` and `else` block. fn unsugar_if(expr: &ast::Expr) -> Option<(&P, &Option>)> { match expr.node { ast::ExprKind::If(_, ref then, ref else_) | diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index e945afbf659..1a6ac75eb37 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -15,7 +15,7 @@ use syntax::ast; use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, higher, - walk_ptrs_ty, recover_for_loop}; + walk_ptrs_ty}; use utils::paths; /// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. @@ -223,7 +223,7 @@ impl LintPass for Pass { impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { - if let Some((pat, arg, body)) = recover_for_loop(expr) { + if let Some((pat, arg, body)) = higher::for_loop(expr) { check_for_loop(cx, pat, arg, body, expr); } // check for `loop { if let {} else break }` that could be `while let` diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 8a5439fb11e..d5d9fe1a0bc 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -2,7 +2,7 @@ use rustc::hir; use rustc::hir::intravisit; use rustc::lint::*; use rustc::ty::{TypeAndMut, TyRef}; -use utils::{in_external_macro, recover_for_loop, span_lint}; +use utils::{higher, in_external_macro, span_lint}; /// **What it does:** This lint checks for instances of `mut mut` references. /// @@ -49,7 +49,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> { return; } - if let Some((_, arg, body)) = recover_for_loop(expr) { + if let Some((_, arg, body)) = higher::for_loop(expr) { // A `for` loop lowers to: // ```rust // match ::std::iter::Iterator::next(&mut iter) { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index b12e68185c2..7bda94ed639 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -5,7 +5,7 @@ use rustc::hir::*; use rustc::hir::intravisit::{Visitor, FnKind}; use std::ops::Deref; use syntax::codemap::Span; -use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint_and_then}; +use utils::{higher, in_external_macro, snippet, span_lint_and_then}; /// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability. /// @@ -91,7 +91,7 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx, decl.span) { return; } - if is_from_for_desugar(decl) { + if higher::is_from_for_desugar(decl) { return; } if let DeclLocal(ref local) = decl.node { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 83e2c1b549c..629834a3c0f 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -6,7 +6,7 @@ use rustc::ty; use std::cmp::Ordering; use syntax::ast::{IntTy, UintTy, FloatTy}; use syntax::codemap::Span; -use utils::{comparisons, in_external_macro, in_macro, is_from_for_desugar, match_def_path, snippet, +use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet, span_help_and_lint, span_lint}; use utils::paths; @@ -106,7 +106,7 @@ fn check_let_unit(cx: &LateContext, decl: &Decl) { if in_external_macro(cx, decl.span) || in_macro(cx, local.pat.span) { return; } - if is_from_for_desugar(decl) { + if higher::is_from_for_desugar(decl) { return; } span_lint(cx, diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 979c044cdbf..16ab44881a5 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -115,3 +115,36 @@ pub fn range(expr: &hir::Expr) -> Option { } } +/// Checks if a `let` decl is from a `for` loop desugaring. +pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { + if_let_chain! {[ + let hir::DeclLocal(ref loc) = decl.node, + let Some(ref expr) = loc.init, + let hir::ExprMatch(_, _, hir::MatchSource::ForLoopDesugar) = expr.node, + ], { + return true; + }} + false +} + +/// Recover the essential nodes of a desugared for loop: +/// `for pat in arg { body }` becomes `(pat, arg, body)`. +pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> { + if_let_chain! {[ + let hir::ExprMatch(ref iterexpr, ref arms, _) = expr.node, + let hir::ExprCall(_, ref iterargs) = iterexpr.node, + iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), + let hir::ExprLoop(ref block, _) = arms[0].body.node, + block.stmts.is_empty(), + let Some(ref loopexpr) = block.expr, + let hir::ExprMatch(_, ref innerarms, hir::MatchSource::ForLoopDesugar) = loopexpr.node, + innerarms.len() == 2 && innerarms[0].pats.len() == 1, + let hir::PatKind::TupleStruct(_, ref somepats, _) = innerarms[0].pats[0].node, + somepats.len() == 1 + ], { + return Some((&somepats[0], + &iterargs[0], + &innerarms[0].body)); + }} + None +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 3ceae788a4d..df9d09ed010 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -21,7 +21,6 @@ use syntax::ptr::P; pub mod cargo; pub mod comparisons; pub mod conf; -pub mod higher; mod hir; pub mod paths; pub mod sugg; @@ -82,6 +81,8 @@ macro_rules! if_let_chain { }; } +pub mod higher; + /// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one /// isn't). pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { @@ -319,19 +320,6 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option { } } -/// Checks if a `let` decl is from a `for` loop desugaring. -pub fn is_from_for_desugar(decl: &Decl) -> bool { - if_let_chain! {[ - let DeclLocal(ref loc) = decl.node, - let Some(ref expr) = loc.init, - let ExprMatch(_, _, MatchSource::ForLoopDesugar) = expr.node - ], { - return true; - }} - false -} - - /// Convert a span to a code snippet if available, otherwise use default. /// /// # Example @@ -706,25 +694,3 @@ pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty infcx.can_equate(&new_a, &new_b).is_ok() }) } - -/// Recover the essential nodes of a desugared for loop: -/// `for pat in arg { body }` becomes `(pat, arg, body)`. -pub fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> { - if_let_chain! {[ - let ExprMatch(ref iterexpr, ref arms, _) = expr.node, - let ExprCall(_, ref iterargs) = iterexpr.node, - iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), - let ExprLoop(ref block, _) = arms[0].body.node, - block.stmts.is_empty(), - let Some(ref loopexpr) = block.expr, - let ExprMatch(_, ref innerarms, MatchSource::ForLoopDesugar) = loopexpr.node, - innerarms.len() == 2 && innerarms[0].pats.len() == 1, - let PatKind::TupleStruct(_, ref somepats, _) = innerarms[0].pats[0].node, - somepats.len() == 1 - ], { - return Some((&somepats[0], - &iterargs[0], - &innerarms[0].body)); - }} - None -} diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 73f2fb7caa8..97a45da4536 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -3,7 +3,7 @@ use rustc::ty::TypeVariants; use rustc::hir::*; use syntax::codemap::Span; use syntax::ptr::P; -use utils::{is_expn_of, match_path, paths, recover_for_loop, snippet, span_lint_and_then}; +use utils::{higher, is_expn_of, match_path, paths, snippet, span_lint_and_then}; /// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible. /// @@ -42,7 +42,7 @@ impl LateLintPass for Pass { }} // search for `for _ in vec![…]` - if let Some((_, arg, _)) = recover_for_loop(expr) { + if let Some((_, arg, _)) = higher::for_loop(expr) { // report the error around the `vec!` not inside `:` let span = cx.sess().codemap().source_callsite(arg.span); check_vec_macro(cx, arg, span);