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