From 1f8453ab73ef40a33e04c95349c6d3c638e576ae Mon Sep 17 00:00:00 2001 From: llogiq Date: Mon, 18 May 2015 10:41:15 +0200 Subject: [PATCH] mut_mut now more robust (thanks to Manishearth, see issue #9) --- src/mut_mut.rs | 43 +++++++++++++++++++---------------- tests/compile-fail/mut_mut.rs | 5 ++++ 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 0a58e293915..d77a40a4ea5 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -1,11 +1,7 @@ use syntax::ptr::P; -use syntax::ast; use syntax::ast::*; -use syntax::ast_util::{is_comparison_binop, binop_to_string}; -use syntax::visit::{FnKind}; -use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; -use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr, ty_float}; -use syntax::codemap::{Span, Spanned}; +use rustc::lint::{Context, LintPass, LintArray, Lint}; +use rustc::middle::ty::{expr_ty, sty, ty_ptr, ty_rptr, mt}; declare_lint!(pub MUT_MUT, Warn, "Warn on usage of double-mut refs, e.g. '&mut &mut ...'"); @@ -27,25 +23,34 @@ impl LintPass for MutMut { } } - if unwrap_addr(expr).and_then(unwrap_addr).is_some() { - cx.span_lint(MUT_MUT, expr.span, - "We're not sure what this means, so if you know, please tell us.") - } + unwrap_addr(expr).map(|e| { + if unwrap_addr(e).is_some() { + cx.span_lint(MUT_MUT, expr.span, + "We're not sure what this means, so if you know, please tell us.") + } else { + match expr_ty(cx.tcx, e).sty { + ty_ptr(mt{ty: _, mutbl: MutMutable}) | + ty_rptr(_, mt{ty: _, mutbl: MutMutable}) => + cx.span_lint(MUT_MUT, expr.span, + "This expression mutably borrows a mutable reference. Consider direct reborrowing"), + _ => () + } + } + }); } fn check_ty(&mut self, cx: &Context, ty: &Ty) { - - fn unwrap_mut(ty : &Ty) -> Option<&Ty> { - match ty.node { - TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), - TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), - _ => Option::None - } - } - if unwrap_mut(ty).and_then(unwrap_mut).is_some() { cx.span_lint(MUT_MUT, ty.span, "We're not sure what this means, so if you know, please tell us.") } } } + +fn unwrap_mut(ty : &Ty) -> Option<&Ty> { + match ty.node { + TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), + TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), + _ => Option::None + } +} diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs index 7d1dad44a90..65e3762e2c4 100644 --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -7,8 +7,13 @@ fn fun(x : &mut &mut u32) -> bool { //~ERROR } #[deny(mut_mut)] +#[allow(unused_mut, unused_variables)] fn main() { let mut x = &mut &mut 1u32; //~ERROR + { + let mut y = &mut x; //~ERROR + } + if fun(x) { let y : &mut &mut &mut u32 = &mut &mut &mut 2; //~^ ERROR