@@ -2,11 +2,12 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
2
2
use clippy_utils:: higher;
3
3
use clippy_utils:: source:: snippet_with_applicability;
4
4
use clippy_utils:: sugg:: Sugg ;
5
+ use rustc_data_structures:: fx:: FxHashSet ;
5
6
use rustc_errors:: Applicability ;
6
- use rustc_hir:: { self as hir, AmbigArg , intravisit} ;
7
+ use rustc_hir:: { self as hir, AmbigArg , HirId , intravisit} ;
7
8
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
8
9
use rustc_middle:: ty;
9
- use rustc_session:: declare_lint_pass ;
10
+ use rustc_session:: impl_lint_pass ;
10
11
11
12
declare_clippy_lint ! {
12
13
/// ### What it does
@@ -28,7 +29,12 @@ declare_clippy_lint! {
28
29
"usage of double-mut refs, e.g., `&mut &mut ...`"
29
30
}
30
31
31
- declare_lint_pass ! ( MutMut => [ MUT_MUT ] ) ;
32
+ impl_lint_pass ! ( MutMut => [ MUT_MUT ] ) ;
33
+
34
+ #[ derive( Default ) ]
35
+ pub ( crate ) struct MutMut {
36
+ seen_tys : FxHashSet < HirId > ,
37
+ }
32
38
33
39
impl < ' tcx > LateLintPass < ' tcx > for MutMut {
34
40
fn check_block ( & mut self , cx : & LateContext < ' tcx > , block : & ' tcx hir:: Block < ' _ > ) {
@@ -42,6 +48,14 @@ impl<'tcx> LateLintPass<'tcx> for MutMut {
42
48
&& mty2. mutbl == hir:: Mutability :: Mut
43
49
&& !ty. span . in_external_macro ( cx. sess ( ) . source_map ( ) )
44
50
{
51
+ if self . seen_tys . contains ( & ty. hir_id ) {
52
+ // we have 2+ `&mut`s, e.g., `&mut &mut &mut x`
53
+ // and we have already flagged on the outermost `&mut &mut (&mut x)`,
54
+ // so don't flag the inner `&mut &mut (x)`
55
+ return ;
56
+ }
57
+ self . seen_tys . insert ( mty. ty . hir_id ) ;
58
+
45
59
let mut applicability = Applicability :: MaybeIncorrect ;
46
60
let sugg = snippet_with_applicability ( cx. sess ( ) , mty. ty . span , ".." , & mut applicability) ;
47
61
span_lint_and_sugg (
0 commit comments