let n = cfg.graph.len_nodes() as u64;
let e = cfg.graph.len_edges() as u64;
let cc = e + 2 - n;
- let mut arm_counter = MatchArmCounter(0);
- arm_counter.visit_block(block);
- let narms = arm_counter.0;
-
- let mut diverge_counter = DivergenceCounter(0, &cx.tcx);
- diverge_counter.visit_block(block);
- let divergence = diverge_counter.0;
-
- if cc + divergence < narms {
- report_cc_bug(cx, cc, narms, divergence, span);
+ let mut helper = CCHelper {
+ match_arms: 0,
+ divergence: 0,
+ tcx: &cx.tcx,
+ };
+ helper.visit_block(block);
+ let CCHelper {
+ match_arms,
+ divergence,
+ ..
+ } = helper;
+
+ if cc + divergence < match_arms {
+ report_cc_bug(cx, cc, match_arms, divergence, span);
} else {
- let rust_cc = cc + divergence - narms;
+ let rust_cc = cc + divergence - match_arms;
if rust_cc > self.limit.limit() {
span_help_and_lint(cx,
CYCLOMATIC_COMPLEXITY,
}
}
-struct MatchArmCounter(u64);
+struct CCHelper<'a, 'tcx: 'a> {
+ match_arms: u64,
+ divergence: u64,
+ tcx: &'a ty::TyCtxt<'tcx>,
+}
-impl<'a> Visitor<'a> for MatchArmCounter {
+impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> {
fn visit_expr(&mut self, e: &'a Expr) {
match e.node {
ExprMatch(_, ref arms, _) => {
walk_expr(self, e);
let arms_n: u64 = arms.iter().map(|arm| arm.pats.len() as u64).sum();
if arms_n > 1 {
- self.0 += arms_n - 2;
+ self.match_arms += arms_n - 2;
}
}
- ExprClosure(..) => {}
- _ => walk_expr(self, e),
- }
- }
-}
-
-struct DivergenceCounter<'a, 'tcx: 'a>(u64, &'a ty::ctxt<'tcx>);
-
-impl<'a, 'b, 'tcx> Visitor<'a> for DivergenceCounter<'b, 'tcx> {
- fn visit_expr(&mut self, e: &'a Expr) {
- match e.node {
ExprCall(ref callee, _) => {
walk_expr(self, e);
- let ty = self.1.node_id_to_type(callee.id);
+ let ty = self.tcx.node_id_to_type(callee.id);
if let ty::TyBareFn(_, ty) = ty.sty {
if ty.sig.skip_binder().output.diverges() {
- self.0 += 1;
+ self.divergence += 1;
}
}
}
use rustc_front::hir::*;
use syntax::codemap::Span;
use syntax::ptr::P;
-use utils::{BOX_NEW_PATH, VEC_FROM_ELEM_PATH};
+use utils::VEC_FROM_ELEM_PATH;
use utils::{is_expn_of, match_path, snippet, span_lint_and_then};
/// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible.
impl LateLintPass for UselessVec {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
- unexpand_vec(cx, expr);
-
- // search for `&!vec[_]` expressions where the adjusted type is `&[_]`
+ // search for `&vec![_]` expressions where the adjusted type is `&[_]`
if_let_chain!{[
let TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty,
let TypeVariants::TySlice(..) = ty.ty.sty,
/// Represent the pre-expansion arguments of a `vec!` invocation.
pub enum VecArgs<'a> {
- /// `vec![elem, len]`
+ /// `vec![elem; len]`
Repeat(&'a P<Expr>, &'a P<Expr>),
/// `vec![a, b, c]`
Vec(&'a [P<Expr>]),
else if match_path(path, &["into_vec"]) && args.len() == 1 {
// `vec![a, b, c]` case
if_let_chain!{[
- let ExprCall(ref fun, ref args) = args[0].node,
- let ExprPath(_, ref path) = fun.node,
- match_path(path, &BOX_NEW_PATH) && args.len() == 1,
- let ExprVec(ref args) = args[0].node
+ let ExprBox(ref boxed) = args[0].node,
+ let ExprVec(ref args) = boxed.node
], {
return Some(VecArgs::Vec(&*args));
}}