]> git.lizzy.rs Git - rust.git/blob - src/mut_mut.rs
moved in_macro to (new) utils.rs
[rust.git] / src / mut_mut.rs
1 use syntax::ptr::P;
2 use syntax::ast::*;
3 use rustc::lint::{Context, LintPass, LintArray, Lint};
4 use rustc::middle::ty::{expr_ty, sty, ty_ptr, ty_rptr, mt};
5 use syntax::codemap::{BytePos, ExpnInfo, MacroFormat, Span};
6 use utils::in_macro;
7
8 declare_lint!(pub MUT_MUT, Warn,
9               "Warn on usage of double-mut refs, e.g. '&mut &mut ...'");
10
11 #[derive(Copy,Clone)]
12 pub struct MutMut;
13
14 impl LintPass for MutMut {
15         fn get_lints(&self) -> LintArray {
16         lint_array!(MUT_MUT)
17         }
18         
19         fn check_expr(&mut self, cx: &Context, expr: &Expr) {
20                 cx.sess().codemap().with_expn_info(expr.span.expn_id, 
21                         |info| check_expr_expd(cx, expr, info))
22         }
23         
24         fn check_ty(&mut self, cx: &Context, ty: &Ty) {
25                 unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| cx.span_lint(MUT_MUT, 
26                         ty.span, "Generally you want to avoid &mut &mut _ if possible."))
27         }
28 }
29
30 fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) {
31         if in_macro(cx, info) { return; }
32
33         fn unwrap_addr(expr : &Expr) -> Option<&Expr> {
34                 match expr.node {
35                         ExprAddrOf(MutMutable, ref e) => Option::Some(e),
36                         _ => Option::None
37                 }
38         }
39         
40         unwrap_addr(expr).map_or((), |e| {
41                 unwrap_addr(e).map(|_| {
42                         cx.span_lint(MUT_MUT, expr.span, 
43                                 "Generally you want to avoid &mut &mut _ if possible.")
44                 }).unwrap_or_else(|| {
45                         if let ty_rptr(_, mt{ty: _, mutbl: MutMutable}) = 
46                                         expr_ty(cx.tcx, e).sty {
47                                 cx.span_lint(MUT_MUT, expr.span,
48                                         "This expression mutably borrows a mutable reference. \
49                                         Consider reborrowing")
50                         }
51                 })
52         })
53 }
54
55 fn unwrap_mut(ty : &Ty) -> Option<&Ty> {
56         match ty.node {
57                 TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty),
58                 TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty),
59                 _ => Option::None
60         }
61 }