Skip to content

Commit 7f301cf

Browse files
authored
Rollup merge of rust-lang#96112 - niluxv:strict-provenance-lint-improvements, 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
2 parents 925e461 + 1d63d6d commit 7f301cf

File tree

4 files changed

+68
-24
lines changed

4 files changed

+68
-24
lines changed

compiler/rustc_typeck/src/check/cast.rs

+29-20
Original file line numberDiff line numberDiff line change
@@ -993,20 +993,33 @@ impl<'a, 'tcx> CastCheck<'tcx> {
993993
));
994994

995995
let msg = "use `.addr()` to obtain the address of a pointer";
996-
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
997-
let scalar_cast = match t_c {
998-
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
999-
_ => format!(" as {}", self.cast_ty),
1000-
};
996+
997+
let expr_prec = self.expr.precedence().order();
998+
let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX;
999+
1000+
let scalar_cast = match t_c {
1001+
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
1002+
_ => format!(" as {}", self.cast_ty),
1003+
};
1004+
1005+
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
1006+
1007+
if needs_parens {
1008+
let suggestions = vec![
1009+
(self.expr_span.shrink_to_lo(), String::from("(")),
1010+
(cast_span, format!(").addr(){scalar_cast}")),
1011+
];
1012+
1013+
err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
1014+
} else {
10011015
err.span_suggestion(
1002-
self.span,
1016+
cast_span,
10031017
msg,
1004-
format!("({snippet}).addr(){scalar_cast}"),
1005-
Applicability::MaybeIncorrect
1018+
format!(".addr(){scalar_cast}"),
1019+
Applicability::MaybeIncorrect,
10061020
);
1007-
} else {
1008-
err.help(msg);
10091021
}
1022+
10101023
err.help(
10111024
"if you can't comply with strict provenance and need to expose the pointer \
10121025
provenance you can use `.expose_addr()` instead"
@@ -1028,16 +1041,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
10281041
self.expr_ty, self.cast_ty
10291042
));
10301043
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
1031-
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
1032-
err.span_suggestion(
1033-
self.span,
1034-
msg,
1035-
format!("(...).with_addr({snippet})"),
1036-
Applicability::HasPlaceholders,
1037-
);
1038-
} else {
1039-
err.help(msg);
1040-
}
1044+
let suggestions = vec![
1045+
(self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")),
1046+
(self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")),
1047+
];
1048+
1049+
err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
10411050
err.help(
10421051
"if you can't comply with strict provenance and don't have a pointer with \
10431052
the correct provenance you can use `std::ptr::from_exposed_addr()` instead"

src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | #![deny(fuzzy_provenance_casts)]
1313
help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address
1414
|
1515
LL | let dangling = (...).with_addr(16_usize);
16-
| ~~~~~~~~~~~~~~~~~~~~~~~~~
16+
| ++++++++++++++++ ~
1717

1818
error: aborting due to previous error
1919

src/test/ui/lint/lint-strict-provenance-lossy-casts.rs

+7
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,11 @@ fn main() {
88

99
let addr_32bit = &x as *const u8 as u32;
1010
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
11+
12+
// don't add unnecessary parens in the suggestion
13+
let ptr = &x as *const u8;
14+
let ptr_addr = ptr as usize;
15+
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
16+
let ptr_addr_32bit = ptr as u32;
17+
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
1118
}

src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr

+31-3
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,50 @@ error: under strict provenance it is considered bad style to cast pointer `*cons
22
--> $DIR/lint-strict-provenance-lossy-casts.rs:6:23
33
|
44
LL | let addr: usize = &x as *const u8 as usize;
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr()`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
note: the lint level is defined here
88
--> $DIR/lint-strict-provenance-lossy-casts.rs:2:9
99
|
1010
LL | #![deny(lossy_provenance_casts)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^
1212
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
13+
help: use `.addr()` to obtain the address of a pointer
14+
|
15+
LL | let addr: usize = (&x as *const u8).addr();
16+
| + ~~~~~~~~
1317

1418
error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
1519
--> $DIR/lint-strict-provenance-lossy-casts.rs:9:22
1620
|
1721
LL | let addr_32bit = &x as *const u8 as u32;
18-
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr() as u32`
22+
| ^^^^^^^^^^^^^^^^^^^^^^
23+
|
24+
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
25+
help: use `.addr()` to obtain the address of a pointer
26+
|
27+
LL | let addr_32bit = (&x as *const u8).addr() as u32;
28+
| + ~~~~~~~~~~~~~~~
29+
30+
error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
31+
--> $DIR/lint-strict-provenance-lossy-casts.rs:14:20
32+
|
33+
LL | let ptr_addr = ptr as usize;
34+
| ^^^---------
35+
| |
36+
| help: use `.addr()` to obtain the address of a pointer: `.addr()`
37+
|
38+
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
39+
40+
error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
41+
--> $DIR/lint-strict-provenance-lossy-casts.rs:16:26
42+
|
43+
LL | let ptr_addr_32bit = ptr as u32;
44+
| ^^^-------
45+
| |
46+
| help: use `.addr()` to obtain the address of a pointer: `.addr() as u32`
1947
|
2048
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
2149

22-
error: aborting due to 2 previous errors
50+
error: aborting due to 4 previous errors
2351

0 commit comments

Comments
 (0)