]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/vec.rs
Merge pull request #3285 from devonhollowood/pedantic-dogfood-items-after-statements
[rust.git] / clippy_lints / src / vec.rs
1 // Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9
10
11 use crate::rustc::hir::*;
12 use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
13 use crate::rustc::{declare_tool_lint, lint_array};
14 use if_chain::if_chain;
15 use crate::rustc::ty::{self, Ty};
16 use crate::syntax::source_map::Span;
17 use crate::utils::{higher, is_copy, snippet, span_lint_and_sugg};
18 use crate::consts::constant;
19
20 /// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would
21 /// be possible.
22 ///
23 /// **Why is this bad?** This is less efficient.
24 ///
25 /// **Known problems:** None.
26 ///
27 /// **Example:**
28 /// ```rust,ignore
29 /// foo(&vec![1, 2])
30 /// ```
31 declare_clippy_lint! {
32     pub USELESS_VEC,
33     perf,
34     "useless `vec!`"
35 }
36
37 #[derive(Copy, Clone, Debug)]
38 pub struct Pass;
39
40 impl LintPass for Pass {
41     fn get_lints(&self) -> LintArray {
42         lint_array!(USELESS_VEC)
43     }
44 }
45
46 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
47     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
48         // search for `&vec![_]` expressions where the adjusted type is `&[_]`
49         if_chain! {
50             if let ty::Ref(_, ty, _) = cx.tables.expr_ty_adjusted(expr).sty;
51             if let ty::Slice(..) = ty.sty;
52             if let ExprKind::AddrOf(_, ref addressee) = expr.node;
53             if let Some(vec_args) = higher::vec_macro(cx, addressee);
54             then {
55                 check_vec_macro(cx, &vec_args, expr.span);
56             }
57         }
58
59         // search for `for _ in vec![…]`
60         if_chain! {
61             if let Some((_, arg, _)) = higher::for_loop(expr);
62             if let Some(vec_args) = higher::vec_macro(cx, arg);
63             if is_copy(cx, vec_type(cx.tables.expr_ty_adjusted(arg)));
64             then {
65                 // report the error around the `vec!` not inside `<std macros>:`
66                 let span = arg.span
67                     .ctxt()
68                     .outer()
69                     .expn_info()
70                     .map(|info| info.call_site)
71                     .expect("unable to get call_site");
72                 check_vec_macro(cx, &vec_args, span);
73             }
74         }
75     }
76 }
77
78 fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) {
79     let snippet = match *vec_args {
80         higher::VecArgs::Repeat(elem, len) => {
81             if constant(cx, cx.tables, len).is_some() {
82                 format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len"))
83             } else {
84                 return;
85             }
86         },
87         higher::VecArgs::Vec(args) => if let Some(last) = args.iter().last() {
88             let span = args[0].span.to(last.span);
89
90             format!("&[{}]", snippet(cx, span, ".."))
91         } else {
92             "&[]".into()
93         },
94     };
95
96     span_lint_and_sugg(
97         cx,
98         USELESS_VEC,
99         span,
100         "useless use of `vec!`",
101         "you can use a slice directly",
102         snippet,
103     );
104 }
105
106 /// Return the item type of the vector (ie. the `T` in `Vec<T>`).
107 fn vec_type(ty: Ty<'_>) -> Ty<'_> {
108     if let ty::Adt(_, substs) = ty.sty {
109         substs.type_at(0)
110     } else {
111         panic!("The type of `vec!` is a not a struct?");
112     }
113 }