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_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/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<I: Interner> DebugWithInfcx<I> for TyKind<I> {
             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 {
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/issues/issue-21596.rs
deleted file mode 100644
index 79f6c91d9ac97..0000000000000
--- a/tests/ui/issues/issue-21596.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    let x = 8u8;
-    let z: *const u8 = &x;
-    println!("{}", z.to_string());  //~ ERROR E0599
-}
diff --git a/tests/ui/issues/issue-21596.stderr b/tests/ui/issues/issue-21596.stderr
deleted file mode 100644
index 8a7fca5f43647..0000000000000
--- a/tests/ui/issues/issue-21596.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0599]: `*const u8` doesn't implement `std::fmt::Display`
-  --> $DIR/issue-21596.rs:4: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 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
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/methods/suggest-convert-ptr-to-ref.rs b/tests/ui/methods/suggest-convert-ptr-to-ref.rs
new file mode 100644
index 0000000000000..ccce3c65470df
--- /dev/null
+++ b/tests/ui/methods/suggest-convert-ptr-to-ref.rs
@@ -0,0 +1,17 @@
+fn main() {
+    let mut x = 8u8;
+    let z: *const u8 = &x;
+    // 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
new file mode 100644
index 0000000000000..69b20d57be829
--- /dev/null
+++ b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr
@@ -0,0 +1,70 @@
+error[E0599]: `*const u8` doesn't implement `std::fmt::Display`
+  --> $DIR/suggest-convert-ptr-to-ref.rs:5:22
+   |
+LL |     println!("{}", z.to_string());
+   |                      ^^^^^^^^^ `*const u8` cannot be formatted with the default formatter
+   |
+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[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`.