From 02d12bc30c173fd0cbf55d67c42d6cbae231203a Mon Sep 17 00:00:00 2001 From: niluxv Date: Sat, 16 Apr 2022 10:05:33 +0200 Subject: [PATCH 1/2] Improve `lossy_provenance_casts` lint diagnostics Use `multipart_suggestion` and don't suggested unnecessary parenthesis. --- compiler/rustc_typeck/src/check/cast.rs | 33 ++++++++++++------ .../lint-strict-provenance-lossy-casts.rs | 7 ++++ .../lint-strict-provenance-lossy-casts.stderr | 34 +++++++++++++++++-- 3 files changed, 61 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 049940d19a651..da054077376c3 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -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" diff --git a/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs b/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs index 3690fbc904d99..9799a05375682 100644 --- a/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs +++ b/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs @@ -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` } diff --git a/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr index e7a6c1837bd56..05178b34b1146 100644 --- a/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr +++ b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr @@ -2,7 +2,7 @@ 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 @@ -10,14 +10,42 @@ note: the lint level is defined here 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 From 1d63d6db558b1ff6cd02cb471b51957657c2d71f Mon Sep 17 00:00:00 2001 From: niluxv Date: Sat, 16 Apr 2022 10:18:31 +0200 Subject: [PATCH 2/2] Improve `fuzzy_provenance_casts` lint diagnostics Use `multipart_suggestion` instead of getting a snippet. --- compiler/rustc_typeck/src/check/cast.rs | 16 ++++++---------- .../lint-strict-provenance-fuzzy-casts.stderr | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index da054077376c3..a153997599aba 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -1041,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" diff --git a/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr index e50d243b6ad6d..c85934aa3ba15 100644 --- a/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr +++ b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr @@ -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