diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index eb997b014c77b..311106474bea0 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 0000000000000..94200cce73ec0 --- /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 0000000000000..ed0ce6effe7d9 --- /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 0000000000000..503a32373d570 --- /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`.