Skip to content

Commit f12f61a

Browse files
committed
add lint for transmute from &T to &mut T of a ADT arguement
1 parent 5e7ce90 commit f12f61a

File tree

5 files changed

+61
-0
lines changed

5 files changed

+61
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6565,6 +6565,7 @@ Released 2018-09-13
65656565
[`mut_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_mut
65666566
[`mut_mutex_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_mutex_lock
65676567
[`mut_range_bound`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_range_bound
6568+
[`mutable_adt_argument_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutable_adt_argument_transmute
65686569
[`mutable_key_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type
65696570
[`mutex_atomic`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_atomic
65706571
[`mutex_integer`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_integer

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[
715715
crate::transmute::CROSSPOINTER_TRANSMUTE_INFO,
716716
crate::transmute::EAGER_TRANSMUTE_INFO,
717717
crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS_INFO,
718+
crate::transmute::MUTABLE_ADT_ARGUMENT_TRANSMUTE_INFO,
718719
crate::transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS_INFO,
719720
crate::transmute::TRANSMUTE_BYTES_TO_STR_INFO,
720721
crate::transmute::TRANSMUTE_INT_TO_BOOL_INFO,

clippy_lints/src/transmute/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod crosspointer_transmute;
22
mod eager_transmute;
33
mod missing_transmute_annotations;
4+
mod transmute_adt_argument;
45
mod transmute_int_to_bool;
56
mod transmute_int_to_non_zero;
67
mod transmute_null_to_fn;
@@ -44,6 +45,22 @@ declare_clippy_lint! {
4445
correctness,
4546
"transmutes that are confusing at best, undefined behavior at worst and always useless"
4647
}
48+
declare_clippy_lint! {
49+
/// ### What it does
50+
/// Checks for transmutes between the same adt, where at least one of the type argument goes from &T to &mut T.
51+
/// This is an a more complicated version of https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#mutable-transmutes.
52+
/// ### Example
53+
///
54+
/// ```ignore
55+
/// unsafe {
56+
/// std::mem::transmute::<Option<&i32>, Option<&mut i32>>(&Some(5));
57+
/// }
58+
/// ```
59+
#[clippy::version = "1.92.0"]
60+
pub MUTABLE_ADT_ARGUMENT_TRANSMUTE,
61+
correctness,
62+
"transmutes on the same adt where at least one of the type argument goes from &T to &mut T"
63+
}
4764

4865
declare_clippy_lint! {
4966
/// ### What it does
@@ -475,6 +492,7 @@ impl_lint_pass!(Transmute => [
475492
USELESS_TRANSMUTE,
476493
WRONG_TRANSMUTE,
477494
TRANSMUTE_BYTES_TO_STR,
495+
MUTABLE_ADT_ARGUMENT_TRANSMUTE,
478496
TRANSMUTE_INT_TO_BOOL,
479497
TRANSMUTE_INT_TO_NON_ZERO,
480498
UNSOUND_COLLECTION_TRANSMUTE,
@@ -516,6 +534,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
516534
}
517535

518536
let linted = wrong_transmute::check(cx, e, from_ty, to_ty)
537+
| transmute_adt_argument::check(cx, e, from_ty, to_ty)
519538
| crosspointer_transmute::check(cx, e, from_ty, to_ty)
520539
| transmuting_null::check(cx, e, arg, to_ty)
521540
| transmute_null_to_fn::check(cx, e, arg, to_ty)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use super::MUTABLE_ADT_ARGUMENT_TRANSMUTE;
2+
use clippy_utils::diagnostics::span_lint;
3+
use rustc_hir::Expr;
4+
use rustc_lint::LateContext;
5+
use rustc_middle::ty::{self, GenericArgKind, Ty};
6+
7+
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool {
8+
from_ty
9+
.walk()
10+
.zip(to_ty.walk())
11+
.filter_map(|(from_ty, to_ty)| {
12+
if let (GenericArgKind::Type(from_ty), GenericArgKind::Type(to_ty)) = (from_ty.kind(), to_ty.kind()) {
13+
Some((from_ty, to_ty))
14+
} else {
15+
None
16+
}
17+
})
18+
.filter(|(from_ty_inner, to_ty_inner)| {
19+
if let (ty::Ref(_, _, from_mut), ty::Ref(_, _, to_mut)) = (from_ty_inner.kind(), to_ty_inner.kind())
20+
&& from_mut < to_mut
21+
{
22+
span_lint(
23+
cx,
24+
MUTABLE_ADT_ARGUMENT_TRANSMUTE,
25+
e.span,
26+
format!("transmute of type argument {from_ty_inner} to {from_ty_inner}"),
27+
);
28+
true
29+
} else {
30+
false
31+
}
32+
})
33+
.count()
34+
> 0
35+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#![warn(clippy::mutable_adt_argument_transmute)]
2+
3+
fn main() {
4+
// test code goes here
5+
}

0 commit comments

Comments
 (0)