Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6565,6 +6565,7 @@ Released 2018-09-13
[`mut_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_mut
[`mut_mutex_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_mutex_lock
[`mut_range_bound`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_range_bound
[`mutable_adt_argument_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutable_adt_argument_transmute
[`mutable_key_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type
[`mutex_atomic`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_atomic
[`mutex_integer`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_integer
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[
crate::transmute::CROSSPOINTER_TRANSMUTE_INFO,
crate::transmute::EAGER_TRANSMUTE_INFO,
crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS_INFO,
crate::transmute::MUTABLE_ADT_ARGUMENT_TRANSMUTE_INFO,
crate::transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS_INFO,
crate::transmute::TRANSMUTE_BYTES_TO_STR_INFO,
crate::transmute::TRANSMUTE_INT_TO_BOOL_INFO,
Expand Down
19 changes: 19 additions & 0 deletions clippy_lints/src/transmute/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod crosspointer_transmute;
mod eager_transmute;
mod missing_transmute_annotations;
mod transmute_adt_argument;
mod transmute_int_to_bool;
mod transmute_int_to_non_zero;
mod transmute_null_to_fn;
Expand Down Expand Up @@ -44,6 +45,22 @@ declare_clippy_lint! {
correctness,
"transmutes that are confusing at best, undefined behavior at worst and always useless"
}
declare_clippy_lint! {
/// ### What it does
/// Checks for transmutes between the same adt, where at least one of the type argument goes from &T to &mut T.
/// This is an a more complicated version of https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#mutable-transmutes.
/// ### Example
///
/// ```ignore
/// unsafe {
/// std::mem::transmute::<Option<&i32>, Option<&mut i32>>(Some(&5));
/// }
/// ```
#[clippy::version = "1.92.0"]
pub MUTABLE_ADT_ARGUMENT_TRANSMUTE,
correctness,
"transmutes on the same adt where at least one of the type argument goes from &T to &mut T"
}

declare_clippy_lint! {
/// ### What it does
Expand Down Expand Up @@ -475,6 +492,7 @@ impl_lint_pass!(Transmute => [
USELESS_TRANSMUTE,
WRONG_TRANSMUTE,
TRANSMUTE_BYTES_TO_STR,
MUTABLE_ADT_ARGUMENT_TRANSMUTE,
TRANSMUTE_INT_TO_BOOL,
TRANSMUTE_INT_TO_NON_ZERO,
UNSOUND_COLLECTION_TRANSMUTE,
Expand Down Expand Up @@ -516,6 +534,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
}

let linted = wrong_transmute::check(cx, e, from_ty, to_ty)
| transmute_adt_argument::check(cx, e, from_ty, to_ty)
| crosspointer_transmute::check(cx, e, from_ty, to_ty)
| transmuting_null::check(cx, e, arg, to_ty)
| transmute_null_to_fn::check(cx, e, arg, to_ty)
Expand Down
35 changes: 35 additions & 0 deletions clippy_lints/src/transmute/transmute_adt_argument.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use super::MUTABLE_ADT_ARGUMENT_TRANSMUTE;
use clippy_utils::diagnostics::span_lint;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, GenericArgKind, Ty};

pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool {
from_ty
.walk()
.zip(to_ty.walk())
.filter_map(|(from_ty, to_ty)| {
if let (GenericArgKind::Type(from_ty), GenericArgKind::Type(to_ty)) = (from_ty.kind(), to_ty.kind()) {
Some((from_ty, to_ty))
} else {
None
}
})
.filter(|(from_ty_inner, to_ty_inner)| {
if let (ty::Ref(_, _, from_mut), ty::Ref(_, _, to_mut)) = (from_ty_inner.kind(), to_ty_inner.kind())
&& from_mut < to_mut
{
span_lint(
cx,
MUTABLE_ADT_ARGUMENT_TRANSMUTE,
e.span,
format!("transmute of type argument {from_ty_inner} to {from_ty_inner}"),
);
true
} else {
false
}
})
.count()
> 0
}
18 changes: 18 additions & 0 deletions tests/ui/mutable_adt_argument_transmute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#![warn(clippy::mutable_adt_argument_transmute)]

fn main() {
unsafe {
let _: Option<&mut i32> = std::mem::transmute(Some(&5i32));
//~^ mutable_adt_argument_transmute
let _: Result<&mut i32, ()> = std::mem::transmute(Result::<&i32, ()>::Ok(&5i32));
//~^ mutable_adt_argument_transmute
let _: Result<Option<&mut String>, ()> =
std::mem::transmute(Result::<Option<&String>, ()>::Ok(Some(&"foo".to_string())));
//~^ mutable_adt_argument_transmute
let _: Result<&mut f32, &usize> = std::mem::transmute(Result::<&f32, &usize>::Ok(&2f32));
//~^ mutable_adt_argument_transmute
let _: Result<(), &mut usize> = std::mem::transmute(Result::<(), &usize>::Ok(()));
//~^ mutable_adt_argument_transmute
let _: Option<&i32> = std::mem::transmute(Some(&5i32));
}
}
35 changes: 35 additions & 0 deletions tests/ui/mutable_adt_argument_transmute.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
error: transmute of type argument &i32 to &i32
--> tests/ui/mutable_adt_argument_transmute.rs:5:35
|
LL | let _: Option<&mut i32> = std::mem::transmute(Some(&5i32));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::mutable-adt-argument-transmute` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::mutable_adt_argument_transmute)]`

error: transmute of type argument &i32 to &i32
--> tests/ui/mutable_adt_argument_transmute.rs:7:39
|
LL | let _: Result<&mut i32, ()> = std::mem::transmute(Result::<&i32, ()>::Ok(&5i32));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute of type argument &std::string::String to &std::string::String
--> tests/ui/mutable_adt_argument_transmute.rs:10:13
|
LL | std::mem::transmute(Result::<Option<&String>, ()>::Ok(Some(&"foo".to_string())));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute of type argument &f32 to &f32
--> tests/ui/mutable_adt_argument_transmute.rs:12:43
|
LL | let _: Result<&mut f32, &usize> = std::mem::transmute(Result::<&f32, &usize>::Ok(&2f32));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute of type argument &usize to &usize
--> tests/ui/mutable_adt_argument_transmute.rs:14:41
|
LL | let _: Result<(), &mut usize> = std::mem::transmute(Result::<(), &usize>::Ok(()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 5 previous errors