Skip to content

Commit 6b235e6

Browse files
committed
Suggest use .get_mut instead of &mut when occur overloaded index expression
Signed-off-by: xizheyin <[email protected]>
1 parent 278e24e commit 6b235e6

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,22 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
11761176
self.body.source_info(location).span
11771177
}
11781178
});
1179+
1180+
// check if the RHS is an overloaded index expression, if so, suggest using .get_mut() instead of &mut, see issue #143732
1181+
let rhs_content_source = self.find_assignments(local).first().map(|&location| {
1182+
if let Some(mir::Statement {
1183+
source_info: _,
1184+
kind:
1185+
mir::StatementKind::Assign(box (_, mir::Rvalue::Ref(_,_,place))),
1186+
..
1187+
}) = self.body[location.block].statements.get(location.statement_index)
1188+
{
1189+
Some(self.borrowed_content_source(place.as_ref()))
1190+
}else{
1191+
None
1192+
}
1193+
}).flatten();
1194+
11791195
match opt_assignment_rhs_span.and_then(|s| s.desugaring_kind()) {
11801196
// on for loops, RHS points to the iterator part
11811197
Some(DesugaringKind::ForLoop) => {
@@ -1203,6 +1219,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
12031219
decl_span,
12041220
opt_assignment_rhs_span,
12051221
opt_ty_info,
1222+
rhs_content_source.is_some_and(|s| {
1223+
matches!(s, BorrowedContentSource::OverloadedIndex(_))
1224+
}),
12061225
)
12071226
} else {
12081227
match local_decl.local_info() {
@@ -1226,6 +1245,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
12261245
decl_span,
12271246
opt_assignment_rhs_span,
12281247
opt_ty_info,
1248+
false,
12291249
),
12301250
}
12311251
}
@@ -1507,6 +1527,7 @@ fn suggest_ampmut<'tcx>(
15071527
decl_span: Span,
15081528
opt_assignment_rhs_span: Option<Span>,
15091529
opt_ty_info: Option<Span>,
1530+
is_overloaded_index: bool,
15101531
) -> Option<AmpMutSugg> {
15111532
// if there is a RHS and it starts with a `&` from it, then check if it is
15121533
// mutable, and if not, put suggest putting `mut ` to make it mutable.
@@ -1553,6 +1574,28 @@ fn suggest_ampmut<'tcx>(
15531574
// if the reference is already mutable then there is nothing we can do
15541575
// here.
15551576
if !is_mut {
1577+
// If this is an overloaded index expression, suggest using .get_mut() instead of &mut
1578+
if is_overloaded_index {
1579+
// Try to extract the expression from &expr[key] to suggest expr.get_mut(key).unwrap()
1580+
let content = rhs_str.strip_prefix('&')?;
1581+
if content.contains('[') && content.contains(']') {
1582+
let bracket_start = content.find('[')?;
1583+
let bracket_end = content.rfind(']')?;
1584+
1585+
if bracket_start < bracket_end {
1586+
let map_part = &content[..bracket_start];
1587+
let key_part = &content[bracket_start + 1..bracket_end];
1588+
1589+
return Some(AmpMutSugg {
1590+
has_sugg: true,
1591+
span: rhs_span,
1592+
suggestion: format!("{}.get_mut({}).unwrap()", map_part, key_part),
1593+
additional: None,
1594+
});
1595+
}
1596+
}
1597+
}
1598+
15561599
// shrink the span to just after the `&` in `&variable`
15571600
let span = rhs_span.with_lo(rhs_span.lo() + BytePos(1)).shrink_to_lo();
15581601

tests/ui/borrowck/suggest-use-as-mut-for-map.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ LL | string.push_str("test");
66
|
77
help: consider changing this to be a mutable reference
88
|
9-
LL | let string = &mut map[&0];
10-
| +++
9+
LL - let string = &map[&0];
10+
LL + let string = map.get_mut(&0).unwrap();
11+
|
1112

1213
error: aborting due to 1 previous error
1314

0 commit comments

Comments
 (0)