Add diagnostics and suggestions for raw pointer arithmetic assignments

This commit is contained in:
Kivooeo 2025-04-21 22:14:44 +05:00
parent 299877e280
commit 834e476a0c
4 changed files with 122 additions and 1 deletions

View file

@ -234,7 +234,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// us do better coercions than we would be able to do otherwise,
// particularly for things like `String + &String`.
let rhs_ty_var = self.next_ty_var(rhs_expr.span);
let result = self.lookup_op_method(
(lhs_expr, lhs_ty),
Some((rhs_expr, rhs_ty_var)),
@ -698,6 +697,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
let lhs_name_str = match lhs_expr.kind {
hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => {
path.segments.last().map_or("_".to_string(), |s| s.ident.to_string())
}
_ => self
.tcx
.sess
.source_map()
.span_to_snippet(lhs_expr.span)
.unwrap_or("_".to_string()),
};
if op.span().can_be_used_for_suggestions() {
match op {
Op::AssignOp(Spanned { node: hir::AssignOpKind::AddAssign, .. })
if lhs_ty.is_raw_ptr() && rhs_ty.is_integral() =>
{
err.multipart_suggestion(
"consider using `add` or `wrapping_add` to do pointer arithmetic",
vec![
(lhs_expr.span.shrink_to_lo(), format!("{} = ", lhs_name_str)),
(
lhs_expr.span.between(rhs_expr.span),
".wrapping_add(".to_owned(),
),
(rhs_expr.span.shrink_to_hi(), ")".to_owned()),
],
Applicability::MaybeIncorrect,
);
}
Op::AssignOp(Spanned { node: hir::AssignOpKind::SubAssign, .. }) => {
if lhs_ty.is_raw_ptr() && rhs_ty.is_integral() {
err.multipart_suggestion(
"consider using `sub` or `wrapping_sub` to do pointer arithmetic",
vec![
(lhs_expr.span.shrink_to_lo(), format!("{} = ", lhs_name_str)),
(
lhs_expr.span.between(rhs_expr.span),
".wrapping_sub(".to_owned(),
),
(rhs_expr.span.shrink_to_hi(), ")".to_owned()),
],
Applicability::MaybeIncorrect,
);
}
}
_ => {}
}
}
let reported = err.emit();
Ty::new_error(self.tcx, reported)
}

View file

@ -0,0 +1,20 @@
//@ run-rustfix
#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_assignments)]
fn test_add_assign_raw_pointer() {
let mut arr = [0u8; 10];
let mut _ptr = arr.as_mut_ptr();
_ptr = _ptr.wrapping_add(2); //~ ERROR binary assignment operation `+=` cannot be applied to type `*mut u8` [E0368]
}
fn test_sub_assign_raw_pointer() {
let mut arr = [0u8; 10];
let mut _ptr = arr.as_mut_ptr();
_ptr = _ptr.wrapping_sub(2); //~ ERROR binary assignment operation `-=` cannot be applied to type `*mut u8` [E0368]
}
fn main() {}

View file

@ -0,0 +1,20 @@
//@ run-rustfix
#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_assignments)]
fn test_add_assign_raw_pointer() {
let mut arr = [0u8; 10];
let mut _ptr = arr.as_mut_ptr();
_ptr += 2; //~ ERROR binary assignment operation `+=` cannot be applied to type `*mut u8` [E0368]
}
fn test_sub_assign_raw_pointer() {
let mut arr = [0u8; 10];
let mut _ptr = arr.as_mut_ptr();
_ptr -= 2; //~ ERROR binary assignment operation `-=` cannot be applied to type `*mut u8` [E0368]
}
fn main() {}

View file

@ -0,0 +1,31 @@
error[E0368]: binary assignment operation `+=` cannot be applied to type `*mut u8`
--> $DIR/pointer-arith-assign.rs:10:5
|
LL | _ptr += 2;
| ----^^^^^
| |
| cannot use `+=` on type `*mut u8`
|
help: consider using `add` or `wrapping_add` to do pointer arithmetic
|
LL - _ptr += 2;
LL + _ptr = _ptr.wrapping_add(2);
|
error[E0368]: binary assignment operation `-=` cannot be applied to type `*mut u8`
--> $DIR/pointer-arith-assign.rs:17:5
|
LL | _ptr -= 2;
| ----^^^^^
| |
| cannot use `-=` on type `*mut u8`
|
help: consider using `sub` or `wrapping_sub` to do pointer arithmetic
|
LL - _ptr -= 2;
LL + _ptr = _ptr.wrapping_sub(2);
|
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0368`.