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

Code before:

use rustc_serialize::{Encodable, Encoder};

use std::alloc::Layout;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter;
use std::mem;
use std::ops::Deref;
use std::ptr;
use std::slice;

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

/// A wrapper for slices with the additional invariant
/// that the slice is interned and no other slice with
/// the same contents can exist in the same context.
/// This means we can use pointer for both
/// equality comparisons and hashing.
///
/// 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)
    }

Review comment (suggestion):
```suggestion
/// - `T` must be `Copy`.  This lets `List<T>` be stored in a dropless arena and
/// allows iterators over `List<T>` to return `T` instead of `&T`. 
```
something like this. Rn it reads like "iterating over a `List<T>` returns a `T`" implies "This lets `List<T>` be stored in a dropless arena." which isn't what is said here.

Code after:
use rustc_serialize::{Encodable, Encoder};
use std::alloc::Layout;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter;
use std::mem;
use std::ops::Deref;
use std::ptr;
use std::slice;

/// `List<T>` is a bit like `&[T]`, but with some critical differences.
/// - IMPORTANT: Every `List<T>` is *required* to have unique contents. The
///   type's correctness relies on this, *but it does not enforce it*.
///   Therefore, any code that creates a `List<T>` must ensure uniqueness
///   itself. In practice this is achieved by interning.
/// - The length is stored within the `List<T>`, so `&List<Ty>` is a thin
///   pointer.
/// - Because of this, you cannot get a `List<T>` that is a sub-list of another
///   `List<T>`. You can get a sub-slice `&[T]`, however.
/// - `List<T>` can be used with `CopyTaggedPtr`, which is useful within
///   structs whose size must be minimized.
/// - Because of the uniqueness assumption, we can use the address of a
///   `List<T>` for faster equality comparisons and hashing.
/// - `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;