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