]> git.lizzy.rs Git - rust.git/blob - src/mut_mut.rs
Remove * dep
[rust.git] / src / mut_mut.rs
1 use rustc::lint::*;
2 use rustc_front::hir::*;
3 use rustc::middle::ty::{TypeAndMut, TyRef};
4
5 use utils::{in_external_macro, span_lint};
6
7 /// **What it does:** This lint checks for instances of `mut mut` references. It is `Warn` by default.
8 ///
9 /// **Why is this bad?** Multiple `mut`s don't add anything meaningful to the source.
10 ///
11 /// **Known problems:** None
12 ///
13 /// **Example:** `let x = &mut &mut y;`
14 declare_lint!(pub MUT_MUT, Allow,
15               "usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \
16                or shows a fundamental misunderstanding of references)");
17
18 #[derive(Copy,Clone)]
19 pub struct MutMut;
20
21 impl LintPass for MutMut {
22     fn get_lints(&self) -> LintArray {
23         lint_array!(MUT_MUT)
24     }
25 }
26
27 impl LateLintPass for MutMut {
28     fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
29         check_expr_mut(cx, expr)
30     }
31
32     fn check_ty(&mut self, cx: &LateContext, ty: &Ty) {
33         unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| span_lint(cx, MUT_MUT,
34             ty.span, "generally you want to avoid `&mut &mut _` if possible"))
35     }
36 }
37
38 fn check_expr_mut(cx: &LateContext, expr: &Expr) {
39     if in_external_macro(cx, expr.span) { return; }
40
41     fn unwrap_addr(expr: &Expr) -> Option<&Expr> {
42         match expr.node {
43             ExprAddrOf(MutMutable, ref e) => Some(e),
44             _ => None
45         }
46     }
47
48     unwrap_addr(expr).map_or((), |e| {
49         unwrap_addr(e).map_or_else(
50             || {
51                 if let TyRef(_, TypeAndMut{mutbl: MutMutable, ..}) =
52                     cx.tcx.expr_ty(e).sty {
53                         span_lint(cx, MUT_MUT, expr.span,
54                                   "this expression mutably borrows a mutable reference. \
55                                    Consider reborrowing")
56                 }
57             },
58             |_| {
59                 span_lint(cx, MUT_MUT, expr.span,
60                           "generally you want to avoid `&mut &mut _` if possible")
61             }
62         )
63     })
64 }
65
66 fn unwrap_mut(ty: &Ty) -> Option<&Ty> {
67     match ty.node {
68         TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Some(pty),
69         _ => None
70     }
71 }