Rollup merge of #140094 - Kivooeo:raw-pointer-assignment-suggestion, r=compiler-errors
Improve diagnostics for pointer arithmetic += and -= (fixes #137391) **Description**: This PR improves the diagnostic message for cases where a binary assignment operation like `ptr += offset` or `ptr -= offset` is attempted on `*mut T`. These operations are not allowed, and the compiler previously suggested calling `.add()` or `.wrapping_add()`, which is misleading if not assigned. This PR updates the diagnostics to suggest assigning the result of `.wrapping_add()` or `.wrapping_sub()` back to the pointer, e.g.: **Examples** For this code ```rust let mut arr = [0u8; 10]; let mut ptr = arr.as_mut_ptr(); ptr += 2; ``` it will say: ```rust 10 | ptr += 2; | ---^^^^^ | | | cannot use `+=` on type `*mut u8` | help: consider replacing `ptr += offset` with `ptr = ptr.wrapping_add(offset)` or `ptr.add(offset)` | 10 - ptr += 2; 10 + ptr = ptr.wrapping_add(2); ``` **Related issue**: #137391 cc `@nabijaczleweli` for context (issue author)
This commit is contained in:
commit
8f42ac0043
4 changed files with 122 additions and 1 deletions
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue