]>
Commit | Line | Data |
---|---|---|
ba9703b0 XL |
1 | // run-pass |
2 | // ignore-wasm32-bare compiled with panic=abort by default | |
17df50a5 XL |
3 | // revisions: mir thir |
4 | // [thir]compile-flags: -Zthir-unsafeck | |
ba9703b0 XL |
5 | |
6 | // This test checks panic emitted from `mem::{uninitialized,zeroed}`. | |
7 | ||
dc3f5686 | 8 | #![feature(never_type, arbitrary_enum_discriminant)] |
ba9703b0 XL |
9 | #![allow(deprecated, invalid_value)] |
10 | ||
11 | use std::{ | |
12 | mem::{self, MaybeUninit, ManuallyDrop}, | |
13 | panic, | |
14 | ptr::NonNull, | |
15 | num, | |
16 | }; | |
17 | ||
18 | #[allow(dead_code)] | |
19 | struct Foo { | |
20 | x: u8, | |
21 | y: !, | |
22 | } | |
23 | ||
24 | enum Bar {} | |
25 | ||
26 | #[allow(dead_code)] | |
27 | enum OneVariant { Variant(i32) } | |
28 | ||
1b1a35ee XL |
29 | #[allow(dead_code, non_camel_case_types)] |
30 | enum OneVariant_NonZero { | |
31 | Variant(i32, i32, num::NonZeroI32), | |
32 | DeadVariant(Bar), | |
33 | } | |
34 | ||
35 | // An `Aggregate` abi enum where 0 is not a valid discriminant. | |
36 | #[allow(dead_code)] | |
37 | #[repr(i32)] | |
38 | enum NoNullVariant { | |
39 | Variant1(i32, i32) = 1, | |
40 | Variant2(i32, i32) = 2, | |
41 | } | |
42 | ||
ba9703b0 XL |
43 | // An enum with ScalarPair layout |
44 | #[allow(dead_code)] | |
45 | enum LR { | |
46 | Left(i64), | |
47 | Right(i64), | |
48 | } | |
49 | #[allow(dead_code, non_camel_case_types)] | |
50 | enum LR_NonZero { | |
51 | Left(num::NonZeroI64), | |
52 | Right(num::NonZeroI64), | |
53 | } | |
54 | ||
55 | fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { | |
56 | let err = panic::catch_unwind(op).err(); | |
57 | assert_eq!( | |
29967ef6 XL |
58 | err.as_ref().and_then(|a| a.downcast_ref::<&str>()), |
59 | Some(&msg) | |
ba9703b0 XL |
60 | ); |
61 | } | |
62 | ||
63 | fn main() { | |
64 | unsafe { | |
65 | // Uninhabited types | |
66 | test_panic_msg( | |
67 | || mem::uninitialized::<!>(), | |
68 | "attempted to instantiate uninhabited type `!`" | |
69 | ); | |
70 | test_panic_msg( | |
71 | || mem::zeroed::<!>(), | |
72 | "attempted to instantiate uninhabited type `!`" | |
73 | ); | |
74 | test_panic_msg( | |
75 | || MaybeUninit::<!>::uninit().assume_init(), | |
76 | "attempted to instantiate uninhabited type `!`" | |
77 | ); | |
78 | ||
79 | test_panic_msg( | |
80 | || mem::uninitialized::<Foo>(), | |
81 | "attempted to instantiate uninhabited type `Foo`" | |
82 | ); | |
83 | test_panic_msg( | |
84 | || mem::zeroed::<Foo>(), | |
85 | "attempted to instantiate uninhabited type `Foo`" | |
86 | ); | |
87 | test_panic_msg( | |
88 | || MaybeUninit::<Foo>::uninit().assume_init(), | |
89 | "attempted to instantiate uninhabited type `Foo`" | |
90 | ); | |
91 | ||
92 | test_panic_msg( | |
93 | || mem::uninitialized::<Bar>(), | |
94 | "attempted to instantiate uninhabited type `Bar`" | |
95 | ); | |
96 | test_panic_msg( | |
97 | || mem::zeroed::<Bar>(), | |
98 | "attempted to instantiate uninhabited type `Bar`" | |
99 | ); | |
100 | test_panic_msg( | |
101 | || MaybeUninit::<Bar>::uninit().assume_init(), | |
102 | "attempted to instantiate uninhabited type `Bar`" | |
103 | ); | |
104 | ||
105 | // Types that do not like zero-initialziation | |
106 | test_panic_msg( | |
107 | || mem::uninitialized::<fn()>(), | |
108 | "attempted to leave type `fn()` uninitialized, which is invalid" | |
109 | ); | |
110 | test_panic_msg( | |
111 | || mem::zeroed::<fn()>(), | |
112 | "attempted to zero-initialize type `fn()`, which is invalid" | |
113 | ); | |
114 | ||
115 | test_panic_msg( | |
116 | || mem::uninitialized::<*const dyn Send>(), | |
117 | "attempted to leave type `*const dyn std::marker::Send` uninitialized, which is invalid" | |
118 | ); | |
119 | test_panic_msg( | |
120 | || mem::zeroed::<*const dyn Send>(), | |
121 | "attempted to zero-initialize type `*const dyn std::marker::Send`, which is invalid" | |
122 | ); | |
123 | ||
124 | /* FIXME(#66151) we conservatively do not error here yet. | |
125 | test_panic_msg( | |
126 | || mem::uninitialized::<LR_NonZero>(), | |
127 | "attempted to leave type `LR_NonZero` uninitialized, which is invalid" | |
128 | ); | |
129 | test_panic_msg( | |
130 | || mem::zeroed::<LR_NonZero>(), | |
131 | "attempted to zero-initialize type `LR_NonZero`, which is invalid" | |
132 | ); | |
133 | ||
134 | test_panic_msg( | |
135 | || mem::uninitialized::<ManuallyDrop<LR_NonZero>>(), | |
136 | "attempted to leave type `std::mem::ManuallyDrop<LR_NonZero>` uninitialized, \ | |
137 | which is invalid" | |
138 | ); | |
139 | test_panic_msg( | |
140 | || mem::zeroed::<ManuallyDrop<LR_NonZero>>(), | |
141 | "attempted to zero-initialize type `std::mem::ManuallyDrop<LR_NonZero>`, \ | |
142 | which is invalid" | |
143 | ); | |
1b1a35ee | 144 | */ |
ba9703b0 XL |
145 | |
146 | test_panic_msg( | |
147 | || mem::uninitialized::<(NonNull<u32>, u32, u32)>(), | |
148 | "attempted to leave type `(std::ptr::NonNull<u32>, u32, u32)` uninitialized, \ | |
149 | which is invalid" | |
150 | ); | |
151 | test_panic_msg( | |
152 | || mem::zeroed::<(NonNull<u32>, u32, u32)>(), | |
153 | "attempted to zero-initialize type `(std::ptr::NonNull<u32>, u32, u32)`, \ | |
154 | which is invalid" | |
155 | ); | |
1b1a35ee XL |
156 | |
157 | test_panic_msg( | |
158 | || mem::uninitialized::<OneVariant_NonZero>(), | |
159 | "attempted to leave type `OneVariant_NonZero` uninitialized, \ | |
160 | which is invalid" | |
161 | ); | |
162 | test_panic_msg( | |
163 | || mem::zeroed::<OneVariant_NonZero>(), | |
164 | "attempted to zero-initialize type `OneVariant_NonZero`, \ | |
165 | which is invalid" | |
166 | ); | |
167 | ||
168 | test_panic_msg( | |
169 | || mem::uninitialized::<NoNullVariant>(), | |
170 | "attempted to leave type `NoNullVariant` uninitialized, \ | |
171 | which is invalid" | |
172 | ); | |
173 | test_panic_msg( | |
174 | || mem::zeroed::<NoNullVariant>(), | |
175 | "attempted to zero-initialize type `NoNullVariant`, \ | |
176 | which is invalid" | |
177 | ); | |
ba9703b0 XL |
178 | |
179 | // Types that can be zero, but not uninit. | |
180 | test_panic_msg( | |
181 | || mem::uninitialized::<bool>(), | |
182 | "attempted to leave type `bool` uninitialized, which is invalid" | |
183 | ); | |
184 | test_panic_msg( | |
185 | || mem::uninitialized::<LR>(), | |
186 | "attempted to leave type `LR` uninitialized, which is invalid" | |
187 | ); | |
188 | test_panic_msg( | |
189 | || mem::uninitialized::<ManuallyDrop<LR>>(), | |
190 | "attempted to leave type `std::mem::ManuallyDrop<LR>` uninitialized, which is invalid" | |
191 | ); | |
192 | ||
193 | // Some things that should work. | |
194 | let _val = mem::zeroed::<bool>(); | |
195 | let _val = mem::zeroed::<LR>(); | |
196 | let _val = mem::zeroed::<ManuallyDrop<LR>>(); | |
197 | let _val = mem::zeroed::<OneVariant>(); | |
198 | let _val = mem::zeroed::<Option<&'static i32>>(); | |
199 | let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>(); | |
200 | let _val = mem::uninitialized::<MaybeUninit<bool>>(); | |
201 | ||
202 | // These are UB because they have not been officially blessed, but we await the resolution | |
203 | // of <https://github.com/rust-lang/unsafe-code-guidelines/issues/71> before doing | |
204 | // anything about that. | |
205 | let _val = mem::uninitialized::<i32>(); | |
206 | let _val = mem::uninitialized::<*const ()>(); | |
207 | } | |
208 | } |