Skip to content

Commit 017fb60

Browse files
committed
New lint: unsound_collection_transmute
1 parent 5f058d8 commit 017fb60

File tree

9 files changed

+491
-258
lines changed

9 files changed

+491
-258
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

+301-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.rs

-6
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,6 @@ fn useless() {
8080

8181
let _: Vec<i32> = my_transmute(my_vec());
8282

83-
let _: Vec<u32> = core::intrinsics::transmute(my_vec());
84-
let _: Vec<u32> = core::mem::transmute(my_vec());
85-
let _: Vec<u32> = std::intrinsics::transmute(my_vec());
86-
let _: Vec<u32> = std::mem::transmute(my_vec());
87-
let _: Vec<u32> = my_transmute(my_vec());
88-
8983
let _: *const usize = std::mem::transmute(5_isize);
9084

9185
let _ = 5_isize as *const usize;

tests/ui/transmute.stderr

+19-19
Original file line numberDiff line numberDiff line change
@@ -117,127 +117,127 @@ LL | let _: Vec<i32> = my_transmute(my_vec());
117117
| ^^^^^^^^^^^^^^^^^^^^^^
118118

119119
error: transmute from an integer to a pointer
120-
--> $DIR/transmute.rs:89:31
120+
--> $DIR/transmute.rs:83:31
121121
|
122122
LL | let _: *const usize = std::mem::transmute(5_isize);
123123
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize`
124124

125125
error: transmute from an integer to a pointer
126-
--> $DIR/transmute.rs:93:31
126+
--> $DIR/transmute.rs:87:31
127127
|
128128
LL | let _: *const usize = std::mem::transmute(1 + 1usize);
129129
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize`
130130

131131
error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`)
132-
--> $DIR/transmute.rs:108:24
132+
--> $DIR/transmute.rs:102:24
133133
|
134134
LL | let _: Usize = core::intrinsics::transmute(int_const_ptr);
135135
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
136136
|
137137
= note: `-D clippy::crosspointer-transmute` implied by `-D warnings`
138138

139139
error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`)
140-
--> $DIR/transmute.rs:110:24
140+
--> $DIR/transmute.rs:104:24
141141
|
142142
LL | let _: Usize = core::intrinsics::transmute(int_mut_ptr);
143143
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
144144

145145
error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`)
146-
--> $DIR/transmute.rs:112:31
146+
--> $DIR/transmute.rs:106:31
147147
|
148148
LL | let _: *const Usize = core::intrinsics::transmute(my_int());
149149
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
150150

151151
error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`)
152-
--> $DIR/transmute.rs:114:29
152+
--> $DIR/transmute.rs:108:29
153153
|
154154
LL | let _: *mut Usize = core::intrinsics::transmute(my_int());
155155
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
156156

157157
error: transmute from a `u32` to a `char`
158-
--> $DIR/transmute.rs:120:28
158+
--> $DIR/transmute.rs:114:28
159159
|
160160
LL | let _: char = unsafe { std::mem::transmute(0_u32) };
161161
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()`
162162
|
163163
= note: `-D clippy::transmute-int-to-char` implied by `-D warnings`
164164

165165
error: transmute from a `i32` to a `char`
166-
--> $DIR/transmute.rs:121:28
166+
--> $DIR/transmute.rs:115:28
167167
|
168168
LL | let _: char = unsafe { std::mem::transmute(0_i32) };
169169
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()`
170170

171171
error: transmute from a `u8` to a `bool`
172-
--> $DIR/transmute.rs:126:28
172+
--> $DIR/transmute.rs:120:28
173173
|
174174
LL | let _: bool = unsafe { std::mem::transmute(0_u8) };
175175
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0`
176176
|
177177
= note: `-D clippy::transmute-int-to-bool` implied by `-D warnings`
178178

179179
error: transmute from a `u32` to a `f32`
180-
--> $DIR/transmute.rs:131:27
180+
--> $DIR/transmute.rs:125:27
181181
|
182182
LL | let _: f32 = unsafe { std::mem::transmute(0_u32) };
183183
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
184184
|
185185
= note: `-D clippy::transmute-int-to-float` implied by `-D warnings`
186186

187187
error: transmute from a `i32` to a `f32`
188-
--> $DIR/transmute.rs:132:27
188+
--> $DIR/transmute.rs:126:27
189189
|
190190
LL | let _: f32 = unsafe { std::mem::transmute(0_i32) };
191191
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)`
192192

193193
error: transmute from a `&[u8]` to a `&str`
194-
--> $DIR/transmute.rs:136:28
194+
--> $DIR/transmute.rs:130:28
195195
|
196196
LL | let _: &str = unsafe { std::mem::transmute(b) };
197197
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()`
198198
|
199199
= note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings`
200200

201201
error: transmute from a `&mut [u8]` to a `&mut str`
202-
--> $DIR/transmute.rs:137:32
202+
--> $DIR/transmute.rs:131:32
203203
|
204204
LL | let _: &mut str = unsafe { std::mem::transmute(mb) };
205205
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`
206206

207207
error: transmute from a pointer to a pointer
208-
--> $DIR/transmute.rs:169:29
208+
--> $DIR/transmute.rs:163:29
209209
|
210210
LL | let _: *const f32 = std::mem::transmute(ptr);
211211
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32`
212212
|
213213
= note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`
214214

215215
error: transmute from a pointer to a pointer
216-
--> $DIR/transmute.rs:170:27
216+
--> $DIR/transmute.rs:164:27
217217
|
218218
LL | let _: *mut f32 = std::mem::transmute(mut_ptr);
219219
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32`
220220

221221
error: transmute from a reference to a reference
222-
--> $DIR/transmute.rs:172:23
222+
--> $DIR/transmute.rs:166:23
223223
|
224224
LL | let _: &f32 = std::mem::transmute(&1u32);
225225
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)`
226226

227227
error: transmute from a reference to a reference
228-
--> $DIR/transmute.rs:173:23
228+
--> $DIR/transmute.rs:167:23
229229
|
230230
LL | let _: &f64 = std::mem::transmute(&1f32);
231231
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1f32 as *const f32 as *const f64)`
232232

233233
error: transmute from a reference to a reference
234-
--> $DIR/transmute.rs:176:27
234+
--> $DIR/transmute.rs:170:27
235235
|
236236
LL | let _: &mut f32 = std::mem::transmute(&mut 1u32);
237237
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)`
238238

239239
error: transmute from a reference to a reference
240-
--> $DIR/transmute.rs:177:37
240+
--> $DIR/transmute.rs:171:37
241241
|
242242
LL | let _: &GenericParam<f32> = std::mem::transmute(&GenericParam { t: 1u32 });
243243
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam<u32> as *const GenericParam<f32>)`

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)