]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/mut_mut.rs
Fix deploy.sh III
[rust.git] / clippy_lints / src / mut_mut.rs
1 use rustc::hir;
2 use rustc::hir::intravisit;
3 use rustc::lint::*;
4 use rustc::ty::{TypeAndMut, TyRef};
5 use utils::{higher, in_external_macro, span_lint};
6
7 /// **What it does:** This lint checks for instances of `mut mut` references.
8 ///
9 /// **Why is this bad?** Multiple `mut`s don't add anything meaningful to the source. This is
10 /// either a copy'n'paste error, or it shows a fundamental misunderstanding of references)
11 ///
12 /// **Known problems:** None
13 ///
14 /// **Example:**
15 /// ```rust
16 /// let x = &mut &mut y;
17 /// ```
18 declare_lint! {
19     pub MUT_MUT,
20     Allow,
21     "usage of double-mut refs, e.g. `&mut &mut ...`"
22 }
23
24 #[derive(Copy,Clone)]
25 pub struct MutMut;
26
27 impl LintPass for MutMut {
28     fn get_lints(&self) -> LintArray {
29         lint_array!(MUT_MUT)
30     }
31 }
32
33 impl LateLintPass for MutMut {
34     fn check_block(&mut self, cx: &LateContext, block: &hir::Block) {
35         intravisit::walk_block(&mut MutVisitor { cx: cx }, block);
36     }
37
38     fn check_ty(&mut self, cx: &LateContext, ty: &hir::Ty) {
39         use rustc::hir::intravisit::Visitor;
40
41         MutVisitor { cx: cx }.visit_ty(ty);
42     }
43 }
44
45 pub struct MutVisitor<'a, 'tcx: 'a> {
46     cx: &'a LateContext<'a, 'tcx>,
47 }
48
49 impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> {
50     fn visit_expr(&mut self, expr: &'v hir::Expr) {
51         if in_external_macro(self.cx, expr.span) {
52             return;
53         }
54
55         if let Some((_, arg, body)) = higher::for_loop(expr) {
56             // A `for` loop lowers to:
57             // ```rust
58             // match ::std::iter::Iterator::next(&mut iter) {
59             // //                                ^^^^
60             // ```
61             // Let's ignore the generated code.
62             intravisit::walk_expr(self, arg);
63             intravisit::walk_expr(self, body);
64         } else if let hir::ExprAddrOf(hir::MutMutable, ref e) = expr.node {
65             if let hir::ExprAddrOf(hir::MutMutable, _) = e.node {
66                 span_lint(self.cx, MUT_MUT, expr.span, "generally you want to avoid `&mut &mut _` if possible");
67             } else if let TyRef(_, TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tcx.expr_ty(e).sty {
68                 span_lint(self.cx,
69                           MUT_MUT,
70                           expr.span,
71                           "this expression mutably borrows a mutable reference. Consider reborrowing");
72             }
73         }
74     }
75
76     fn visit_ty(&mut self, ty: &hir::Ty) {
77         if let hir::TyRptr(_, hir::MutTy { ty: ref pty, mutbl: hir::MutMutable }) = ty.node {
78             if let hir::TyRptr(_, hir::MutTy { mutbl: hir::MutMutable, .. }) = pty.node {
79                 span_lint(self.cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible");
80             }
81
82         }
83
84         intravisit::walk_ty(self, ty);
85     }
86 }