about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-12 07:15:19 +0000
committerbors <bors@rust-lang.org>2023-06-12 07:15:19 +0000
commitfd0a3313f7a64cb16533030e49a271db449368c3 (patch)
tree0bef4734e29477f755f2e0e2c266d2736d561bee
parent77dba225c1048e5585b2cdefb7f8588bd2d2741b (diff)
parent63d643da841bedd6b855f617edecc0b13c0cd71e (diff)
downloadrust-fd0a3313f7a64cb16533030e49a271db449368c3.tar.gz
rust-fd0a3313f7a64cb16533030e49a271db449368c3.zip
Auto merge of #112261 - jieyouxu:c-like-ptr-arithmetics-diagnostics, r=WaffleLapkin
Add help for trying to do C-like pointer arithmetics

This PR adds help messages for these cases:

```rust
fn main() {
    let ptr1: *const u32 = std::ptr::null();
    let ptr2: *const u32 = std::ptr::null();
    let a = ptr1 + 5;
    let b = ptr1 - 5;
    let c = ptr2 - ptr1;
    let d = ptr1[5];
}
```

### Current Output

```
error[E0369]: cannot add `{integer}` to `*const u32`
 --> tests/ui/typeck/issue-112252-ptr-arithmetics-help.rs:4:18
  |
4 |     let a = ptr1 + 5; //~ ERROR cannot add
  |             ---- ^ - {integer}
  |             |
  |             *const u32

error[E0369]: cannot subtract `{integer}` from `*const u32`
 --> tests/ui/typeck/issue-112252-ptr-arithmetics-help.rs:5:18
  |
5 |     let b = ptr1 - 5; //~ ERROR cannot subtract
  |             ---- ^ - {integer}
  |             |
  |             *const u32

error[E0369]: cannot subtract `*const u32` from `*const u32`
 --> tests/ui/typeck/issue-112252-ptr-arithmetics-help.rs:6:18
  |
6 |     let c = ptr2 - ptr1; //~ ERROR cannot subtract
  |             ---- ^ ---- *const u32
  |             |
  |             *const u32

error[E0608]: cannot index into a value of type `*const u32`
 --> tests/ui/typeck/issue-112252-ptr-arithmetics-help.rs:7:13
  |
7 |     let d = ptr1[5]; //~ ERROR cannot index
  |             ^^^^^^^

error: aborting due to 4 previous errors
```

### Output After This PR

```
error[E0369]: cannot add `{integer}` to `*const u32`
  --> $DIR/issue-112252-ptr-arithmetics-help.rs:6:20
   |
LL |     let _a = _ptr1 + 5;
   |              ------^--
   |              |       |
   |              |       {integer}
   |              *const u32
   |              help: consider using `wrapping_add` or `add` for pointer + {integer}: `_ptr1.wrapping_add(5)`

error[E0369]: cannot subtract `{integer}` from `*const u32`
  --> $DIR/issue-112252-ptr-arithmetics-help.rs:7:20
   |
LL |     let _b = _ptr1 - 5;
   |              ------^--
   |              |       |
   |              |       {integer}
   |              *const u32
   |              help: consider using `offset` for pointer - {integer}: `unsafe { _ptr1.offset(-5) }`

error[E0369]: cannot subtract `*const u32` from `*const u32`
  --> $DIR/issue-112252-ptr-arithmetics-help.rs:8:20
   |
LL |     let _c = _ptr2 - _ptr1;
   |              ------^------
   |              |       |
   |              |       *const u32
   |              *const u32
   |              help: consider using `offset_from` for pointer - pointer if the pointers point to the same allocation: `_ptr2.offset_from(_ptr1)`

error[E0608]: cannot index into a value of type `*const u32`
  --> $DIR/issue-112252-ptr-arithmetics-help.rs:9:14
   |
LL |     let _d = _ptr1[5];
   |              ^^^^^^^^
   |
help: consider using `wrapping_add` or `add` for indexing into raw pointer
   |
LL |     let _d = _ptr1.wrapping_add(5);
   |              ~~~~~~~~~~~~~~~~~~~~~

error: aborting due to 4 previous errors
```

Closes #112252.
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs15
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs46
-rw-r--r--tests/ui/typeck/issue-112252-ptr-arithmetics-help.fixed10
-rw-r--r--tests/ui/typeck/issue-112252-ptr-arithmetics-help.rs10
-rw-r--r--tests/ui/typeck/issue-112252-ptr-arithmetics-help.stderr54
5 files changed, 135 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index f03c7ca44ba..3f6847be91b 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2871,6 +2871,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             );
                         }
                     }
+
+                    if base_t.is_unsafe_ptr() && idx_t.is_integral() {
+                        err.multipart_suggestion(
+                            "consider using `wrapping_add` or `add` for indexing into raw pointer",
+                            vec![
+                                (base.span.between(idx.span), ".wrapping_add(".to_owned()),
+                                (
+                                    idx.span.shrink_to_hi().until(expr.span.shrink_to_hi()),
+                                    ")".to_owned(),
+                                ),
+                            ],
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+
                     let reported = err.emit();
                     self.tcx.ty_error(reported)
                 }
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index b8bf2b69120..4f3d1d45679 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -521,6 +521,52 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                 }
+
+                // Suggest using `add`, `offset` or `offset_from` for pointer - {integer},
+                // pointer + {integer} or pointer - pointer.
+                if op.span.can_be_used_for_suggestions() {
+                    match op.node {
+                        hir::BinOpKind::Add if lhs_ty.is_unsafe_ptr() && rhs_ty.is_integral() => {
+                            err.multipart_suggestion(
+                                "consider using `wrapping_add` or `add` for pointer + {integer}",
+                                vec![
+                                    (
+                                        lhs_expr.span.between(rhs_expr.span),
+                                        ".wrapping_add(".to_owned(),
+                                    ),
+                                    (rhs_expr.span.shrink_to_hi(), ")".to_owned()),
+                                ],
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                        hir::BinOpKind::Sub => {
+                            if lhs_ty.is_unsafe_ptr() && rhs_ty.is_integral() {
+                                err.multipart_suggestion(
+                                    "consider using `wrapping_sub` or `sub` for pointer - {integer}",
+                                    vec![
+                                        (lhs_expr.span.between(rhs_expr.span), ".wrapping_sub(".to_owned()),
+                                        (rhs_expr.span.shrink_to_hi(), ")".to_owned()),
+                                    ],
+                                    Applicability::MaybeIncorrect
+                                );
+                            }
+
+                            if lhs_ty.is_unsafe_ptr() && rhs_ty.is_unsafe_ptr() {
+                                err.multipart_suggestion(
+                                    "consider using `offset_from` for pointer - pointer if the pointers point to the same allocation",
+                                    vec![
+                                        (lhs_expr.span.shrink_to_lo(), "unsafe { ".to_owned()),
+                                        (lhs_expr.span.between(rhs_expr.span), ".offset_from(".to_owned()),
+                                        (rhs_expr.span.shrink_to_hi(), ") }".to_owned()),
+                                    ],
+                                    Applicability::MaybeIncorrect
+                                );
+                            }
+                        }
+                        _ => {}
+                    }
+                }
+
                 let reported = err.emit();
                 self.tcx.ty_error(reported)
             }
diff --git a/tests/ui/typeck/issue-112252-ptr-arithmetics-help.fixed b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.fixed
new file mode 100644
index 00000000000..bdb884f5431
--- /dev/null
+++ b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+
+fn main() {
+    let _ptr1: *const u32 = std::ptr::null();
+    let _ptr2: *const u32 = std::ptr::null();
+    let _a = _ptr1.wrapping_add(5); //~ ERROR cannot add
+    let _b = _ptr1.wrapping_sub(5); //~ ERROR cannot subtract
+    let _c = unsafe { _ptr2.offset_from(_ptr1) }; //~ ERROR cannot subtract
+    let _d = _ptr1.wrapping_add(5); //~ ERROR cannot index
+}
diff --git a/tests/ui/typeck/issue-112252-ptr-arithmetics-help.rs b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.rs
new file mode 100644
index 00000000000..cf68850cc4d
--- /dev/null
+++ b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.rs
@@ -0,0 +1,10 @@
+// run-rustfix
+
+fn main() {
+    let _ptr1: *const u32 = std::ptr::null();
+    let _ptr2: *const u32 = std::ptr::null();
+    let _a = _ptr1 + 5; //~ ERROR cannot add
+    let _b = _ptr1 - 5; //~ ERROR cannot subtract
+    let _c = _ptr2 - _ptr1; //~ ERROR cannot subtract
+    let _d = _ptr1[5]; //~ ERROR cannot index
+}
diff --git a/tests/ui/typeck/issue-112252-ptr-arithmetics-help.stderr b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.stderr
new file mode 100644
index 00000000000..c55930da225
--- /dev/null
+++ b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.stderr
@@ -0,0 +1,54 @@
+error[E0369]: cannot add `{integer}` to `*const u32`
+  --> $DIR/issue-112252-ptr-arithmetics-help.rs:6:20
+   |
+LL |     let _a = _ptr1 + 5;
+   |              ----- ^ - {integer}
+   |              |
+   |              *const u32
+   |
+help: consider using `wrapping_add` or `add` for pointer + {integer}
+   |
+LL |     let _a = _ptr1.wrapping_add(5);
+   |                   ~~~~~~~~~~~~~~ +
+
+error[E0369]: cannot subtract `{integer}` from `*const u32`
+  --> $DIR/issue-112252-ptr-arithmetics-help.rs:7:20
+   |
+LL |     let _b = _ptr1 - 5;
+   |              ----- ^ - {integer}
+   |              |
+   |              *const u32
+   |
+help: consider using `wrapping_sub` or `sub` for pointer - {integer}
+   |
+LL |     let _b = _ptr1.wrapping_sub(5);
+   |                   ~~~~~~~~~~~~~~ +
+
+error[E0369]: cannot subtract `*const u32` from `*const u32`
+  --> $DIR/issue-112252-ptr-arithmetics-help.rs:8:20
+   |
+LL |     let _c = _ptr2 - _ptr1;
+   |              ----- ^ ----- *const u32
+   |              |
+   |              *const u32
+   |
+help: consider using `offset_from` for pointer - pointer if the pointers point to the same allocation
+   |
+LL |     let _c = unsafe { _ptr2.offset_from(_ptr1) };
+   |              ++++++++      ~~~~~~~~~~~~~     +++
+
+error[E0608]: cannot index into a value of type `*const u32`
+  --> $DIR/issue-112252-ptr-arithmetics-help.rs:9:14
+   |
+LL |     let _d = _ptr1[5];
+   |              ^^^^^^^^
+   |
+help: consider using `wrapping_add` or `add` for indexing into raw pointer
+   |
+LL |     let _d = _ptr1.wrapping_add(5);
+   |                   ~~~~~~~~~~~~~~ ~
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0369, E0608.
+For more information about an error, try `rustc --explain E0369`.