Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework ptr-to-ref conversion suggestion for method calls #123007

Merged
merged 3 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions compiler/rustc_ast_ir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
46 changes: 37 additions & 9 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Copy link
Contributor Author

@kadiwa4 kadiwa4 Mar 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if this is the right lifetime to use.

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() {
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
8 changes: 1 addition & 7 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
13 changes: 2 additions & 11 deletions compiler/rustc_type_ir/src/ty_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 0 additions & 1 deletion src/tools/tidy/src/issues.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/tools/tidy/src/ui_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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] = &[
Expand Down
5 changes: 0 additions & 5 deletions tests/ui/issues/issue-21596.rs

This file was deleted.

15 changes: 0 additions & 15 deletions tests/ui/issues/issue-21596.stderr

This file was deleted.

17 changes: 17 additions & 0 deletions tests/ui/methods/suggest-convert-ptr-to-ref.rs
Original file line number Diff line number Diff line change
@@ -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
}
70 changes: 70 additions & 0 deletions tests/ui/methods/suggest-convert-ptr-to-ref.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Loading