3 use rustc
::ty
::{self, Ty}
;
4 use rustc
::ty
::subst
::Substs
;
5 use rustc_const_eval
::ConstContext
;
6 use syntax
::codemap
::Span
;
7 use utils
::{higher, is_copy, snippet, span_lint_and_sugg}
;
9 /// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would
12 /// **Why is this bad?** This is less efficient.
14 /// **Known problems:** None.
26 #[derive(Copy, Clone, Debug)]
29 impl LintPass
for Pass
{
30 fn get_lints(&self) -> LintArray
{
31 lint_array
!(USELESS_VEC
)
35 impl<'a
, 'tcx
> LateLintPass
<'a
, 'tcx
> for Pass
{
36 fn check_expr(&mut self, cx
: &LateContext
<'a
, 'tcx
>, expr
: &'tcx Expr
) {
37 // search for `&vec![_]` expressions where the adjusted type is `&[_]`
39 let ty
::TyRef(_
, ref ty
) = cx
.tables
.expr_ty_adjusted(expr
).sty
,
40 let ty
::TySlice(..) = ty
.ty
.sty
,
41 let ExprAddrOf(_
, ref addressee
) = expr
.node
,
42 let Some(vec_args
) = higher
::vec_macro(cx
, addressee
),
44 check_vec_macro(cx
, &vec_args
, expr
.span
);
47 // search for `for _ in vec![…]`
49 let Some((_
, arg
, _
)) = higher
::for_loop(expr
),
50 let Some(vec_args
) = higher
::vec_macro(cx
, arg
),
51 is_copy(cx
, vec_type(cx
.tables
.expr_ty_adjusted(arg
))),
53 // report the error around the `vec!` not inside `<std macros>:`
54 let span
= arg
.span
.ctxt().outer().expn_info().map(|info
| info
.call_site
).expect("unable to get call_site");
55 check_vec_macro(cx
, &vec_args
, span
);
60 fn check_vec_macro(cx
: &LateContext
, vec_args
: &higher
::VecArgs
, span
: Span
) {
61 let snippet
= match *vec_args
{
62 higher
::VecArgs
::Repeat(elem
, len
) => {
63 let parent_item
= cx
.tcx
.hir
.get_parent(len
.id
);
64 let parent_def_id
= cx
.tcx
.hir
.local_def_id(parent_item
);
65 let substs
= Substs
::identity_for_item(cx
.tcx
, parent_def_id
);
66 if ConstContext
::new(cx
.tcx
, cx
.param_env
.and(substs
), cx
.tables
)
70 format
!("&[{}; {}]", snippet(cx
, elem
.span
, "elem"), snippet(cx
, len
.span
, "len")).into()
75 higher
::VecArgs
::Vec(args
) => {
76 if let Some(last
) = args
.iter().last() {
77 let span
= args
[0].span
.to(last
.span
);
79 format
!("&[{}]", snippet(cx
, span
, "..")).into()
90 "useless use of `vec!`",
91 "you can use a slice directly",
96 /// Return the item type of the vector (ie. the `T` in `Vec<T>`).
97 fn vec_type(ty
: Ty
) -> Ty
{
98 if let ty
::TyAdt(_
, substs
) = ty
.sty
{
101 panic
!("The type of `vec!` is a not a struct?");