diff options
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/transmute/mod.rs')
-rw-r--r-- | src/tools/clippy/clippy_lints/src/transmute/mod.rs | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 691d759d7..c01cbe509 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -3,6 +3,7 @@ mod transmute_float_to_int; mod transmute_int_to_bool; mod transmute_int_to_char; mod transmute_int_to_float; +mod transmute_int_to_non_zero; mod transmute_null_to_fn; mod transmute_num_to_bytes; mod transmute_ptr_to_ptr; @@ -255,6 +256,31 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does + /// Checks for transmutes from integers to `NonZero*` types, and suggests their `new_unchecked` + /// method instead. + /// + /// ### Why is this bad? + /// Transmutes work on any types and thus might cause unsoundness when those types change + /// elsewhere. `new_unchecked` only works for the appropriate types instead. + /// + /// ### Example + /// ```rust + /// # use core::num::NonZeroU32; + /// let _non_zero: NonZeroU32 = unsafe { std::mem::transmute(123) }; + /// ``` + /// Use instead: + /// ```rust + /// # use core::num::NonZeroU32; + /// let _non_zero = unsafe { NonZeroU32::new_unchecked(123) }; + /// ``` + #[clippy::version = "1.69.0"] + pub TRANSMUTE_INT_TO_NON_ZERO, + complexity, + "transmutes from an integer to a non-zero wrapper" +} + +declare_clippy_lint! { + /// ### What it does /// Checks for transmutes from a float to an integer. /// /// ### Why is this bad? @@ -451,6 +477,7 @@ impl_lint_pass!(Transmute => [ TRANSMUTE_BYTES_TO_STR, TRANSMUTE_INT_TO_BOOL, TRANSMUTE_INT_TO_FLOAT, + TRANSMUTE_INT_TO_NON_ZERO, TRANSMUTE_FLOAT_TO_INT, TRANSMUTE_NUM_TO_BYTES, UNSOUND_COLLECTION_TRANSMUTE, @@ -479,7 +506,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { // - char conversions (https://github.com/rust-lang/rust/issues/89259) let const_context = in_constant(cx, e.hir_id); - let from_ty = cx.typeck_results().expr_ty_adjusted(arg); + let (from_ty, from_ty_adjusted) = match cx.typeck_results().expr_adjustments(arg) { + [] => (cx.typeck_results().expr_ty(arg), false), + [.., a] => (a.target, true), + }; // Adjustments for `to_ty` happen after the call to `transmute`, so don't use them. let to_ty = cx.typeck_results().expr_ty(e); @@ -498,6 +528,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg) | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg) | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context) + | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg) | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context) | ( @@ -506,7 +537,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { ); if !linted { - transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, to_ty, arg); + transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg); } } } |