Skip to content

File tree

4 files changed

+47
-8
lines changed

4 files changed

+47
-8
lines changed

clippy_lints/src/mut_mut.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,30 @@ impl<'tcx> LateLintPass<'tcx> for MutMut {
5656
}
5757
self.seen_tys.insert(mty.ty.hir_id);
5858

59+
// if there is an even longer chain, like `&mut &mut &mut x`, suggest peeling off
60+
// all extra ones at once
61+
let (mut t, mut t2) = (mty.ty, mty2.ty);
62+
let mut many_muts = false;
63+
loop {
64+
if let TyKind::Ref(_, next) = t2.kind
65+
&& next.mutbl == Mutability::Mut
66+
{
67+
(t, t2) = (t2, next.ty);
68+
many_muts = true;
69+
} else {
70+
break;
71+
}
72+
}
73+
5974
let mut applicability = Applicability::MaybeIncorrect;
60-
let sugg = snippet_with_applicability(cx.sess(), mty.ty.span, "..", &mut applicability);
75+
let sugg = snippet_with_applicability(cx.sess(), t.span, "..", &mut applicability);
76+
let suffix = if many_muts { "s" } else { "" };
6177
span_lint_and_sugg(
6278
cx,
6379
MUT_MUT,
6480
ty.span,
6581
"a type of form `&mut &mut _`",
66-
"remove the extra `&mut`",
82+
format!("remove the extra `&mut`{suffix}"),
6783
sugg.to_string(),
6884
applicability,
6985
);
@@ -91,20 +107,43 @@ impl<'tcx> intravisit::Visitor<'tcx> for MutVisitor<'_, 'tcx> {
91107
intravisit::walk_expr(self, arg);
92108
intravisit::walk_expr(self, body);
93109
} else if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, e) = expr.kind {
94-
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _) = e.kind {
110+
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, e2) = e.kind {
95111
if !expr.span.eq_ctxt(e.span) {
96112
return;
97113
}
114+
115+
// if there is an even longer chain, like `&mut &mut &mut x`, suggest peeling off
116+
// all extra ones at once
117+
let (mut e, mut e2) = (e, e2);
118+
let mut many_muts = false;
119+
loop {
120+
if !e.span.eq_ctxt(e2.span) {
121+
return;
122+
}
123+
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, next) = e2.kind {
124+
(e, e2) = (e2, next);
125+
many_muts = true;
126+
} else {
127+
break;
128+
}
129+
}
130+
98131
let mut applicability = Applicability::MaybeIncorrect;
99132
let sugg = Sugg::hir_with_applicability(self.cx, e, "..", &mut applicability);
133+
let suffix = if many_muts { "s" } else { "" };
100134
span_lint_hir_and_then(
101135
self.cx,
102136
MUT_MUT,
103137
expr.hir_id,
104138
expr.span,
105139
"an expression of form `&mut &mut _`",
106140
|diag| {
107-
diag.span_suggestion(expr.span, "remove the extra `&mut`", sugg, applicability);
141+
diag.span_suggestion(
142+
expr.span,
143+
format!("remove the extra `&mut`{suffix}"),
144+
sugg,
145+
applicability,
146+
);
108147
},
109148
);
110149
} else if let ty::Ref(_, ty, Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind()

tests/ui/mut_mut.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ fn main() {
4343
}
4444

4545
{
46-
let y: &mut &mut u32 = &mut &mut 2;
46+
let y: &mut u32 = &mut 2;
4747
//~^ mut_mut
4848
//~| mut_mut
4949
}

tests/ui/mut_mut.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ error: an expression of form `&mut &mut _`
3535
--> tests/ui/mut_mut.rs:46:37
3636
|
3737
LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2;
38-
| ^^^^^^^^^^^^^^^^ help: remove the extra `&mut`: `&mut &mut 2`
38+
| ^^^^^^^^^^^^^^^^ help: remove the extra `&mut`s: `&mut 2`
3939

4040
error: a type of form `&mut &mut _`
4141
--> tests/ui/mut_mut.rs:46:16
4242
|
4343
LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2;
44-
| ^^^^^^^^^^^^^^^^^^ help: remove the extra `&mut`: `&mut &mut u32`
44+
| ^^^^^^^^^^^^^^^^^^ help: remove the extra `&mut`s: `&mut u32`
4545

4646
error: aborting due to 7 previous errors
4747

tests/ui/mut_mut_unfixable.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ error: an expression of form `&mut &mut _`
2929
--> tests/ui/mut_mut_unfixable.rs:30:17
3030
|
3131
LL | let y = &mut &mut &mut 2;
32-
| ^^^^^^^^^^^^^^^^ help: remove the extra `&mut`: `&mut &mut 2`
32+
| ^^^^^^^^^^^^^^^^ help: remove the extra `&mut`s: `&mut 2`
3333

3434
error: aborting due to 5 previous errors
3535

0 commit comments

Comments
 (0)