diff options
| author | Michael Goulet <michael@errs.io> | 2022-03-04 21:59:13 -0800 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2022-05-17 20:21:54 -0700 |
| commit | a5c4f4cc4b14b2dff2506d08defb1b97adcbf333 (patch) | |
| tree | c04d82a4d30d2856726dc5078528963892583260 | |
| parent | 4c5f6e6277b89e47d73a192078697f7a5f3dc0ac (diff) | |
| download | rust-a5c4f4cc4b14b2dff2506d08defb1b97adcbf333.tar.gz rust-a5c4f4cc4b14b2dff2506d08defb1b97adcbf333.zip | |
Suggest deref non-lvalue mutable reference
| -rw-r--r-- | compiler/rustc_typeck/src/check/expr.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/op.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/typeck/assign-non-lval-mut-ref.fixed | 7 | ||||
| -rw-r--r-- | src/test/ui/typeck/assign-non-lval-mut-ref.rs | 7 | ||||
| -rw-r--r-- | src/test/ui/typeck/assign-non-lval-mut-ref.stderr | 16 | ||||
| -rw-r--r-- | src/test/ui/typeck/issue-93486.stderr | 5 |
6 files changed, 56 insertions, 3 deletions
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index f3a5b9f13dd..9015868b499 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -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; @@ -858,6 +859,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); }); + adjust_err(&mut err); + err.emit(); } @@ -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); diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 1ae53a77adc..5066e21dc8d 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -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 } diff --git a/src/test/ui/typeck/assign-non-lval-mut-ref.fixed b/src/test/ui/typeck/assign-non-lval-mut-ref.fixed new file mode 100644 index 00000000000..76e2afc672a --- /dev/null +++ b/src/test/ui/typeck/assign-non-lval-mut-ref.fixed @@ -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 +} diff --git a/src/test/ui/typeck/assign-non-lval-mut-ref.rs b/src/test/ui/typeck/assign-non-lval-mut-ref.rs new file mode 100644 index 00000000000..ff91f2297c8 --- /dev/null +++ b/src/test/ui/typeck/assign-non-lval-mut-ref.rs @@ -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 +} diff --git a/src/test/ui/typeck/assign-non-lval-mut-ref.stderr b/src/test/ui/typeck/assign-non-lval-mut-ref.stderr new file mode 100644 index 00000000000..745ada5de0b --- /dev/null +++ b/src/test/ui/typeck/assign-non-lval-mut-ref.stderr @@ -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`. diff --git a/src/test/ui/typeck/issue-93486.stderr b/src/test/ui/typeck/issue-93486.stderr index 70b5b63f1cb..95eb021965f 100644 --- a/src/test/ui/typeck/issue-93486.stderr +++ b/src/test/ui/typeck/issue-93486.stderr @@ -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 |
