about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFabian Wolff <fabian.wolff@alumni.ethz.ch>2021-11-29 19:31:17 +0100
committerFabian Wolff <fabian.wolff@alumni.ethz.ch>2021-11-29 19:31:17 +0100
commit821b92b102064cdef6787fe1114dae948fbbb62d (patch)
treed1916f13aa08beb3b175447235f92ecc00ebe557
parent5fd3a5c7c175f228afaf5fc6ff00c177b83d8055 (diff)
downloadrust-821b92b102064cdef6787fe1114dae948fbbb62d.tar.gz
rust-821b92b102064cdef6787fe1114dae948fbbb62d.zip
Improve error message for incorrect field accesses through raw pointers
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs32
-rw-r--r--src/test/ui/typeck/issue-91210-ptr-method.fixed15
-rw-r--r--src/test/ui/typeck/issue-91210-ptr-method.rs15
-rw-r--r--src/test/ui/typeck/issue-91210-ptr-method.stderr11
4 files changed, 72 insertions, 1 deletions
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index eb997b014c7..311106474be 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -46,6 +46,7 @@ use rustc_span::hygiene::DesugaringKind;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{BytePos, Pos};
 use rustc_trait_selection::traits::{self, ObligationCauseCode};
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -2063,7 +2064,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some(span),
             );
         } else {
-            err.help("methods are immutable and cannot be assigned to");
+            let mut found = false;
+
+            if let ty::RawPtr(ty_and_mut) = expr_t.kind() {
+                if let ty::Adt(adt_def, _) = ty_and_mut.ty.kind() {
+                    if adt_def.variants.len() == 1
+                        && adt_def
+                            .variants
+                            .iter()
+                            .next()
+                            .unwrap()
+                            .fields
+                            .iter()
+                            .any(|f| f.ident == field)
+                    {
+                        if let Some(dot_loc) = expr_snippet.rfind('.') {
+                            found = true;
+                            err.span_suggestion(
+                                expr.span.with_hi(expr.span.lo() + BytePos::from_usize(dot_loc)),
+                                "to access the field, dereference first",
+                                format!("(*{})", &expr_snippet[0..dot_loc]),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                    }
+                }
+            }
+
+            if !found {
+                err.help("methods are immutable and cannot be assigned to");
+            }
         }
 
         err.emit();
diff --git a/src/test/ui/typeck/issue-91210-ptr-method.fixed b/src/test/ui/typeck/issue-91210-ptr-method.fixed
new file mode 100644
index 00000000000..94200cce73e
--- /dev/null
+++ b/src/test/ui/typeck/issue-91210-ptr-method.fixed
@@ -0,0 +1,15 @@
+// Regression test for issue #91210.
+
+// run-rustfix
+
+#![allow(unused)]
+
+struct Foo { read: i32 }
+
+unsafe fn blah(x: *mut Foo) {
+    (*x).read = 4;
+    //~^ ERROR: attempted to take value of method
+    //~| HELP: to access the field, dereference first
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-91210-ptr-method.rs b/src/test/ui/typeck/issue-91210-ptr-method.rs
new file mode 100644
index 00000000000..ed0ce6effe7
--- /dev/null
+++ b/src/test/ui/typeck/issue-91210-ptr-method.rs
@@ -0,0 +1,15 @@
+// Regression test for issue #91210.
+
+// run-rustfix
+
+#![allow(unused)]
+
+struct Foo { read: i32 }
+
+unsafe fn blah(x: *mut Foo) {
+    x.read = 4;
+    //~^ ERROR: attempted to take value of method
+    //~| HELP: to access the field, dereference first
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-91210-ptr-method.stderr b/src/test/ui/typeck/issue-91210-ptr-method.stderr
new file mode 100644
index 00000000000..503a32373d5
--- /dev/null
+++ b/src/test/ui/typeck/issue-91210-ptr-method.stderr
@@ -0,0 +1,11 @@
+error[E0615]: attempted to take value of method `read` on type `*mut Foo`
+  --> $DIR/issue-91210-ptr-method.rs:10:7
+   |
+LL |     x.read = 4;
+   |     - ^^^^ method, not a field
+   |     |
+   |     help: to access the field, dereference first: `(*x)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0615`.