From db3a5c58739137036f85cee036c1b63af2517093 Mon Sep 17 00:00:00 2001 From: Kalle Wachsmuth Date: Sun, 24 Mar 2024 14:05:07 +0100 Subject: [PATCH 1/3] move test --- src/tools/tidy/src/issues.txt | 1 - src/tools/tidy/src/ui_tests.rs | 2 +- .../issue-21596.rs => methods/suggest-convert-ptr-to-ref.rs} | 0 .../suggest-convert-ptr-to-ref.stderr} | 0 4 files changed, 1 insertion(+), 2 deletions(-) rename tests/ui/{issues/issue-21596.rs => methods/suggest-convert-ptr-to-ref.rs} (100%) rename tests/ui/{issues/issue-21596.stderr => methods/suggest-convert-ptr-to-ref.stderr} (100%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index e14932ad99d85..211dc347b0fdd 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -1791,7 +1791,6 @@ ui/issues/issue-2150.rs ui/issues/issue-2151.rs ui/issues/issue-21546.rs ui/issues/issue-21554.rs -ui/issues/issue-21596.rs ui/issues/issue-21600.rs ui/issues/issue-21622.rs ui/issues/issue-21634.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 78de8c0537dcc..7136bc4d8f21a 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -17,7 +17,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: usize = 1722; +const ISSUES_ENTRY_LIMIT: usize = 1720; const ROOT_ENTRY_LIMIT: usize = 859; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ diff --git a/tests/ui/issues/issue-21596.rs b/tests/ui/methods/suggest-convert-ptr-to-ref.rs similarity index 100% rename from tests/ui/issues/issue-21596.rs rename to tests/ui/methods/suggest-convert-ptr-to-ref.rs diff --git a/tests/ui/issues/issue-21596.stderr b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr similarity index 100% rename from tests/ui/issues/issue-21596.stderr rename to tests/ui/methods/suggest-convert-ptr-to-ref.stderr From 277e61854eaad456816730bb0a75d85a3a460d96 Mon Sep 17 00:00:00 2001 From: Kalle Wachsmuth Date: Sun, 24 Mar 2024 14:53:58 +0100 Subject: [PATCH 2/3] introduce `Mutability::ptr_str` --- compiler/rustc_ast_ir/src/lib.rs | 8 ++++++++ compiler/rustc_middle/src/mir/pretty.rs | 7 +------ compiler/rustc_middle/src/ty/print/pretty.rs | 8 +------- compiler/rustc_type_ir/src/ty_kind.rs | 13 ++----------- 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index ff7a155204716..9ff2e32f06b0f 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -51,6 +51,14 @@ impl Mutability { } } + /// Returns `"const"` or `"mut"` depending on the mutability. + pub fn ptr_str(self) -> &'static str { + match self { + Mutability::Not => "const", + Mutability::Mut => "mut", + } + } + /// Returns `""` (empty string) or `"mutably "` depending on the mutability. pub fn mutably_str(self) -> &'static str { match self { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 41df2e3b5875a..15bd5c089652c 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -978,12 +978,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { CopyForDeref(ref place) => write!(fmt, "deref_copy {place:#?}"), AddressOf(mutability, ref place) => { - let kind_str = match mutability { - Mutability::Mut => "mut", - Mutability::Not => "const", - }; - - write!(fmt, "&raw {kind_str} {place:?}") + write!(fmt, "&raw {mut_str} {place:?}", mut_str = mutability.ptr_str()) } Aggregate(ref kind, ref places) => { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 20ebd87c3d4ca..0bd009cd51da1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -671,13 +671,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!("(", print(ty), ") is ", write("{pat:?}")) } ty::RawPtr(ty, mutbl) => { - p!(write( - "*{} ", - match mutbl { - hir::Mutability::Mut => "mut", - hir::Mutability::Not => "const", - } - )); + p!(write("*{} ", mutbl.ptr_str())); p!(print(ty)) } ty::Ref(r, ty, mutbl) => { diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 8813955f2af05..56ae7ad9f741a 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -373,17 +373,8 @@ impl DebugWithInfcx for TyKind { Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)), Pat(t, p) => write!(f, "pattern_type!({:?} is {:?})", &this.wrap(t), &this.wrap(p)), Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), - RawPtr(ty, mutbl) => { - match mutbl { - Mutability::Mut => write!(f, "*mut "), - Mutability::Not => write!(f, "*const "), - }?; - write!(f, "{:?}", &this.wrap(ty)) - } - Ref(r, t, m) => match m { - Mutability::Mut => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)), - Mutability::Not => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)), - }, + RawPtr(ty, mutbl) => write!(f, "*{} {:?}", mutbl.ptr_str(), this.wrap(ty)), + Ref(r, t, m) => write!(f, "&{:?} {}{:?}", this.wrap(r), m.prefix_str(), this.wrap(t)), FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&this.wrap(s)).finish(), FnPtr(s) => write!(f, "{:?}", &this.wrap(s)), Dynamic(p, r, repr) => match repr { From 3a2a3ae0b33f93341dc028de5c6c26efe4b65732 Mon Sep 17 00:00:00 2001 From: Kalle Wachsmuth Date: Sun, 24 Mar 2024 17:42:16 +0100 Subject: [PATCH 3/3] rework ptr-to-ref conversion suggestion for method calls --- .../rustc_hir_typeck/src/method/suggest.rs | 46 +++++++++++--- .../ui/methods/suggest-convert-ptr-to-ref.rs | 16 ++++- .../methods/suggest-convert-ptr-to-ref.stderr | 63 +++++++++++++++++-- 3 files changed, 110 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index a199f57aad99f..754866c85c4a0 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -529,16 +529,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - if let ty::RawPtr(_, _) = &rcvr_ty.kind() { - err.note( - "try using `<*const T>::as_ref()` to get a reference to the \ - type behind the pointer: https://doc.rust-lang.org/std/\ - primitive.pointer.html#method.as_ref", - ); - err.note( - "using `<*const T>::as_ref()` on a pointer which is unaligned or points \ - to invalid or uninitialized memory is undefined behavior", + + // on pointers, check if the method would exist on a reference + if let SelfSource::MethodCall(rcvr_expr) = source + && let ty::RawPtr(ty, ptr_mutbl) = *rcvr_ty.kind() + && let Ok(pick) = self.lookup_probe_for_diagnostic( + item_name, + Ty::new_ref(tcx, ty::Region::new_error_misc(tcx), ty, ptr_mutbl), + self.tcx.hir().expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)), + ProbeScope::TraitsInScope, + None, + ) + && let ty::Ref(_, _, sugg_mutbl) = *pick.self_ty.kind() + && (sugg_mutbl.is_not() || ptr_mutbl.is_mut()) + { + let (method, method_anchor) = match sugg_mutbl { + Mutability::Not => { + let method_anchor = match ptr_mutbl { + Mutability::Not => "as_ref", + Mutability::Mut => "as_ref-1", + }; + ("as_ref", method_anchor) + } + Mutability::Mut => ("as_mut", "as_mut"), + }; + err.span_note( + tcx.def_span(pick.item.def_id), + format!("the method `{item_name}` exists on the type `{ty}`", ty = pick.self_ty), ); + let mut_str = ptr_mutbl.ptr_str(); + err.note(format!( + "you might want to use the unsafe method `<*{mut_str} T>::{method}` to get \ + an optional reference to the value behind the pointer" + )); + err.note(format!( + "read the documentation for `<*{mut_str} T>::{method}` and ensure you satisfy its \ + safety preconditions before calling it to avoid undefined behavior: \ + https://doc.rust-lang.org/std/primitive.pointer.html#method.{method_anchor}" + )); } let mut ty_span = match rcvr_ty.kind() { diff --git a/tests/ui/methods/suggest-convert-ptr-to-ref.rs b/tests/ui/methods/suggest-convert-ptr-to-ref.rs index 79f6c91d9ac97..ccce3c65470df 100644 --- a/tests/ui/methods/suggest-convert-ptr-to-ref.rs +++ b/tests/ui/methods/suggest-convert-ptr-to-ref.rs @@ -1,5 +1,17 @@ fn main() { - let x = 8u8; + let mut x = 8u8; let z: *const u8 = &x; - println!("{}", z.to_string()); //~ ERROR E0599 + // issue #21596 + println!("{}", z.to_string()); //~ ERROR E0599 + + let t: *mut u8 = &mut x; + println!("{}", t.to_string()); //~ ERROR E0599 + t.make_ascii_lowercase(); //~ ERROR E0599 + + // suggest `as_mut` simply because the name is similar + let _ = t.as_mut_ref(); //~ ERROR E0599 + let _ = t.as_ref_mut(); //~ ERROR E0599 + + // no ptr-to-ref suggestion + z.make_ascii_lowercase(); //~ ERROR E0599 } diff --git a/tests/ui/methods/suggest-convert-ptr-to-ref.stderr b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr index 8a7fca5f43647..69b20d57be829 100644 --- a/tests/ui/methods/suggest-convert-ptr-to-ref.stderr +++ b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr @@ -1,15 +1,70 @@ error[E0599]: `*const u8` doesn't implement `std::fmt::Display` - --> $DIR/issue-21596.rs:4:22 + --> $DIR/suggest-convert-ptr-to-ref.rs:5:22 | LL | println!("{}", z.to_string()); | ^^^^^^^^^ `*const u8` cannot be formatted with the default formatter | - = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref - = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior +note: the method `to_string` exists on the type `&u8` + --> $SRC_DIR/alloc/src/string.rs:LL:COL + = note: you might want to use the unsafe method `<*const T>::as_ref` to get an optional reference to the value behind the pointer + = note: read the documentation for `<*const T>::as_ref` and ensure you satisfy its safety preconditions before calling it to avoid undefined behavior: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref = note: the following trait bounds were not satisfied: `*const u8: std::fmt::Display` which is required by `*const u8: ToString` -error: aborting due to 1 previous error +error[E0599]: `*mut u8` doesn't implement `std::fmt::Display` + --> $DIR/suggest-convert-ptr-to-ref.rs:8:22 + | +LL | println!("{}", t.to_string()); + | ^^^^^^^^^ `*mut u8` cannot be formatted with the default formatter + | +note: the method `to_string` exists on the type `&&mut u8` + --> $SRC_DIR/alloc/src/string.rs:LL:COL + = note: you might want to use the unsafe method `<*mut T>::as_ref` to get an optional reference to the value behind the pointer + = note: read the documentation for `<*mut T>::as_ref` and ensure you satisfy its safety preconditions before calling it to avoid undefined behavior: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref-1 + = note: the following trait bounds were not satisfied: + `*mut u8: std::fmt::Display` + which is required by `*mut u8: ToString` + +error[E0599]: no method named `make_ascii_lowercase` found for raw pointer `*mut u8` in the current scope + --> $DIR/suggest-convert-ptr-to-ref.rs:9:7 + | +LL | t.make_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^ method not found in `*mut u8` + | +note: the method `make_ascii_lowercase` exists on the type `&mut u8` + --> $SRC_DIR/core/src/num/mod.rs:LL:COL + = note: you might want to use the unsafe method `<*mut T>::as_mut` to get an optional reference to the value behind the pointer + = note: read the documentation for `<*mut T>::as_mut` and ensure you satisfy its safety preconditions before calling it to avoid undefined behavior: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_mut + +error[E0599]: no method named `as_mut_ref` found for raw pointer `*mut u8` in the current scope + --> $DIR/suggest-convert-ptr-to-ref.rs:12:15 + | +LL | let _ = t.as_mut_ref(); + | ^^^^^^^^^^ + | +help: there is a method `as_mut` with a similar name + | +LL | let _ = t.as_mut(); + | ~~~~~~ + +error[E0599]: no method named `as_ref_mut` found for raw pointer `*mut u8` in the current scope + --> $DIR/suggest-convert-ptr-to-ref.rs:13:15 + | +LL | let _ = t.as_ref_mut(); + | ^^^^^^^^^^ + | +help: there is a method `as_mut` with a similar name + | +LL | let _ = t.as_mut(); + | ~~~~~~ + +error[E0599]: no method named `make_ascii_lowercase` found for raw pointer `*const u8` in the current scope + --> $DIR/suggest-convert-ptr-to-ref.rs:16:7 + | +LL | z.make_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^ method not found in `*const u8` + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0599`.