Skip to content

Commit 5fcf14a

Browse files
committed
Add diagnostics and suggestions for raw pointer arithmetic assignments
1 parent 611b511 commit 5fcf14a

File tree

4 files changed

+124
-1
lines changed

4 files changed

+124
-1
lines changed

compiler/rustc_hir_typeck/src/op.rs

+53-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
234234
// us do better coercions than we would be able to do otherwise,
235235
// particularly for things like `String + &String`.
236236
let rhs_ty_var = self.next_ty_var(rhs_expr.span);
237-
238237
let result = self.lookup_op_method(
239238
(lhs_expr, lhs_ty),
240239
Some((rhs_expr, rhs_ty_var)),
@@ -698,6 +697,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
698697
}
699698
}
700699

700+
// If there any better way to get lhs name variable please tell me :)
701+
// I really wanna know
702+
let lhs_name_str = match lhs_expr.kind {
703+
hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => {
704+
path.segments.last().map_or("_".to_string(), |s| s.ident.to_string())
705+
}
706+
_ => self
707+
.tcx
708+
.sess
709+
.source_map()
710+
.span_to_snippet(lhs_expr.span)
711+
.unwrap_or("_".to_string()),
712+
};
713+
714+
if op.span().can_be_used_for_suggestions() {
715+
match op {
716+
Op::AssignOp(Spanned { node: hir::AssignOpKind::AddAssign, .. })
717+
if lhs_ty.is_raw_ptr() && rhs_ty.is_integral() =>
718+
{
719+
err.multipart_suggestion(
720+
"consider replacing `ptr += offset` with `ptr = ptr.wrapping_add(offset)` or `ptr.add(offset)`",
721+
vec![
722+
(lhs_expr.span.shrink_to_lo(), format!("{} = ", lhs_name_str)),
723+
(
724+
lhs_expr.span.between(rhs_expr.span),
725+
".wrapping_add(".to_owned(),
726+
),
727+
(rhs_expr.span.shrink_to_hi(), ")".to_owned()),
728+
],
729+
Applicability::MaybeIncorrect,
730+
);
731+
}
732+
Op::AssignOp(Spanned { node: hir::AssignOpKind::SubAssign, .. }) => {
733+
if lhs_ty.is_raw_ptr() && rhs_ty.is_integral() {
734+
err.multipart_suggestion(
735+
"consider replacing `ptr -= offset` with `ptr = ptr.wrapping_sub(offset)` or `ptr.sub(offset)`",
736+
vec![
737+
(lhs_expr.span.shrink_to_lo(), format!("{} = ", lhs_name_str)),
738+
(
739+
lhs_expr.span.between(rhs_expr.span),
740+
".wrapping_sub(".to_owned(),
741+
742+
),
743+
(rhs_expr.span.shrink_to_hi(), ")".to_owned()),
744+
],
745+
Applicability::MaybeIncorrect,
746+
);
747+
}
748+
}
749+
_ => {}
750+
}
751+
}
752+
701753
let reported = err.emit();
702754
Ty::new_error(self.tcx, reported)
703755
}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//@ run-rustfix
2+
#![allow(dead_code)]
3+
#![allow(unused_variables)]
4+
#![allow(unused_assignments)]
5+
6+
fn test_add_assign_raw_pointer() {
7+
let mut arr = [0u8; 10];
8+
let mut _ptr = arr.as_mut_ptr();
9+
10+
_ptr = _ptr.wrapping_add(2); //~ ERROR binary assignment operation `+=` cannot be applied to type `*mut u8` [E0368]
11+
}
12+
13+
fn test_sub_assign_raw_pointer() {
14+
let mut arr = [0u8; 10];
15+
let mut _ptr = arr.as_mut_ptr();
16+
17+
_ptr = _ptr.wrapping_sub(2); //~ ERROR binary assignment operation `-=` cannot be applied to type `*mut u8` [E0368]
18+
}
19+
20+
fn main() {}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//@ run-rustfix
2+
#![allow(dead_code)]
3+
#![allow(unused_variables)]
4+
#![allow(unused_assignments)]
5+
6+
fn test_add_assign_raw_pointer() {
7+
let mut arr = [0u8; 10];
8+
let mut _ptr = arr.as_mut_ptr();
9+
10+
_ptr += 2; //~ ERROR binary assignment operation `+=` cannot be applied to type `*mut u8` [E0368]
11+
}
12+
13+
fn test_sub_assign_raw_pointer() {
14+
let mut arr = [0u8; 10];
15+
let mut _ptr = arr.as_mut_ptr();
16+
17+
_ptr -= 2; //~ ERROR binary assignment operation `-=` cannot be applied to type `*mut u8` [E0368]
18+
}
19+
20+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error[E0368]: binary assignment operation `+=` cannot be applied to type `*mut u8`
2+
--> $DIR/pointer-arith-assign.rs:10:5
3+
|
4+
LL | _ptr += 2;
5+
| ----^^^^^
6+
| |
7+
| cannot use `+=` on type `*mut u8`
8+
|
9+
help: consider replacing `ptr += offset` with `ptr = ptr.wrapping_add(offset)` or `ptr.add(offset)`
10+
|
11+
LL - _ptr += 2;
12+
LL + _ptr = _ptr.wrapping_add(2);
13+
|
14+
15+
error[E0368]: binary assignment operation `-=` cannot be applied to type `*mut u8`
16+
--> $DIR/pointer-arith-assign.rs:17:5
17+
|
18+
LL | _ptr -= 2;
19+
| ----^^^^^
20+
| |
21+
| cannot use `-=` on type `*mut u8`
22+
|
23+
help: consider replacing `ptr -= offset` with `ptr = ptr.wrapping_sub(offset)` or `ptr.sub(offset)`
24+
|
25+
LL - _ptr -= 2;
26+
LL + _ptr = _ptr.wrapping_sub(2);
27+
|
28+
29+
error: aborting due to 2 previous errors
30+
31+
For more information about this error, try `rustc --explain E0368`.

0 commit comments

Comments
 (0)