mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-18 03:25:55 +00:00
Merge pull request #807 from mcarton/vec
Add `for _ in vec![…]` to the `USELESS_VEC` lint
This commit is contained in:
commit
9cbfa5dbc9
26
src/loops.rs
26
src/loops.rs
@ -14,7 +14,7 @@ use syntax::ast;
|
|||||||
|
|
||||||
use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro,
|
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,
|
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::{BTREEMAP_PATH, HASHMAP_PATH, LL_PATH, OPTION_PATH, RESULT_PATH, VEC_PATH};
|
||||||
use utils::UnsugaredRange;
|
use utils::UnsugaredRange;
|
||||||
|
|
||||||
@ -641,30 +641,6 @@ impl<'a> Visitor<'a> for UsedVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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> {
|
struct VarVisitor<'v, 't: 'v> {
|
||||||
cx: &'v LateContext<'v, 't>, // context reference
|
cx: &'v LateContext<'v, 't>, // context reference
|
||||||
var: Name, // var name to look for as index
|
var: Name, // var name to look for as index
|
||||||
|
@ -800,3 +800,27 @@ pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty
|
|||||||
let new_b = b.subst(infcx.tcx, &infcx.parameter_environment.free_substs);
|
let new_b = b.subst(infcx.tcx, &infcx.parameter_environment.free_substs);
|
||||||
infcx.can_equate(&new_a, &new_b).is_ok()
|
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
|
||||||
|
}
|
||||||
|
60
src/vec.rs
60
src/vec.rs
@ -4,7 +4,7 @@ use rustc_front::hir::*;
|
|||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use utils::VEC_FROM_ELEM_PATH;
|
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.
|
/// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible.
|
||||||
///
|
///
|
||||||
@ -38,32 +38,42 @@ impl LateLintPass for UselessVec {
|
|||||||
let TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty,
|
let TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty,
|
||||||
let TypeVariants::TySlice(..) = ty.ty.sty,
|
let TypeVariants::TySlice(..) = ty.ty.sty,
|
||||||
let ExprAddrOf(_, ref addressee) = expr.node,
|
let ExprAddrOf(_, ref addressee) = expr.node,
|
||||||
let Some(vec_args) = unexpand_vec(cx, addressee)
|
|
||||||
], {
|
], {
|
||||||
let snippet = match vec_args {
|
check_vec_macro(cx, expr, addressee);
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,4 +41,11 @@ fn main() {
|
|||||||
on_vec(&vec![]);
|
on_vec(&vec![]);
|
||||||
on_vec(&vec![1, 2]);
|
on_vec(&vec![1, 2]);
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user