Skip to content

Commit a5c4f4c

Browse files
Suggest deref non-lvalue mutable reference
1 parent 4c5f6e6 commit a5c4f4c

File tree

6 files changed

+56
-3
lines changed

6 files changed

+56
-3
lines changed

compiler/rustc_typeck/src/check/expr.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
836836
lhs: &'tcx hir::Expr<'tcx>,
837837
err_code: &'static str,
838838
op_span: Span,
839+
adjust_err: impl FnOnce(&mut DiagnosticBuilder<'tcx, ErrorGuaranteed>),
839840
) {
840841
if lhs.is_syntactic_place_expr() {
841842
return;
@@ -858,6 +859,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
858859
);
859860
});
860861

862+
adjust_err(&mut err);
863+
861864
err.emit();
862865
}
863866

@@ -1050,9 +1053,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10501053
return self.tcx.ty_error();
10511054
}
10521055

1053-
self.check_lhs_assignable(lhs, "E0070", span);
1054-
10551056
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
1057+
1058+
self.check_lhs_assignable(lhs, "E0070", span, |err| {
1059+
let rhs_ty = self.check_expr(&rhs);
1060+
1061+
if let ty::Ref(_, lhs_inner_ty, hir::Mutability::Mut) = lhs_ty.kind() {
1062+
if self.can_coerce(rhs_ty, *lhs_inner_ty) {
1063+
err.span_suggestion_verbose(
1064+
lhs.span.shrink_to_lo(),
1065+
"consider dereferencing here to assign to the mutable \
1066+
borrowed piece of memory",
1067+
"*".to_string(),
1068+
Applicability::MachineApplicable,
1069+
);
1070+
}
1071+
}
1072+
});
1073+
10561074
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs));
10571075

10581076
self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);

compiler/rustc_typeck/src/check/op.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4141
return_ty
4242
};
4343

44-
self.check_lhs_assignable(lhs, "E0067", op.span);
44+
self.check_lhs_assignable(lhs, "E0067", op.span, |_| {});
4545

4646
ty
4747
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
let mut x = vec![1usize];
5+
*x.last_mut().unwrap() = 2usize;
6+
//~^ ERROR invalid left-hand side of assignment
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
let mut x = vec![1usize];
5+
x.last_mut().unwrap() = 2usize;
6+
//~^ ERROR invalid left-hand side of assignment
7+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0070]: invalid left-hand side of assignment
2+
--> $DIR/assign-non-lval-mut-ref.rs:5:27
3+
|
4+
LL | x.last_mut().unwrap() = 2usize;
5+
| --------------------- ^
6+
| |
7+
| cannot assign to this expression
8+
|
9+
help: consider dereferencing here to assign to the mutable borrowed piece of memory
10+
|
11+
LL | *x.last_mut().unwrap() = 2usize;
12+
| +
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0070`.

src/test/ui/typeck/issue-93486.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | vec![].last_mut().unwrap() = 3_u8;
55
| -------------------------- ^
66
| |
77
| cannot assign to this expression
8+
|
9+
help: consider dereferencing here to assign to the mutable borrowed piece of memory
10+
|
11+
LL | *vec![].last_mut().unwrap() = 3_u8;
12+
| +
813

914
error: aborting due to previous error
1015

0 commit comments

Comments
 (0)