summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/transmute/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/transmute/mod.rs')
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/mod.rs35
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);
}
}
}