diff --git a/src/mut_mut.rs b/src/mut_mut.rs index bf8155b5c3c..b1e21def574 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -2,6 +2,7 @@ use syntax::ptr::P; use syntax::ast::*; use rustc::lint::{Context, LintPass, LintArray, Lint}; use rustc::middle::ty::{expr_ty, sty, ty_ptr, ty_rptr, mt}; +use syntax::codemap::ExpnInfo; declare_lint!(pub MUT_MUT, Warn, "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); @@ -15,27 +16,8 @@ impl LintPass for MutMut { } fn check_expr(&mut self, cx: &Context, expr: &Expr) { - - fn unwrap_addr(expr : &Expr) -> Option<&Expr> { - match expr.node { - ExprAddrOf(MutMutable, ref e) => Option::Some(e), - _ => Option::None - } - } - - unwrap_addr(expr).map_or((), |e| { - unwrap_addr(e).map(|_| { - cx.span_lint(MUT_MUT, expr.span, - "Generally you want to avoid &mut &mut _ if possible.") - }).unwrap_or_else(|| { - if let ty_rptr(_, mt{ty: _, mutbl: MutMutable}) = - expr_ty(cx.tcx, e).sty { - cx.span_lint(MUT_MUT, expr.span, - "This expression mutably borrows a mutable reference. \ - Consider reborrowing") - } - }) - }) + cx.sess().codemap().with_expn_info(expr.span.expn_id, + |info| check_expr_expd(cx, expr, info)) } fn check_ty(&mut self, cx: &Context, ty: &Ty) { @@ -44,6 +26,35 @@ impl LintPass for MutMut { } } +fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { + if in_external_macro(info) { return; } + + fn unwrap_addr(expr : &Expr) -> Option<&Expr> { + match expr.node { + ExprAddrOf(MutMutable, ref e) => Option::Some(e), + _ => Option::None + } + } + + unwrap_addr(expr).map_or((), |e| { + unwrap_addr(e).map(|_| { + cx.span_lint(MUT_MUT, expr.span, + "Generally you want to avoid &mut &mut _ if possible.") + }).unwrap_or_else(|| { + if let ty_rptr(_, mt{ty: _, mutbl: MutMutable}) = + expr_ty(cx.tcx, e).sty { + cx.span_lint(MUT_MUT, expr.span, + "This expression mutably borrows a mutable reference. \ + Consider reborrowing") + } + }) + }) +} + +fn in_external_macro(info: Option<&ExpnInfo>) -> bool { + info.map_or(false, |i| i.callee.span.is_some()) +} + fn unwrap_mut(ty : &Ty) -> Option<&Ty> { match ty.node { TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty),