about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-07-04 00:24:10 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-07-04 06:06:33 +0000
commita5e7da0cf6cd7b03ad9d1079aab978b52007b221 (patch)
tree442274c6adfa9cc7edaf93d103ff9a65645ef794
parent8ea1066fe6605d85969d403080b2c5d93376797e (diff)
downloadrust-a5e7da0cf6cd7b03ad9d1079aab978b52007b221.tar.gz
rust-a5e7da0cf6cd7b03ad9d1079aab978b52007b221.zip
Tweak raw-pointer field access and array indexing suggestions
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs44
-rw-r--r--tests/ui/issues/issue-11004.stderr20
-rw-r--r--tests/ui/suggestions/parenthesized-deref-suggestion.stderr14
-rw-r--r--tests/ui/typeck/issue-53712.stderr10
-rw-r--r--tests/ui/unsafe/unsafe-fn-autoderef.stderr10
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 @@ 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");
@@ -2721,7 +2721,6 @@ 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>,
@@ -2729,32 +2728,41 @@ impl<'a, 'tcx> FnCtxt<'a, '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<'_> {
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