Skip to content

Commit 18f4f3d

Browse files
committed
rework ptr-to-ref conversion suggestion for method calls
1 parent 18cda45 commit 18f4f3d

File tree

3 files changed

+103
-15
lines changed

3 files changed

+103
-15
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+33-9
Original file line numberDiff line numberDiff line change
@@ -529,16 +529,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
529529
Applicability::MachineApplicable,
530530
);
531531
}
532-
if let ty::RawPtr(_, _) = &rcvr_ty.kind() {
533-
err.note(
534-
"try using `<*const T>::as_ref()` to get a reference to the \
535-
type behind the pointer: https://doc.rust-lang.org/std/\
536-
primitive.pointer.html#method.as_ref",
537-
);
538-
err.note(
539-
"using `<*const T>::as_ref()` on a pointer which is unaligned or points \
540-
to invalid or uninitialized memory is undefined behavior",
532+
533+
// on pointers, check if the method would exist on a reference
534+
if let SelfSource::MethodCall(rcvr_expr) = source
535+
&& let ty::RawPtr(ty, ptr_mutbl) = *rcvr_ty.kind()
536+
&& let Ok(pick) = self.lookup_probe_for_diagnostic(
537+
item_name,
538+
Ty::new_ref(tcx, ty::Region::new_error_misc(tcx), ty, ptr_mutbl),
539+
self.tcx.hir().expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)),
540+
ProbeScope::TraitsInScope,
541+
None,
542+
)
543+
&& let ty::Ref(_, _, sugg_mutbl) = *pick.self_ty.kind()
544+
&& (sugg_mutbl.is_not() || ptr_mutbl.is_mut())
545+
{
546+
let (method, method_anchor) = match sugg_mutbl {
547+
Mutability::Not => {
548+
let method_anchor = match ptr_mutbl {
549+
Mutability::Not => "as_ref",
550+
Mutability::Mut => "as_ref-1",
551+
};
552+
("as_ref", method_anchor)
553+
}
554+
Mutability::Mut => ("as_mut", "as_mut"),
555+
};
556+
err.span_note(
557+
tcx.def_span(pick.item.def_id),
558+
format!("the method `{item_name}` exists on the type `{ty}`", ty = pick.self_ty),
541559
);
560+
err.note(format!(
561+
"try using the unsafe method `<*{mut_str} T>::{method}` to get \
562+
an optional reference to the value behind the pointer: \
563+
https://doc.rust-lang.org/std/primitive.pointer.html#method.{method_anchor}",
564+
mut_str = ptr_mutbl.ptr_str()
565+
));
542566
}
543567

544568
let mut ty_span = match rcvr_ty.kind() {
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
fn main() {
2-
let x = 8u8;
2+
let mut x = 8u8;
33
let z: *const u8 = &x;
4-
println!("{}", z.to_string()); //~ ERROR E0599
4+
// issue #21596
5+
println!("{}", z.to_string()); //~ ERROR E0599
6+
7+
let t: *mut u8 = &mut x;
8+
println!("{}", t.to_string()); //~ ERROR E0599
9+
t.make_ascii_lowercase(); //~ ERROR E0599
10+
11+
// suggest `as_mut` simply because the name is similar
12+
let _ = t.as_mut_ref(); //~ ERROR E0599
13+
let _ = t.as_ref_mut(); //~ ERROR E0599
14+
15+
// no ptr-to-ref suggestion
16+
z.make_ascii_lowercase(); //~ ERROR E0599
517
}
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,67 @@
11
error[E0599]: `*const u8` doesn't implement `std::fmt::Display`
2-
--> $DIR/issue-21596.rs:4:22
2+
--> $DIR/suggest-convert-ptr-to-ref.rs:5:22
33
|
44
LL | println!("{}", z.to_string());
55
| ^^^^^^^^^ `*const u8` cannot be formatted with the default formatter
66
|
7-
= 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
8-
= note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior
7+
note: the method `to_string` exists on the type `&u8`
8+
--> $SRC_DIR/alloc/src/string.rs:LL:COL
9+
= note: try using the unsafe method `<*const T>::as_ref` to get an optional reference to the value behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref
910
= note: the following trait bounds were not satisfied:
1011
`*const u8: std::fmt::Display`
1112
which is required by `*const u8: ToString`
1213

13-
error: aborting due to 1 previous error
14+
error[E0599]: `*mut u8` doesn't implement `std::fmt::Display`
15+
--> $DIR/suggest-convert-ptr-to-ref.rs:8:22
16+
|
17+
LL | println!("{}", t.to_string());
18+
| ^^^^^^^^^ `*mut u8` cannot be formatted with the default formatter
19+
|
20+
note: the method `to_string` exists on the type `&&mut u8`
21+
--> $SRC_DIR/alloc/src/string.rs:LL:COL
22+
= note: try using the unsafe method `<*mut T>::as_ref` to get an optional reference to the value behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref-1
23+
= note: the following trait bounds were not satisfied:
24+
`*mut u8: std::fmt::Display`
25+
which is required by `*mut u8: ToString`
26+
27+
error[E0599]: no method named `make_ascii_lowercase` found for raw pointer `*mut u8` in the current scope
28+
--> $DIR/suggest-convert-ptr-to-ref.rs:9:7
29+
|
30+
LL | t.make_ascii_lowercase();
31+
| ^^^^^^^^^^^^^^^^^^^^ method not found in `*mut u8`
32+
|
33+
note: the method `make_ascii_lowercase` exists on the type `&mut u8`
34+
--> $SRC_DIR/core/src/num/mod.rs:LL:COL
35+
= note: try using the unsafe method `<*mut T>::as_mut` to get an optional reference to the value behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_mut
36+
37+
error[E0599]: no method named `as_mut_ref` found for raw pointer `*mut u8` in the current scope
38+
--> $DIR/suggest-convert-ptr-to-ref.rs:12:15
39+
|
40+
LL | let _ = t.as_mut_ref();
41+
| ^^^^^^^^^^
42+
|
43+
help: there is a method `as_mut` with a similar name
44+
|
45+
LL | let _ = t.as_mut();
46+
| ~~~~~~
47+
48+
error[E0599]: no method named `as_ref_mut` found for raw pointer `*mut u8` in the current scope
49+
--> $DIR/suggest-convert-ptr-to-ref.rs:13:15
50+
|
51+
LL | let _ = t.as_ref_mut();
52+
| ^^^^^^^^^^
53+
|
54+
help: there is a method `as_mut` with a similar name
55+
|
56+
LL | let _ = t.as_mut();
57+
| ~~~~~~
58+
59+
error[E0599]: no method named `make_ascii_lowercase` found for raw pointer `*const u8` in the current scope
60+
--> $DIR/suggest-convert-ptr-to-ref.rs:16:7
61+
|
62+
LL | z.make_ascii_lowercase();
63+
| ^^^^^^^^^^^^^^^^^^^^ method not found in `*const u8`
64+
65+
error: aborting due to 6 previous errors
1466

1567
For more information about this error, try `rustc --explain E0599`.

0 commit comments

Comments
 (0)