Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Suggest deref non-lvalue mutable reference
  • Loading branch information
compiler-errors committed May 18, 2022
commit a5c4f4cc4b14b2dff2506d08defb1b97adcbf333
22 changes: 20 additions & 2 deletions compiler/rustc_typeck/src/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lhs: &'tcx hir::Expr<'tcx>,
err_code: &'static str,
op_span: Span,
adjust_err: impl FnOnce(&mut DiagnosticBuilder<'tcx, ErrorGuaranteed>),
) {
if lhs.is_syntactic_place_expr() {
return;
Expand All @@ -858,6 +859,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
});

adjust_err(&mut err);

err.emit();
}

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

self.check_lhs_assignable(lhs, "E0070", span);

let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);

self.check_lhs_assignable(lhs, "E0070", span, |err| {
let rhs_ty = self.check_expr(&rhs);

if let ty::Ref(_, lhs_inner_ty, hir::Mutability::Mut) = lhs_ty.kind() {
if self.can_coerce(rhs_ty, *lhs_inner_ty) {
err.span_suggestion_verbose(
lhs.span.shrink_to_lo(),
"consider dereferencing here to assign to the mutable \
borrowed piece of memory",
"*".to_string(),
Applicability::MachineApplicable,
);
}
}
});

let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs));

self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return_ty
};

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

ty
}
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui/typeck/assign-non-lval-mut-ref.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// run-rustfix

fn main() {
let mut x = vec![1usize];
*x.last_mut().unwrap() = 2usize;
//~^ ERROR invalid left-hand side of assignment
}
7 changes: 7 additions & 0 deletions src/test/ui/typeck/assign-non-lval-mut-ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// run-rustfix

fn main() {
let mut x = vec![1usize];
x.last_mut().unwrap() = 2usize;
//~^ ERROR invalid left-hand side of assignment
}
16 changes: 16 additions & 0 deletions src/test/ui/typeck/assign-non-lval-mut-ref.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0070]: invalid left-hand side of assignment
--> $DIR/assign-non-lval-mut-ref.rs:5:27
|
LL | x.last_mut().unwrap() = 2usize;
| --------------------- ^
| |
| cannot assign to this expression
|
help: consider dereferencing here to assign to the mutable borrowed piece of memory
|
LL | *x.last_mut().unwrap() = 2usize;
| +

error: aborting due to previous error

For more information about this error, try `rustc --explain E0070`.
5 changes: 5 additions & 0 deletions src/test/ui/typeck/issue-93486.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ LL | vec![].last_mut().unwrap() = 3_u8;
| -------------------------- ^
| |
| cannot assign to this expression
|
help: consider dereferencing here to assign to the mutable borrowed piece of memory
|
LL | *vec![].last_mut().unwrap() = 3_u8;
| +

error: aborting due to previous error

Expand Down