Skip to content

Commit 2f430ef

Browse files
committed
New lint: unsound_collection_transmute
1 parent edd9047 commit 2f430ef

File tree

8 files changed

+503
-234
lines changed

8 files changed

+503
-234
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,7 @@ Released 2018-09-13
12241224
[`unsafe_removed_from_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_removed_from_name
12251225
[`unsafe_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_vector_initialization
12261226
[`unseparated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#unseparated_literal_suffix
1227+
[`unsound_collection_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsound_collection_transmute
12271228
[`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice
12281229
[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice
12291230
[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
88

9-
[There are 317 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
9+
[There are 318 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
1010

1111
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
1212

clippy_lints/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,7 @@ pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry<'_>, conf: &Con
889889
transmute::TRANSMUTE_INT_TO_FLOAT,
890890
transmute::TRANSMUTE_PTR_TO_PTR,
891891
transmute::TRANSMUTE_PTR_TO_REF,
892+
transmute::UNSOUND_COLLECTION_TRANSMUTE,
892893
transmute::USELESS_TRANSMUTE,
893894
transmute::WRONG_TRANSMUTE,
894895
transmuting_null::TRANSMUTING_NULL,
@@ -1143,6 +1144,7 @@ pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry<'_>, conf: &Con
11431144
suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
11441145
suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
11451146
swap::ALMOST_SWAPPED,
1147+
transmute::UNSOUND_COLLECTION_TRANSMUTE,
11461148
transmute::WRONG_TRANSMUTE,
11471149
transmuting_null::TRANSMUTING_NULL,
11481150
types::ABSURD_EXTREME_COMPARISONS,

clippy_lints/src/transmute.rs

+299-231
Large diffs are not rendered by default.

src/lintlist/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub use lint::Lint;
66
pub use lint::LINT_LEVELS;
77

88
// begin lint list, do not remove this comment, it’s used in `update_lints`
9-
pub const ALL_LINTS: [Lint; 317] = [
9+
pub const ALL_LINTS: [Lint; 318] = [
1010
Lint {
1111
name: "absurd_extreme_comparisons",
1212
group: "correctness",
@@ -2023,6 +2023,13 @@ pub const ALL_LINTS: [Lint; 317] = [
20232023
deprecation: None,
20242024
module: "misc_early",
20252025
},
2026+
Lint {
2027+
name: "unsound_collection_transmute",
2028+
group: "correctness",
2029+
desc: "transmute between collections of layout-incompatible types",
2030+
deprecation: None,
2031+
module: "transmute",
2032+
},
20262033
Lint {
20272034
name: "unused_io_amount",
20282035
group: "correctness",

tests/ui/transmute.stderr

+33-1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,38 @@ error: transmute from a type (`std::vec::Vec<i32>`) to itself
116116
LL | let _: Vec<i32> = my_transmute(my_vec());
117117
| ^^^^^^^^^^^^^^^^^^^^^^
118118

119+
error: transmute from `std::vec::Vec<i32>` to `std::vec::Vec<u32>` with mismatched layout is unsound
120+
--> $DIR/transmute.rs:83:27
121+
|
122+
LL | let _: Vec<u32> = core::intrinsics::transmute(my_vec());
123+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
124+
|
125+
= note: `#[deny(clippy::unsound_collection_transmute)]` on by default
126+
127+
error: transmute from `std::vec::Vec<i32>` to `std::vec::Vec<u32>` with mismatched layout is unsound
128+
--> $DIR/transmute.rs:84:27
129+
|
130+
LL | let _: Vec<u32> = core::mem::transmute(my_vec());
131+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
132+
133+
error: transmute from `std::vec::Vec<i32>` to `std::vec::Vec<u32>` with mismatched layout is unsound
134+
--> $DIR/transmute.rs:85:27
135+
|
136+
LL | let _: Vec<u32> = std::intrinsics::transmute(my_vec());
137+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
138+
139+
error: transmute from `std::vec::Vec<i32>` to `std::vec::Vec<u32>` with mismatched layout is unsound
140+
--> $DIR/transmute.rs:86:27
141+
|
142+
LL | let _: Vec<u32> = std::mem::transmute(my_vec());
143+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
144+
145+
error: transmute from `std::vec::Vec<i32>` to `std::vec::Vec<u32>` with mismatched layout is unsound
146+
--> $DIR/transmute.rs:87:27
147+
|
148+
LL | let _: Vec<u32> = my_transmute(my_vec());
149+
| ^^^^^^^^^^^^^^^^^^^^^^
150+
119151
error: transmute from an integer to a pointer
120152
--> $DIR/transmute.rs:89:31
121153
|
@@ -242,5 +274,5 @@ error: transmute from a reference to a reference
242274
LL | let _: &GenericParam<f32> = std::mem::transmute(&GenericParam { t: 1u32 });
243275
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam<u32> as *const GenericParam<f32>)`
244276

245-
error: aborting due to 38 previous errors
277+
error: aborting due to 43 previous errors
246278

tests/ui/transmute_collection.rs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#![warn(clippy::unsound_collection_transmute)]
2+
3+
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
4+
use std::mem::transmute;
5+
6+
fn main() {
7+
unsafe {
8+
// wrong size
9+
let _ = transmute::<_, Vec<u32>>(vec![0u8]);
10+
// wrong layout
11+
let _ = transmute::<_, Vec<[u8; 4]>>(vec![1234u32]);
12+
13+
// wrong size
14+
let _ = transmute::<_, VecDeque<u32>>(VecDeque::<u8>::new());
15+
// wrong layout
16+
let _ = transmute::<_, VecDeque<u32>>(VecDeque::<[u8; 4]>::new());
17+
18+
// wrong size
19+
let _ = transmute::<_, BinaryHeap<u32>>(BinaryHeap::<u8>::new());
20+
// wrong layout
21+
let _ = transmute::<_, BinaryHeap<u32>>(BinaryHeap::<[u8; 4]>::new());
22+
23+
// wrong size
24+
let _ = transmute::<_, BTreeSet<u32>>(BTreeSet::<u8>::new());
25+
// wrong layout
26+
let _ = transmute::<_, BTreeSet<u32>>(BTreeSet::<[u8; 4]>::new());
27+
28+
// wrong size
29+
let _ = transmute::<_, HashSet<u32>>(HashSet::<u8>::new());
30+
// wrong layout
31+
let _ = transmute::<_, HashSet<u32>>(HashSet::<[u8; 4]>::new());
32+
33+
// wrong size
34+
let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u8, u8>::new());
35+
let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u32, u32>::new());
36+
// wrong layout
37+
let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u8, [u8; 4]>::new());
38+
let _ = transmute::<_, BTreeMap<u32, u32>>(BTreeMap::<[u8; 4], u32>::new());
39+
40+
// wrong size
41+
let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u8, u8>::new());
42+
let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u32, u32>::new());
43+
// wrong layout
44+
let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u8, [u8; 4]>::new());
45+
let _ = transmute::<_, HashMap<u32, u32>>(HashMap::<[u8; 4], u32>::new());
46+
}
47+
}

tests/ui/transmute_collection.stderr

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
error: transmute from `std::vec::Vec<u8>` to `std::vec::Vec<u32>` with mismatched layout is unsound
2+
--> $DIR/transmute_collection.rs:9:17
3+
|
4+
LL | let _ = transmute::<_, Vec<u32>>(vec![0u8]);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::unsound-collection-transmute` implied by `-D warnings`
8+
9+
error: transmute from `std::vec::Vec<u32>` to `std::vec::Vec<[u8; 4]>` with mismatched layout is unsound
10+
--> $DIR/transmute_collection.rs:11:17
11+
|
12+
LL | let _ = transmute::<_, Vec<[u8; 4]>>(vec![1234u32]);
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
15+
error: transmute from `std::collections::VecDeque<u8>` to `std::collections::VecDeque<u32>` with mismatched layout is unsound
16+
--> $DIR/transmute_collection.rs:14:17
17+
|
18+
LL | let _ = transmute::<_, VecDeque<u32>>(VecDeque::<u8>::new());
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
21+
error: transmute from `std::collections::VecDeque<[u8; 4]>` to `std::collections::VecDeque<u32>` with mismatched layout is unsound
22+
--> $DIR/transmute_collection.rs:16:17
23+
|
24+
LL | let _ = transmute::<_, VecDeque<u32>>(VecDeque::<[u8; 4]>::new());
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26+
27+
error: transmute from `std::collections::BinaryHeap<u8>` to `std::collections::BinaryHeap<u32>` with mismatched layout is unsound
28+
--> $DIR/transmute_collection.rs:19:17
29+
|
30+
LL | let _ = transmute::<_, BinaryHeap<u32>>(BinaryHeap::<u8>::new());
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32+
33+
error: transmute from `std::collections::BinaryHeap<[u8; 4]>` to `std::collections::BinaryHeap<u32>` with mismatched layout is unsound
34+
--> $DIR/transmute_collection.rs:21:17
35+
|
36+
LL | let _ = transmute::<_, BinaryHeap<u32>>(BinaryHeap::<[u8; 4]>::new());
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38+
39+
error: transmute from `std::collections::BTreeSet<u8>` to `std::collections::BTreeSet<u32>` with mismatched layout is unsound
40+
--> $DIR/transmute_collection.rs:24:17
41+
|
42+
LL | let _ = transmute::<_, BTreeSet<u32>>(BTreeSet::<u8>::new());
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44+
45+
error: transmute from `std::collections::BTreeSet<[u8; 4]>` to `std::collections::BTreeSet<u32>` with mismatched layout is unsound
46+
--> $DIR/transmute_collection.rs:26:17
47+
|
48+
LL | let _ = transmute::<_, BTreeSet<u32>>(BTreeSet::<[u8; 4]>::new());
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
50+
51+
error: transmute from `std::collections::HashSet<u8>` to `std::collections::HashSet<u32>` with mismatched layout is unsound
52+
--> $DIR/transmute_collection.rs:29:17
53+
|
54+
LL | let _ = transmute::<_, HashSet<u32>>(HashSet::<u8>::new());
55+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56+
57+
error: transmute from `std::collections::HashSet<[u8; 4]>` to `std::collections::HashSet<u32>` with mismatched layout is unsound
58+
--> $DIR/transmute_collection.rs:31:17
59+
|
60+
LL | let _ = transmute::<_, HashSet<u32>>(HashSet::<[u8; 4]>::new());
61+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62+
63+
error: transmute from `std::collections::BTreeMap<u8, u8>` to `std::collections::BTreeMap<u8, u32>` with mismatched layout is unsound
64+
--> $DIR/transmute_collection.rs:34:17
65+
|
66+
LL | let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u8, u8>::new());
67+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
68+
69+
error: transmute from `std::collections::BTreeMap<u32, u32>` to `std::collections::BTreeMap<u8, u32>` with mismatched layout is unsound
70+
--> $DIR/transmute_collection.rs:35:17
71+
|
72+
LL | let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u32, u32>::new());
73+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
74+
75+
error: transmute from `std::collections::BTreeMap<u8, [u8; 4]>` to `std::collections::BTreeMap<u8, u32>` with mismatched layout is unsound
76+
--> $DIR/transmute_collection.rs:37:17
77+
|
78+
LL | let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u8, [u8; 4]>::new());
79+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
80+
81+
error: transmute from `std::collections::BTreeMap<[u8; 4], u32>` to `std::collections::BTreeMap<u32, u32>` with mismatched layout is unsound
82+
--> $DIR/transmute_collection.rs:38:17
83+
|
84+
LL | let _ = transmute::<_, BTreeMap<u32, u32>>(BTreeMap::<[u8; 4], u32>::new());
85+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
86+
87+
error: transmute from `std::collections::HashMap<u8, u8>` to `std::collections::HashMap<u8, u32>` with mismatched layout is unsound
88+
--> $DIR/transmute_collection.rs:41:17
89+
|
90+
LL | let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u8, u8>::new());
91+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
92+
93+
error: transmute from `std::collections::HashMap<u32, u32>` to `std::collections::HashMap<u8, u32>` with mismatched layout is unsound
94+
--> $DIR/transmute_collection.rs:42:17
95+
|
96+
LL | let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u32, u32>::new());
97+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
98+
99+
error: transmute from `std::collections::HashMap<u8, [u8; 4]>` to `std::collections::HashMap<u8, u32>` with mismatched layout is unsound
100+
--> $DIR/transmute_collection.rs:44:17
101+
|
102+
LL | let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u8, [u8; 4]>::new());
103+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
104+
105+
error: transmute from `std::collections::HashMap<[u8; 4], u32>` to `std::collections::HashMap<u32, u32>` with mismatched layout is unsound
106+
--> $DIR/transmute_collection.rs:45:17
107+
|
108+
LL | let _ = transmute::<_, HashMap<u32, u32>>(HashMap::<[u8; 4], u32>::new());
109+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
110+
111+
error: aborting due to 18 previous errors
112+

0 commit comments

Comments
 (0)