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