From a5e7da0cf6cd7b03ad9d1079aab978b52007b221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 4 Jul 2024 00:24:10 +0000 Subject: [PATCH] Tweak raw-pointer field access and array indexing suggestions --- compiler/rustc_hir_typeck/src/expr.rs | 44 +++++++++++-------- tests/ui/issues/issue-11004.stderr | 20 +++++---- .../parenthesized-deref-suggestion.stderr | 14 +++--- tests/ui/typeck/issue-53712.stderr | 10 +++-- tests/ui/unsafe/unsafe-fn-autoderef.stderr | 10 +++-- 5 files changed, 58 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index f3aece4e1d8..bd5e5294983 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2551,10 +2551,10 @@ fn ban_nonexisting_field( 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"); @@ -2721,7 +2721,6 @@ fn point_at_param_definition(&self, err: &mut Diag<'_>, param: ty::ParamTy) { fn maybe_suggest_array_indexing( &self, err: &mut Diag<'_>, - expr: &hir::Expr<'_>, base: &hir::Expr<'_>, field: Ident, len: ty::Const<'tcx>, @@ -2729,32 +2728,41 @@ fn maybe_suggest_array_indexing( 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::()) - && 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<'_> { diff --git a/tests/ui/issues/issue-11004.stderr b/tests/ui/issues/issue-11004.stderr index ea141e61df8..6d157c91130 100644 --- a/tests/ui/issues/issue-11004.stderr +++ b/tests/ui/issues/issue-11004.stderr @@ -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 diff --git a/tests/ui/suggestions/parenthesized-deref-suggestion.stderr b/tests/ui/suggestions/parenthesized-deref-suggestion.stderr index 9f185f5dd52..29e973b3a17 100644 --- a/tests/ui/suggestions/parenthesized-deref-suggestion.stderr +++ b/tests/ui/suggestions/parenthesized-deref-suggestion.stderr @@ -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 diff --git a/tests/ui/typeck/issue-53712.stderr b/tests/ui/typeck/issue-53712.stderr index ec31766324b..ffaf5cde1d7 100644 --- a/tests/ui/typeck/issue-53712.stderr +++ b/tests/ui/typeck/issue-53712.stderr @@ -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 diff --git a/tests/ui/unsafe/unsafe-fn-autoderef.stderr b/tests/ui/unsafe/unsafe-fn-autoderef.stderr index c3ab8020222..c19028ac866 100644 --- a/tests/ui/unsafe/unsafe-fn-autoderef.stderr +++ b/tests/ui/unsafe/unsafe-fn-autoderef.stderr @@ -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