Repository: rust-lang/rust
File: compiler/rustc_middle/src/ty/list.rs (Rust)

Code before:
///
/// Unlike slices, the types contained in `List` are expected to be `Copy`
/// and iterating over a `List` returns `T` instead of a reference.
///
/// Note: `Slice` was already taken by the `Ty`.
#[repr(C)]
pub struct List<T> {
    len: usize,
    data: [T; 0],
    opaque: OpaqueListContents,
}

unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
    const BITS: usize = std::mem::align_of::<usize>().trailing_zeros() as usize;
    #[inline]
    fn into_usize(self) -> usize {
        self as *const List<T> as usize
    }
    #[inline]
    unsafe fn from_usize(ptr: usize) -> Self {
        &*(ptr as *const List<T>)
    }
    unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
        // Self: Copy so this is fine
        let ptr = Self::from_usize(ptr);
        f(&ptr)
    }
}

unsafe impl<T: Sync> Sync for List<T> {}

impl<T: Copy> List<T> {
    #[inline]
    pub(super) fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List<T> {
        assert!(!mem::needs_drop::<T>());
        assert!(mem::size_of::<T>() != 0);
        assert!(!slice.is_empty());

        let (layout, _offset) =
            Layout::new::<usize>().extend(Layout::for_value::<[T]>(slice)).unwrap();
        let mem = arena.dropless.alloc_raw(layout) as *mut List<T>;
        unsafe {
            // Write the length
            ptr::addr_of_mut!((*mem).len).write(slice.len());

            // Write the elements
            ptr::addr_of_mut!((*mem).data)
                .cast::<T>()
                .copy_from_nonoverlapping(slice.as_ptr(), slice.len());

            &mut *mem

Review comment (suggestion):
```suggestion
        #[repr(align(64))]
        struct MaxAlign;

        assert!(mem::align_of::<T>() <= mem::align_of::<MaxAlign>());
```
should be a bit cleaner

Code after:
/// - `T` must be `Copy`. This lets `List<T>` be stored in a dropless arena and
///   iterators return a `T` rather than a `&T`.
/// - `T` must not be zero-sized.
#[repr(C)]
pub struct List<T> {
    len: usize,

    /// Although this claims to be a zero-length array, in practice `len`
    /// elements are actually present.
    data: [T; 0],

    opaque: OpaqueListContents,
}

extern "C" {
    /// A dummy type used to force `List` to be unsized while not requiring
    /// references to it be wide pointers.
    type OpaqueListContents;
}

impl<T> List<T> {
    /// Returns a reference to the (unique, static) empty list.
    #[inline(always)]
    pub fn empty<'a>() -> &'a List<T> {
        #[repr(align(64))]
        struct MaxAlign;

        assert!(mem::align_of::<T>() <= mem::align_of::<MaxAlign>());

        #[repr(C)]
        struct InOrder<T, U>(T, U);

        // The empty slice is static and contains a single `0` usize (for the
        // length) that is 64-byte aligned, thus featuring the necessary
        // trailing padding for elements with up to 64-byte alignment.
        static EMPTY_SLICE: InOrder<usize, MaxAlign> = InOrder(0, MaxAlign);
        unsafe { &*(&EMPTY_SLICE as *const _ as *const List<T>) }
    }
}

impl<T: Copy> List<T> {
    /// Allocates a list from `arena` and copies the contents of `slice` into it.
    ///
    /// WARNING: the contents *must be unique*, such that no list with these
    /// contents has been previously created. If not, operations such as `eq`
    /// and `hash` might give incorrect results.
    ///
    /// Panics if `T` is `Drop`, or `T` is zero-sized, or the slice is empty
    /// (because the empty list exists statically, and is available via
    /// `empty()`).
    #[inline]