about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-09-04 18:55:45 +0200
committerGitHub <noreply@github.com>2022-09-04 18:55:45 +0200
commitdd35e2f79bd19f331ca8a0644400af99e5a598ae (patch)
treea257d3ccb7bc15afb23778039df7ed89c0a78813
parent8f8a36d1c2795dcdab29d12a73cc49fd252ecc34 (diff)
parent98f4b20abc9ad5ff77874119bbec305f4c7c6226 (diff)
downloadrust-dd35e2f79bd19f331ca8a0644400af99e5a598ae.tar.gz
rust-dd35e2f79bd19f331ca8a0644400af99e5a598ae.zip
Rollup merge of #101388 - compiler-errors:issue-101376, r=fee1-dead
Don't delay invalid LHS bug unless it will be covered by an error in `check_overloaded_binop`

Fixes #101376
-rw-r--r--compiler/rustc_typeck/src/check/op.rs25
-rw-r--r--src/test/ui/typeck/assign-non-lval-needs-deref.rs19
-rw-r--r--src/test/ui/typeck/assign-non-lval-needs-deref.stderr16
3 files changed, 57 insertions, 3 deletions
diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs
index 952086e898f..0d9dbb5bc11 100644
--- a/compiler/rustc_typeck/src/check/op.rs
+++ b/compiler/rustc_typeck/src/check/op.rs
@@ -57,9 +57,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     )
                     .is_ok()
                 {
-                    // Suppress this error, since we already emitted
-                    // a deref suggestion in check_overloaded_binop
-                    err.downgrade_to_delayed_bug();
+                    // If LHS += RHS is an error, but *LHS += RHS is successful, then we will have
+                    // emitted a better suggestion during error handling in check_overloaded_binop.
+                    if self
+                        .lookup_op_method(
+                            lhs_ty,
+                            Some(rhs_ty),
+                            Some(rhs),
+                            Op::Binary(op, IsAssign::Yes),
+                            expected,
+                        )
+                        .is_err()
+                    {
+                        err.downgrade_to_delayed_bug();
+                    } else {
+                        // Otherwise, it's valid to suggest dereferencing the LHS here.
+                        err.span_suggestion_verbose(
+                            lhs.span.shrink_to_lo(),
+                            "consider dereferencing the left-hand side of this operation",
+                            "*",
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
                 }
             }
         });
diff --git a/src/test/ui/typeck/assign-non-lval-needs-deref.rs b/src/test/ui/typeck/assign-non-lval-needs-deref.rs
new file mode 100644
index 00000000000..c979d76b4f4
--- /dev/null
+++ b/src/test/ui/typeck/assign-non-lval-needs-deref.rs
@@ -0,0 +1,19 @@
+// issue #101376
+
+use std::ops::AddAssign;
+struct Foo;
+
+impl AddAssign<()> for Foo {
+    fn add_assign(&mut self, _: ()) {}
+}
+
+impl AddAssign<()> for &mut Foo {
+    fn add_assign(&mut self, _: ()) {}
+}
+
+fn main() {
+    (&mut Foo) += ();
+    //~^ ERROR invalid left-hand side of assignment
+    //~| NOTE cannot assign to this expression
+    //~| HELP consider dereferencing the left-hand side of this operation
+}
diff --git a/src/test/ui/typeck/assign-non-lval-needs-deref.stderr b/src/test/ui/typeck/assign-non-lval-needs-deref.stderr
new file mode 100644
index 00000000000..ee83b145321
--- /dev/null
+++ b/src/test/ui/typeck/assign-non-lval-needs-deref.stderr
@@ -0,0 +1,16 @@
+error[E0067]: invalid left-hand side of assignment
+  --> $DIR/assign-non-lval-needs-deref.rs:15:16
+   |
+LL |     (&mut Foo) += ();
+   |     ---------- ^^
+   |     |
+   |     cannot assign to this expression
+   |
+help: consider dereferencing the left-hand side of this operation
+   |
+LL |     *(&mut Foo) += ();
+   |     +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0067`.