Skip to content

Commit

Permalink
Rollup merge of #96112 - niluxv:strict-provenance-lint-improvements, …
Browse files Browse the repository at this point in the history
…r=nagisa

Strict provenance lint diagnostics improvements

Use `multipart_suggestion` instead of `span_suggestion` and getting a snippet for the expression. Also don't suggest unnecessary parenthesis in `lossy_provenance_casts`.
cc ``@estebank``
``@rustbot`` label A-diagnostics
  • Loading branch information
Dylan-DPC authored Apr 16, 2022
2 parents ff91155 + 1d63d6d commit 99437b3
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 24 deletions.
49 changes: 29 additions & 20 deletions compiler/rustc_typeck/src/check/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -993,20 +993,33 @@ impl<'a, 'tcx> CastCheck<'tcx> {
));

let msg = "use `.addr()` to obtain the address of a pointer";
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
let scalar_cast = match t_c {
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
_ => format!(" as {}", self.cast_ty),
};

let expr_prec = self.expr.precedence().order();
let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX;

let scalar_cast = match t_c {
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
_ => format!(" as {}", self.cast_ty),
};

let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);

if needs_parens {
let suggestions = vec![
(self.expr_span.shrink_to_lo(), String::from("(")),
(cast_span, format!(").addr(){scalar_cast}")),
];

err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
} else {
err.span_suggestion(
self.span,
cast_span,
msg,
format!("({snippet}).addr(){scalar_cast}"),
Applicability::MaybeIncorrect
format!(".addr(){scalar_cast}"),
Applicability::MaybeIncorrect,
);
} else {
err.help(msg);
}

err.help(
"if you can't comply with strict provenance and need to expose the pointer \
provenance you can use `.expose_addr()` instead"
Expand All @@ -1028,16 +1041,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
self.expr_ty, self.cast_ty
));
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
err.span_suggestion(
self.span,
msg,
format!("(...).with_addr({snippet})"),
Applicability::HasPlaceholders,
);
} else {
err.help(msg);
}
let suggestions = vec![
(self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")),
(self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")),
];

err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
err.help(
"if you can't comply with strict provenance and don't have a pointer with \
the correct provenance you can use `std::ptr::from_exposed_addr()` instead"
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LL | #![deny(fuzzy_provenance_casts)]
help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address
|
LL | let dangling = (...).with_addr(16_usize);
| ~~~~~~~~~~~~~~~~~~~~~~~~~
| ++++++++++++++++ ~

error: aborting due to previous error

7 changes: 7 additions & 0 deletions src/test/ui/lint/lint-strict-provenance-lossy-casts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,11 @@ fn main() {

let addr_32bit = &x as *const u8 as u32;
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`

// don't add unnecessary parens in the suggestion
let ptr = &x as *const u8;
let ptr_addr = ptr as usize;
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
let ptr_addr_32bit = ptr as u32;
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
}
34 changes: 31 additions & 3 deletions src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,50 @@ error: under strict provenance it is considered bad style to cast pointer `*cons
--> $DIR/lint-strict-provenance-lossy-casts.rs:6:23
|
LL | let addr: usize = &x as *const u8 as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr()`
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-strict-provenance-lossy-casts.rs:2:9
|
LL | #![deny(lossy_provenance_casts)]
| ^^^^^^^^^^^^^^^^^^^^^^
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
help: use `.addr()` to obtain the address of a pointer
|
LL | let addr: usize = (&x as *const u8).addr();
| + ~~~~~~~~

error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
--> $DIR/lint-strict-provenance-lossy-casts.rs:9:22
|
LL | let addr_32bit = &x as *const u8 as u32;
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr() as u32`
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
help: use `.addr()` to obtain the address of a pointer
|
LL | let addr_32bit = (&x as *const u8).addr() as u32;
| + ~~~~~~~~~~~~~~~

error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
--> $DIR/lint-strict-provenance-lossy-casts.rs:14:20
|
LL | let ptr_addr = ptr as usize;
| ^^^---------
| |
| help: use `.addr()` to obtain the address of a pointer: `.addr()`
|
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead

error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
--> $DIR/lint-strict-provenance-lossy-casts.rs:16:26
|
LL | let ptr_addr_32bit = ptr as u32;
| ^^^-------
| |
| help: use `.addr()` to obtain the address of a pointer: `.addr() as u32`
|
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead

error: aborting due to 2 previous errors
error: aborting due to 4 previous errors

0 comments on commit 99437b3

Please sign in to comment.