Skip to content

Commit

Permalink
Tweak raw-pointer field access and array indexing suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Jul 4, 2024
1 parent 8ea1066 commit a5e7da0
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 40 deletions.
44 changes: 26 additions & 18 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2551,10 +2551,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

match *base_ty.peel_refs().kind() {
ty::Array(_, len) => {
self.maybe_suggest_array_indexing(&mut err, expr, base, ident, len);
self.maybe_suggest_array_indexing(&mut err, base, ident, len);
}
ty::RawPtr(..) => {
self.suggest_first_deref_field(&mut err, expr, base, ident);
self.suggest_first_deref_field(&mut err, base, ident);
}
ty::Param(param_ty) => {
err.span_label(ident.span, "unknown field");
Expand Down Expand Up @@ -2721,40 +2721,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn maybe_suggest_array_indexing(
&self,
err: &mut Diag<'_>,
expr: &hir::Expr<'_>,
base: &hir::Expr<'_>,
field: Ident,
len: ty::Const<'tcx>,
) {
err.span_label(field.span, "unknown field");
if let (Some(len), Ok(user_index)) =
(len.try_eval_target_usize(self.tcx, self.param_env), field.as_str().parse::<u64>())
&& let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span)
{
let help = "instead of using tuple indexing, use array indexing";
let suggestion = format!("{base}[{field}]");
let applicability = if len < user_index {
Applicability::MachineApplicable
} else {
Applicability::MaybeIncorrect
};
err.span_suggestion(expr.span, help, suggestion, applicability);
err.multipart_suggestion(
help,
vec![
(base.span.between(field.span), "[".to_string()),
(field.span.shrink_to_hi(), "]".to_string()),
],
applicability,
);
}
}

fn suggest_first_deref_field(
&self,
err: &mut Diag<'_>,
expr: &hir::Expr<'_>,
base: &hir::Expr<'_>,
field: Ident,
) {
fn suggest_first_deref_field(&self, err: &mut Diag<'_>, base: &hir::Expr<'_>, field: Ident) {
err.span_label(field.span, "unknown field");
if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) {
let msg = format!("`{base}` is a raw pointer; try dereferencing it");
let suggestion = format!("(*{base}).{field}");
err.span_suggestion(expr.span, msg, suggestion, Applicability::MaybeIncorrect);
}
let val = if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span)
&& base.len() < 20
{
format!("`{base}`")
} else {
"the value".to_string()
};
err.multipart_suggestion(
format!("{val} is a raw pointer; try dereferencing it"),
vec![
(base.span.shrink_to_lo(), "(*".to_string()),
(base.span.shrink_to_hi(), ")".to_string()),
],
Applicability::MaybeIncorrect,
);
}

fn no_such_field_err(&self, field: Ident, expr_t: Ty<'tcx>, id: HirId) -> Diag<'_> {
Expand Down
20 changes: 12 additions & 8 deletions tests/ui/issues/issue-11004.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@ error[E0609]: no field `x` on type `*mut A`
--> $DIR/issue-11004.rs:7:21
|
LL | let x : i32 = n.x;
| --^
| | |
| | unknown field
| help: `n` is a raw pointer; try dereferencing it: `(*n).x`
| ^ unknown field
|
help: `n` is a raw pointer; try dereferencing it
|
LL | let x : i32 = (*n).x;
| ++ +

error[E0609]: no field `y` on type `*mut A`
--> $DIR/issue-11004.rs:8:21
|
LL | let y : f64 = n.y;
| --^
| | |
| | unknown field
| help: `n` is a raw pointer; try dereferencing it: `(*n).y`
| ^ unknown field
|
help: `n` is a raw pointer; try dereferencing it
|
LL | let y : f64 = (*n).y;
| ++ +

error: aborting due to 2 previous errors

Expand Down
14 changes: 8 additions & 6 deletions tests/ui/suggestions/parenthesized-deref-suggestion.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ error[E0609]: no field `opts` on type `*const Session`
LL | (sess as *const Session).opts;
| ^^^^ unknown field
|
help: `(sess as *const Session)` is a raw pointer; try dereferencing it
help: the value is a raw pointer; try dereferencing it
|
LL | (*(sess as *const Session)).opts;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| ++ +

error[E0609]: no field `0` on type `[u32; 1]`
--> $DIR/parenthesized-deref-suggestion.rs:10:21
|
LL | (x as [u32; 1]).0;
| ----------------^
| | |
| | unknown field
| help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]`
| ^ unknown field
|
help: instead of using tuple indexing, use array indexing
|
LL | (x as [u32; 1])[0];
| ~ +

error: aborting due to 2 previous errors

Expand Down
10 changes: 6 additions & 4 deletions tests/ui/typeck/issue-53712.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ error[E0609]: no field `0` on type `[{integer}; 5]`
--> $DIR/issue-53712.rs:5:9
|
LL | arr.0;
| ----^
| | |
| | unknown field
| help: instead of using tuple indexing, use array indexing: `arr[0]`
| ^ unknown field
|
help: instead of using tuple indexing, use array indexing
|
LL | arr[0];
| ~ +

error: aborting due to 1 previous error

Expand Down
10 changes: 6 additions & 4 deletions tests/ui/unsafe/unsafe-fn-autoderef.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ error[E0609]: no field `f` on type `*const Rec`
--> $DIR/unsafe-fn-autoderef.rs:19:14
|
LL | return p.f;
| --^
| | |
| | unknown field
| help: `p` is a raw pointer; try dereferencing it: `(*p).f`
| ^ unknown field
|
help: `p` is a raw pointer; try dereferencing it
|
LL | return (*p).f;
| ++ +

error: aborting due to 1 previous error

Expand Down

0 comments on commit a5e7da0

Please sign in to comment.