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,
- unsugar_range, walk_ptrs_ty};
+ unsugar_range, walk_ptrs_ty, recover_for_loop};
use utils::{BTREEMAP_PATH, HASHMAP_PATH, LL_PATH, OPTION_PATH, RESULT_PATH, VEC_PATH};
use utils::UnsugaredRange;
}
}
-/// Recover the essential nodes of a desugared for loop:
-/// `for pat in arg { body }` becomes `(pat, arg, body)`.
-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(_, Some(ref somepats)) = innerarms[0].pats[0].node,
- somepats.len() == 1
- ], {
- return Some((&somepats[0],
- &iterargs[0],
- &innerarms[0].body));
- }
- }
- None
-}
-
struct VarVisitor<'v, 't: 'v> {
cx: &'v LateContext<'v, 't>, // context reference
var: Name, // var name to look for as index
let new_b = b.subst(infcx.tcx, &infcx.parameter_environment.free_substs);
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(_, Some(ref somepats)) = innerarms[0].pats[0].node,
+ somepats.len() == 1
+ ], {
+ return Some((&somepats[0],
+ &iterargs[0],
+ &innerarms[0].body));
+ }
+ }
+ None
+}
use syntax::codemap::Span;
use syntax::ptr::P;
use utils::VEC_FROM_ELEM_PATH;
-use utils::{is_expn_of, match_path, snippet, span_lint_and_then};
+use utils::{is_expn_of, match_path, recover_for_loop, snippet, span_lint_and_then};
/// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible.
///
let TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty,
let TypeVariants::TySlice(..) = ty.ty.sty,
let ExprAddrOf(_, ref addressee) = expr.node,
- let Some(vec_args) = unexpand_vec(cx, addressee)
], {
- let snippet = match vec_args {
- VecArgs::Repeat(elem, len) => {
- format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into()
- }
- VecArgs::Vec(args) => {
- if let Some(last) = args.iter().last() {
- let span = Span {
- lo: args[0].span.lo,
- hi: last.span.hi,
- expn_id: args[0].span.expn_id,
- };
+ check_vec_macro(cx, expr, addressee);
+ }}
+
+ // search for `for _ in vec![…]`
+ if let Some((_, arg, _)) = recover_for_loop(expr) {
+ check_vec_macro(cx, arg, arg);
+ }
+ }
+}
+
+fn check_vec_macro(cx: &LateContext, expr: &Expr, vec: &Expr) {
+ if let Some(vec_args) = unexpand_vec(cx, vec) {
+ let snippet = match vec_args {
+ VecArgs::Repeat(elem, len) => {
+ format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into()
+ }
+ VecArgs::Vec(args) => {
+ if let Some(last) = args.iter().last() {
+ let span = Span {
+ lo: args[0].span.lo,
+ hi: last.span.hi,
+ expn_id: args[0].span.expn_id,
+ };
- format!("&[{}]", snippet(cx, span, "..")).into()
- }
- else {
- "&[]".into()
- }
+ format!("&[{}]", snippet(cx, span, "..")).into()
+ }
+ else {
+ "&[]".into()
}
- };
+ }
+ };
- span_lint_and_then(cx, USELESS_VEC, expr.span, "useless use of `vec!`", |db| {
- db.span_suggestion(expr.span, "you can use a slice directly", snippet);
- });
- }}
+ span_lint_and_then(cx, USELESS_VEC, expr.span, "useless use of `vec!`", |db| {
+ db.span_suggestion(expr.span, "you can use a slice directly", snippet);
+ });
}
}
on_vec(&vec![]);
on_vec(&vec![1, 2]);
on_vec(&vec![1; 2]);
+
+ for a in vec![1, 2, 3] {
+ //~^ ERROR useless use of `vec!`
+ //~| HELP you can use
+ //~| SUGGESTION for a in &[1, 2, 3] {
+ println!("{}", a);
+ }
}