]> git.lizzy.rs Git - rust.git/blob - src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
255151a96032c016eccb4305c614925306e1b79b
[rust.git] / src / test / ui / intrinsics / panic-uninitialized-zeroed.rs
1 // run-pass
2 // needs-unwind
3 // ignore-wasm32-bare compiled with panic=abort by default
4 // revisions: mir thir strict
5 // [thir]compile-flags: -Zthir-unsafeck
6 // [strict]compile-flags: -Zstrict-init-checks
7 // ignore-tidy-linelength
8
9 // This test checks panic emitted from `mem::{uninitialized,zeroed}`.
10
11 #![feature(never_type, arbitrary_enum_discriminant)]
12 #![allow(deprecated, invalid_value)]
13
14 use std::{
15     mem::{self, MaybeUninit, ManuallyDrop},
16     panic,
17     ptr::NonNull,
18     num,
19 };
20
21 #[allow(dead_code)]
22 struct Foo {
23     x: u8,
24     y: !,
25 }
26
27 enum Bar {}
28
29 #[allow(dead_code)]
30 enum OneVariant { Variant(i32) }
31
32 #[allow(dead_code, non_camel_case_types)]
33 enum OneVariant_NonZero {
34     Variant(i32, i32, num::NonZeroI32),
35     DeadVariant(Bar),
36 }
37
38 // An `Aggregate` abi enum where 0 is not a valid discriminant.
39 #[allow(dead_code)]
40 #[repr(i32)]
41 enum NoNullVariant {
42     Variant1(i32, i32) = 1,
43     Variant2(i32, i32) = 2,
44 }
45
46 // An enum with ScalarPair layout
47 #[allow(dead_code)]
48 enum LR {
49     Left(i64),
50     Right(i64),
51 }
52 #[allow(dead_code, non_camel_case_types)]
53 enum LR_NonZero {
54     Left(num::NonZeroI64),
55     Right(num::NonZeroI64),
56 }
57
58 struct ZeroSized;
59
60 #[allow(dead_code)]
61 #[repr(i32)]
62 enum ZeroIsValid {
63     Zero(u8) = 0,
64     One(NonNull<()>) = 1,
65 }
66
67 fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
68     let err = panic::catch_unwind(op).err();
69     assert_eq!(
70         err.as_ref().and_then(|a| a.downcast_ref::<&str>()),
71         Some(&msg)
72     );
73 }
74
75 fn main() {
76     unsafe {
77         // Uninhabited types
78         test_panic_msg(
79             || mem::uninitialized::<!>(),
80             "attempted to instantiate uninhabited type `!`"
81         );
82         test_panic_msg(
83             || mem::zeroed::<!>(),
84             "attempted to instantiate uninhabited type `!`"
85         );
86         test_panic_msg(
87             || MaybeUninit::<!>::uninit().assume_init(),
88             "attempted to instantiate uninhabited type `!`"
89         );
90
91         test_panic_msg(
92             || mem::uninitialized::<Foo>(),
93             "attempted to instantiate uninhabited type `Foo`"
94         );
95         test_panic_msg(
96             || mem::zeroed::<Foo>(),
97             "attempted to instantiate uninhabited type `Foo`"
98         );
99         test_panic_msg(
100             || MaybeUninit::<Foo>::uninit().assume_init(),
101             "attempted to instantiate uninhabited type `Foo`"
102         );
103
104         test_panic_msg(
105             || mem::uninitialized::<Bar>(),
106             "attempted to instantiate uninhabited type `Bar`"
107         );
108         test_panic_msg(
109             || mem::zeroed::<Bar>(),
110             "attempted to instantiate uninhabited type `Bar`"
111         );
112         test_panic_msg(
113             || MaybeUninit::<Bar>::uninit().assume_init(),
114             "attempted to instantiate uninhabited type `Bar`"
115         );
116
117         test_panic_msg(
118             || mem::uninitialized::<[Foo; 2]>(),
119             "attempted to instantiate uninhabited type `[Foo; 2]`"
120         );
121         test_panic_msg(
122             || mem::zeroed::<[Foo; 2]>(),
123             "attempted to instantiate uninhabited type `[Foo; 2]`"
124         );
125         test_panic_msg(
126             || MaybeUninit::<[Foo; 2]>::uninit().assume_init(),
127             "attempted to instantiate uninhabited type `[Foo; 2]`"
128         );
129
130         test_panic_msg(
131             || mem::uninitialized::<[Bar; 2]>(),
132             "attempted to instantiate uninhabited type `[Bar; 2]`"
133         );
134         test_panic_msg(
135             || mem::zeroed::<[Bar; 2]>(),
136             "attempted to instantiate uninhabited type `[Bar; 2]`"
137         );
138         test_panic_msg(
139             || MaybeUninit::<[Bar; 2]>::uninit().assume_init(),
140             "attempted to instantiate uninhabited type `[Bar; 2]`"
141         );
142
143         // Types that do not like zero-initialziation
144         test_panic_msg(
145             || mem::uninitialized::<fn()>(),
146             "attempted to leave type `fn()` uninitialized, which is invalid"
147         );
148         test_panic_msg(
149             || mem::zeroed::<fn()>(),
150             "attempted to zero-initialize type `fn()`, which is invalid"
151         );
152
153         test_panic_msg(
154             || mem::uninitialized::<*const dyn Send>(),
155             "attempted to leave type `*const dyn core::marker::Send` uninitialized, which is invalid"
156         );
157         test_panic_msg(
158             || mem::zeroed::<*const dyn Send>(),
159             "attempted to zero-initialize type `*const dyn core::marker::Send`, which is invalid"
160         );
161
162         test_panic_msg(
163             || mem::uninitialized::<(NonNull<u32>, u32, u32)>(),
164             "attempted to leave type `(core::ptr::non_null::NonNull<u32>, u32, u32)` uninitialized, \
165                 which is invalid"
166         );
167
168         test_panic_msg(
169             || mem::zeroed::<(NonNull<u32>, u32, u32)>(),
170             "attempted to zero-initialize type `(core::ptr::non_null::NonNull<u32>, u32, u32)`, \
171                 which is invalid"
172         );
173
174         test_panic_msg(
175             || mem::uninitialized::<OneVariant_NonZero>(),
176             "attempted to leave type `OneVariant_NonZero` uninitialized, \
177                 which is invalid"
178         );
179         test_panic_msg(
180             || mem::zeroed::<OneVariant_NonZero>(),
181             "attempted to zero-initialize type `OneVariant_NonZero`, \
182                 which is invalid"
183         );
184
185         test_panic_msg(
186             || mem::uninitialized::<LR_NonZero>(),
187             "attempted to leave type `LR_NonZero` uninitialized, which is invalid"
188         );
189
190         test_panic_msg(
191             || mem::uninitialized::<ManuallyDrop<LR_NonZero>>(),
192             "attempted to leave type `core::mem::manually_drop::ManuallyDrop<LR_NonZero>` uninitialized, \
193              which is invalid"
194         );
195
196         test_panic_msg(
197             || mem::uninitialized::<NoNullVariant>(),
198             "attempted to leave type `NoNullVariant` uninitialized, \
199                 which is invalid"
200         );
201
202         test_panic_msg(
203             || mem::zeroed::<NoNullVariant>(),
204             "attempted to zero-initialize type `NoNullVariant`, \
205                 which is invalid"
206         );
207
208         // Types that can be zero, but not uninit.
209         test_panic_msg(
210             || mem::uninitialized::<bool>(),
211             "attempted to leave type `bool` uninitialized, which is invalid"
212         );
213
214         test_panic_msg(
215             || mem::uninitialized::<LR>(),
216             "attempted to leave type `LR` uninitialized, which is invalid"
217         );
218
219         test_panic_msg(
220             || mem::uninitialized::<ManuallyDrop<LR>>(),
221             "attempted to leave type `core::mem::manually_drop::ManuallyDrop<LR>` uninitialized, which is invalid"
222         );
223
224         // Some things that should work.
225         let _val = mem::zeroed::<bool>();
226         let _val = mem::zeroed::<LR>();
227         let _val = mem::zeroed::<ManuallyDrop<LR>>();
228         let _val = mem::zeroed::<OneVariant>();
229         let _val = mem::zeroed::<Option<&'static i32>>();
230         let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>();
231         let _val = mem::zeroed::<[!; 0]>();
232         let _val = mem::zeroed::<ZeroIsValid>();
233         let _val = mem::uninitialized::<MaybeUninit<bool>>();
234         let _val = mem::uninitialized::<[!; 0]>();
235         let _val = mem::uninitialized::<()>();
236         let _val = mem::uninitialized::<ZeroSized>();
237
238         if cfg!(strict) {
239             test_panic_msg(
240                 || mem::uninitialized::<i32>(),
241                 "attempted to leave type `i32` uninitialized, which is invalid"
242             );
243
244             test_panic_msg(
245                 || mem::uninitialized::<*const ()>(),
246                 "attempted to leave type `*const ()` uninitialized, which is invalid"
247             );
248
249             test_panic_msg(
250                 || mem::uninitialized::<[i32; 1]>(),
251                 "attempted to leave type `[i32; 1]` uninitialized, which is invalid"
252             );
253
254             test_panic_msg(
255                 || mem::zeroed::<NonNull<()>>(),
256                 "attempted to zero-initialize type `core::ptr::non_null::NonNull<()>`, which is invalid"
257             );
258
259             test_panic_msg(
260                 || mem::zeroed::<[NonNull<()>; 1]>(),
261                 "attempted to zero-initialize type `[core::ptr::non_null::NonNull<()>; 1]`, which is invalid"
262             );
263
264             // FIXME(#66151) we conservatively do not error here yet (by default).
265             test_panic_msg(
266                 || mem::zeroed::<LR_NonZero>(),
267                 "attempted to zero-initialize type `LR_NonZero`, which is invalid"
268             );
269
270             test_panic_msg(
271                 || mem::zeroed::<ManuallyDrop<LR_NonZero>>(),
272                 "attempted to zero-initialize type `core::mem::manually_drop::ManuallyDrop<LR_NonZero>`, \
273                  which is invalid"
274             );
275         } else {
276             // These are UB because they have not been officially blessed, but we await the resolution
277             // of <https://github.com/rust-lang/unsafe-code-guidelines/issues/71> before doing
278             // anything about that.
279             let _val = mem::uninitialized::<i32>();
280             let _val = mem::uninitialized::<*const ()>();
281
282             // These are UB, but best to test them to ensure we don't become unintentionally
283             // stricter.
284
285             // It's currently unchecked to create invalid enums and values inside arrays.
286             let _val = mem::zeroed::<LR_NonZero>();
287             let _val = mem::zeroed::<[LR_NonZero; 1]>();
288             let _val = mem::zeroed::<[NonNull<()>; 1]>();
289             let _val = mem::uninitialized::<[NonNull<()>; 1]>();
290         }
291     }
292 }