diff options
| author | niluxv <niluxv.opensource.C-h2ty6xl@yandex.com> | 2022-04-16 10:05:33 +0200 |
|---|---|---|
| committer | niluxv <niluxv.opensource.C-h2ty6xl@yandex.com> | 2022-04-16 10:32:37 +0200 |
| commit | 02d12bc30c173fd0cbf55d67c42d6cbae231203a (patch) | |
| tree | c3433d6a54133e83b84456e8c9fffcfda6c55797 | |
| parent | 080d5452e1bb6e18e12a073d4d0283fd9b6dac0b (diff) | |
| download | rust-02d12bc30c173fd0cbf55d67c42d6cbae231203a.tar.gz rust-02d12bc30c173fd0cbf55d67c42d6cbae231203a.zip | |
Improve `lossy_provenance_casts` lint diagnostics
Use `multipart_suggestion` and don't suggested unnecessary parenthesis.
| -rw-r--r-- | compiler/rustc_typeck/src/check/cast.rs | 33 | ||||
| -rw-r--r-- | src/test/ui/lint/lint-strict-provenance-lossy-casts.rs | 7 | ||||
| -rw-r--r-- | src/test/ui/lint/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 049940d19a6..da054077376 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 3690fbc904d..9799a053756 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 e7a6c1837bd..05178b34b11 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 |
