+use crate::consts::constant;
+use crate::utils::{higher, is_copy, snippet_with_applicability, span_lint_and_sugg};
+use if_chain::if_chain;
use rustc::hir::*;
-use rustc::lint::*;
+use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty::{self, Ty};
-use rustc::ty::subst::Substs;
-use rustc_const_eval::ConstContext;
-use syntax::codemap::Span;
-use utils::{higher, is_copy, snippet, span_lint_and_sugg};
+use rustc::{declare_tool_lint, lint_array};
+use rustc_errors::Applicability;
+use syntax::source_map::Span;
-/// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would
-/// be possible.
-///
-/// **Why is this bad?** This is less efficient.
-///
-/// **Known problems:** None.
-///
-/// **Example:**
-/// ```rust,ignore
-/// foo(&vec![1, 2])
-/// ```
-declare_lint! {
+declare_clippy_lint! {
+ /// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would
+ /// be possible.
+ ///
+ /// **Why is this bad?** This is less efficient.
+ ///
+ /// **Known problems:** None.
+ ///
+ /// **Example:**
+ /// ```rust,ignore
+ /// foo(&vec![1, 2])
+ /// ```
pub USELESS_VEC,
- Warn,
+ perf,
"useless `vec!`"
}
fn get_lints(&self) -> LintArray {
lint_array!(USELESS_VEC)
}
+
+ fn name(&self) -> &'static str {
+ "UselessVec"
+ }
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
// search for `&vec![_]` expressions where the adjusted type is `&[_]`
if_chain! {
- if let ty::TyRef(_, ref ty) = cx.tables.expr_ty_adjusted(expr).sty;
- if let ty::TySlice(..) = ty.ty.sty;
- if let ExprAddrOf(_, ref addressee) = expr.node;
+ if let ty::Ref(_, ty, _) = cx.tables.expr_ty_adjusted(expr).sty;
+ if let ty::Slice(..) = ty.sty;
+ if let ExprKind::AddrOf(_, ref addressee) = expr.node;
if let Some(vec_args) = higher::vec_macro(cx, addressee);
then {
check_vec_macro(cx, &vec_args, expr.span);
if is_copy(cx, vec_type(cx.tables.expr_ty_adjusted(arg)));
then {
// report the error around the `vec!` not inside `<std macros>:`
- let span = arg.span.ctxt().outer().expn_info().map(|info| info.call_site).expect("unable to get call_site");
+ let span = arg.span
+ .ctxt()
+ .outer()
+ .expn_info()
+ .map(|info| info.call_site)
+ .expect("unable to get call_site")
+ .ctxt()
+ .outer()
+ .expn_info()
+ .map(|info| info.call_site)
+ .expect("unable to get call_site");
check_vec_macro(cx, &vec_args, span);
}
}
}
fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) {
+ let mut applicability = Applicability::MachineApplicable;
let snippet = match *vec_args {
higher::VecArgs::Repeat(elem, len) => {
- let parent_item = cx.tcx.hir.get_parent(len.id);
- let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
- let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
- if ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables)
- .eval(len)
- .is_ok()
- {
- format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len"))
+ if constant(cx, cx.tables, len).is_some() {
+ format!(
+ "&[{}; {}]",
+ snippet_with_applicability(cx, elem.span, "elem", &mut applicability),
+ snippet_with_applicability(cx, len.span, "len", &mut applicability)
+ )
} else {
return;
}
},
- higher::VecArgs::Vec(args) => if let Some(last) = args.iter().last() {
- let span = args[0].span.to(last.span);
+ higher::VecArgs::Vec(args) => {
+ if let Some(last) = args.iter().last() {
+ let span = args[0].span.to(last.span);
- format!("&[{}]", snippet(cx, span, ".."))
- } else {
- "&[]".into()
+ format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability))
+ } else {
+ "&[]".into()
+ }
},
};
"useless use of `vec!`",
"you can use a slice directly",
snippet,
+ applicability,
);
}
-/// Return the item type of the vector (ie. the `T` in `Vec<T>`).
-fn vec_type(ty: Ty) -> Ty {
- if let ty::TyAdt(_, substs) = ty.sty {
+/// Returns the item type of the vector (i.e., the `T` in `Vec<T>`).
+fn vec_type(ty: Ty<'_>) -> Ty<'_> {
+ if let ty::Adt(_, substs) = ty.sty {
substs.type_at(0)
} else {
panic!("The type of `vec!` is a not a struct?");