]>
Commit | Line | Data |
---|---|---|
a2a8927a XL |
1 | // run-pass |
2 | // | |
3 | // Test that we can handle unsized types with an extern type tail part. | |
4 | // Regression test for issue #91827. | |
5 | ||
a2a8927a XL |
6 | #![feature(extern_types)] |
7 | ||
8 | use std::ptr::addr_of; | |
9 | ||
10 | extern "C" { | |
11 | type Opaque; | |
12 | } | |
13 | ||
14 | unsafe impl Sync for Opaque {} | |
15 | ||
16 | #[repr(C)] | |
17 | pub struct List<T> { | |
18 | len: usize, | |
19 | data: [T; 0], | |
20 | tail: Opaque, | |
21 | } | |
22 | ||
23 | #[repr(C)] | |
24 | pub struct ListImpl<T, const N: usize> { | |
25 | len: usize, | |
26 | data: [T; N], | |
27 | } | |
28 | ||
29 | impl<T> List<T> { | |
30 | const fn as_slice(&self) -> &[T] { | |
31 | unsafe { std::slice::from_raw_parts(self.data.as_ptr(), self.len) } | |
32 | } | |
33 | } | |
34 | ||
35 | impl<T, const N: usize> ListImpl<T, N> { | |
36 | const fn as_list(&self) -> &List<T> { | |
37 | unsafe { std::mem::transmute(self) } | |
38 | } | |
39 | } | |
40 | ||
41 | pub static A: ListImpl<u128, 3> = ListImpl { | |
42 | len: 3, | |
43 | data: [5, 6, 7], | |
44 | }; | |
45 | pub static A_REF: &'static List<u128> = A.as_list(); | |
46 | pub static A_TAIL_OFFSET: isize = tail_offset(A.as_list()); | |
47 | ||
48 | const fn tail_offset<T>(list: &List<T>) -> isize { | |
49 | unsafe { (addr_of!(list.tail) as *const u8).offset_from(list as *const List<T> as *const u8) } | |
50 | } | |
51 | ||
52 | fn main() { | |
53 | assert_eq!(A_REF.as_slice(), &[5, 6, 7]); | |
54 | // Check that interpreter and code generation agree about the position of the tail field. | |
55 | assert_eq!(A_TAIL_OFFSET, tail_offset(A_REF)); | |
56 | } |