better error for bad LHS in binop-assign
This commit is contained in:
parent
a5c4f4cc4b
commit
b26580f214
@ -1058,6 +1058,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
self.check_lhs_assignable(lhs, "E0070", span, |err| {
|
self.check_lhs_assignable(lhs, "E0070", span, |err| {
|
||||||
let rhs_ty = self.check_expr(&rhs);
|
let rhs_ty = self.check_expr(&rhs);
|
||||||
|
|
||||||
|
// FIXME: This could be done any time lhs_ty is DerefMut into something that
|
||||||
|
// is compatible with rhs_ty, and not _just_ `&mut`
|
||||||
if let ty::Ref(_, lhs_inner_ty, hir::Mutability::Mut) = lhs_ty.kind() {
|
if let ty::Ref(_, lhs_inner_ty, hir::Mutability::Mut) = lhs_ty.kind() {
|
||||||
if self.can_coerce(rhs_ty, *lhs_inner_ty) {
|
if self.can_coerce(rhs_ty, *lhs_inner_ty) {
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
|
@ -41,7 +41,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
return_ty
|
return_ty
|
||||||
};
|
};
|
||||||
|
|
||||||
self.check_lhs_assignable(lhs, "E0067", op.span, |_| {});
|
self.check_lhs_assignable(lhs, "E0067", op.span, |err| {
|
||||||
|
if let Ref(_, rty, hir::Mutability::Mut) = lhs_ty.kind() {
|
||||||
|
if self
|
||||||
|
.lookup_op_method(*rty, Some(rhs_ty), Some(rhs), Op::Binary(op, IsAssign::Yes))
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
// Suppress this error, since we already emitted
|
||||||
|
// a deref suggestion in check_overloaded_binop
|
||||||
|
err.delay_as_bug();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
@ -404,8 +415,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
(err, missing_trait, use_output)
|
(err, missing_trait, use_output)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Ref(_, rty, _) = lhs_ty.kind() {
|
if let Ref(_, rty, mutability) = lhs_ty.kind() {
|
||||||
if self.infcx.type_is_copy_modulo_regions(self.param_env, *rty, lhs_expr.span)
|
let is_copy =
|
||||||
|
self.infcx.type_is_copy_modulo_regions(self.param_env, *rty, lhs_expr.span);
|
||||||
|
// We should suggest `a + b` => `*a + b` if `a` is copy, and suggest
|
||||||
|
// `a += b` => `*a += b` if a is a mut ref.
|
||||||
|
// FIXME: This could be done any time lhs_ty is DerefMut into something that
|
||||||
|
// is compatible with rhs_ty, and not _just_ `&mut` (for IsAssign::Yes).
|
||||||
|
if ((is_assign == IsAssign::No && is_copy)
|
||||||
|
|| (is_assign == IsAssign::Yes && *mutability == hir::Mutability::Mut))
|
||||||
&& self
|
&& self
|
||||||
.lookup_op_method(
|
.lookup_op_method(
|
||||||
*rty,
|
*rty,
|
||||||
|
@ -5,11 +5,6 @@ LL | let x = |ref x: isize| { x += 1; };
|
|||||||
| -^^^^^
|
| -^^^^^
|
||||||
| |
|
| |
|
||||||
| cannot use `+=` on type `&isize`
|
| cannot use `+=` on type `&isize`
|
||||||
|
|
|
||||||
help: `+=` can be used on `isize`, you can dereference `x`
|
|
||||||
|
|
|
||||||
LL | let x = |ref x: isize| { *x += 1; };
|
|
||||||
| +
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut x = vec![1usize];
|
let mut x = vec![1usize];
|
||||||
*x.last_mut().unwrap() = 2usize;
|
*x.last_mut().unwrap() = 2;
|
||||||
//~^ ERROR invalid left-hand side of assignment
|
//~^ ERROR invalid left-hand side of assignment
|
||||||
|
*x.last_mut().unwrap() += 1;
|
||||||
|
//~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize`
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut x = vec![1usize];
|
let mut x = vec![1usize];
|
||||||
x.last_mut().unwrap() = 2usize;
|
x.last_mut().unwrap() = 2;
|
||||||
//~^ ERROR invalid left-hand side of assignment
|
//~^ ERROR invalid left-hand side of assignment
|
||||||
|
x.last_mut().unwrap() += 1;
|
||||||
|
//~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize`
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,30 @@
|
|||||||
error[E0070]: invalid left-hand side of assignment
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/assign-non-lval-mut-ref.rs:5:27
|
--> $DIR/assign-non-lval-mut-ref.rs:5:27
|
||||||
|
|
|
|
||||||
LL | x.last_mut().unwrap() = 2usize;
|
LL | x.last_mut().unwrap() = 2;
|
||||||
| --------------------- ^
|
| --------------------- ^
|
||||||
| |
|
| |
|
||||||
| cannot assign to this expression
|
| cannot assign to this expression
|
||||||
|
|
|
|
||||||
help: consider dereferencing here to assign to the mutable borrowed piece of memory
|
help: consider dereferencing here to assign to the mutable borrowed piece of memory
|
||||||
|
|
|
|
||||||
LL | *x.last_mut().unwrap() = 2usize;
|
LL | *x.last_mut().unwrap() = 2;
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut usize`
|
||||||
|
--> $DIR/assign-non-lval-mut-ref.rs:7:5
|
||||||
|
|
|
||||||
|
LL | x.last_mut().unwrap() += 1;
|
||||||
|
| ---------------------^^^^^
|
||||||
|
| |
|
||||||
|
| cannot use `+=` on type `&mut usize`
|
||||||
|
|
|
||||||
|
help: `+=` can be used on `usize`, you can dereference `x.last_mut().unwrap()`
|
||||||
|
|
|
||||||
|
LL | *x.last_mut().unwrap() += 1;
|
||||||
|
| +
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0070`.
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0070, E0368.
|
||||||
|
For more information about an error, try `rustc --explain E0070`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user