Move more functions to utils::higher
This commit is contained in:
parent
92b04129fe
commit
4dff4df577
@ -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<ast::Block>, &Option<P<ast::Expr>>)> {
|
||||
match expr.node {
|
||||
ast::ExprKind::If(_, ref then, ref else_) |
|
||||
|
@ -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`
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -115,3 +115,36 @@ pub fn range(expr: &hir::Expr) -> Option<Range> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
}
|
||||
|
@ -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<Name> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
}
|
||||
|
@ -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 `<std macros>:`
|
||||
let span = cx.sess().codemap().source_callsite(arg.span);
|
||||
check_vec_macro(cx, arg, span);
|
||||
|
Loading…
x
Reference in New Issue
Block a user