1 use crate::arena::Arena;
3 use rustc_serialize::{Encodable, Encoder};
5 use std::cmp::{self, Ordering};
7 use std::hash::{Hash, Hasher};
15 /// A dummy type used to force `List` to be unsized while not requiring references to it be wide
17 type OpaqueListContents;
20 /// A wrapper for slices with the additional invariant
21 /// that the slice is interned and no other slice with
22 /// the same contents can exist in the same context.
23 /// This means we can use pointer for both
24 /// equality comparisons and hashing.
26 /// Unlike slices, The types contained in `List` are expected to be `Copy`
27 /// and iterating over a `List` returns `T` instead of a reference.
29 /// Note: `Slice` was already taken by the `Ty`.
34 opaque: OpaqueListContents,
37 unsafe impl<T: Sync> Sync for List<T> {}
39 impl<T: Copy> List<T> {
41 pub(super) fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List<T> {
42 assert!(!mem::needs_drop::<T>());
43 assert!(mem::size_of::<T>() != 0);
44 assert!(!slice.is_empty());
46 // Align up the size of the len (usize) field
47 let align = mem::align_of::<T>();
48 let align_mask = align - 1;
49 let offset = mem::size_of::<usize>();
50 let offset = (offset + align_mask) & !align_mask;
52 let size = offset + slice.len() * mem::size_of::<T>();
56 .alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
58 let result = &mut *(mem as *mut List<T>);
60 result.len = slice.len();
63 let arena_slice = slice::from_raw_parts_mut(result.data.as_mut_ptr(), result.len);
64 arena_slice.copy_from_slice(slice);
70 // If this method didn't exist, we would use `slice.iter` due to
73 // This would be weird, as `self.into_iter` iterates over `T` directly.
75 pub fn iter(&self) -> <&'_ List<T> as IntoIterator>::IntoIter {
80 impl<T: fmt::Debug> fmt::Debug for List<T> {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 impl<T: Encodable> Encodable for List<T> {
88 fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
93 impl<T> Ord for List<T>
97 fn cmp(&self, other: &List<T>) -> Ordering {
98 if self == other { Ordering::Equal } else { <[T] as Ord>::cmp(&**self, &**other) }
102 impl<T> PartialOrd for List<T>
106 fn partial_cmp(&self, other: &List<T>) -> Option<Ordering> {
108 Some(Ordering::Equal)
110 <[T] as PartialOrd>::partial_cmp(&**self, &**other)
115 impl<T: PartialEq> PartialEq for List<T> {
117 fn eq(&self, other: &List<T>) -> bool {
121 impl<T: Eq> Eq for List<T> {}
123 impl<T> Hash for List<T> {
125 fn hash<H: Hasher>(&self, s: &mut H) {
126 (self as *const List<T>).hash(s)
130 impl<T> Deref for List<T> {
133 fn deref(&self) -> &[T] {
138 impl<T> AsRef<[T]> for List<T> {
140 fn as_ref(&self) -> &[T] {
141 unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) }
145 impl<'a, T: Copy> IntoIterator for &'a List<T> {
147 type IntoIter = iter::Copied<<&'a [T] as IntoIterator>::IntoIter>;
149 fn into_iter(self) -> Self::IntoIter {
150 self[..].iter().copied()
156 pub fn empty<'a>() -> &'a List<T> {
157 #[repr(align(64), C)]
158 struct EmptySlice([u8; 64]);
159 static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]);
160 assert!(mem::align_of::<T>() <= 64);
161 unsafe { &*(&EMPTY_SLICE as *const _ as *const List<T>) }