1use std::alloc::Layout;
2use std::cmp::Ordering;
3use std::hash::{Hash, Hasher};
4use std::ops::Deref;
5use std::{fmt, iter, mem, ptr, slice};
6
7use rustc_data_structures::aligned::{Aligned, align_of};
8use rustc_data_structures::sync::DynSync;
9use rustc_serialize::{Encodable, Encoder};
10use rustc_type_ir::FlagComputation;
11
12use super::{DebruijnIndex, TyCtxt, TypeFlags};
13use crate::arena::Arena;
14
15pub type List<T> = RawList<(), T>;
32
33#[repr(C)]
38pub struct RawList<H, T> {
39 skel: ListSkeleton<H, T>,
40
41 _extern_ty: ExternTy,
52}
53
54#[repr(C)]
57struct ListSkeleton<H, T> {
58 header: H,
59 len: usize,
60 data: [T; 0],
64}
65
66impl<T> Default for &List<T> {
67 fn default() -> Self {
68 List::empty()
69 }
70}
71
72unsafe extern "C" {
73 type ExternTy;
74}
75
76impl<H, T> RawList<H, T> {
77 #[inline(always)]
78 pub fn len(&self) -> usize {
79 self.skel.len
80 }
81
82 #[inline(always)]
83 pub fn as_slice(&self) -> &[T] {
84 self
85 }
86
87 #[inline]
97 pub(super) fn from_arena<'tcx>(
98 arena: &'tcx Arena<'tcx>,
99 header: H,
100 slice: &[T],
101 ) -> &'tcx RawList<H, T>
102 where
103 T: Copy,
104 {
105 if !!mem::needs_drop::<T>() {
::core::panicking::panic("assertion failed: !mem::needs_drop::<T>()")
};assert!(!mem::needs_drop::<T>());
106 if !(size_of::<T>() != 0) {
::core::panicking::panic("assertion failed: size_of::<T>() != 0")
};assert!(size_of::<T>() != 0);
107 if !!slice.is_empty() {
::core::panicking::panic("assertion failed: !slice.is_empty()")
};assert!(!slice.is_empty());
108
109 let (layout, _offset) =
110 Layout::new::<ListSkeleton<H, T>>().extend(Layout::for_value::<[T]>(slice)).unwrap();
111
112 let mem = arena.dropless.alloc_raw(layout) as *mut RawList<H, T>;
113 unsafe {
114 (&raw mut (*mem).skel.header).write(header);
116
117 (&raw mut (*mem).skel.len).write(slice.len());
119
120 (&raw mut (*mem).skel.data)
122 .cast::<T>()
123 .copy_from_nonoverlapping(slice.as_ptr(), slice.len());
124
125 &*mem
126 }
127 }
128
129 #[inline(always)]
134 pub fn iter(&self) -> <&'_ RawList<H, T> as IntoIterator>::IntoIter
135 where
136 T: Copy,
137 {
138 self.into_iter()
139 }
140}
141
142impl<'a, H, T: Copy> rustc_type_ir::inherent::SliceLike for &'a RawList<H, T> {
143 type Item = T;
144
145 type IntoIter = iter::Copied<<&'a [T] as IntoIterator>::IntoIter>;
146
147 fn iter(self) -> Self::IntoIter {
148 (*self).iter()
149 }
150
151 fn as_slice(&self) -> &[Self::Item] {
152 (*self).as_slice()
153 }
154}
155
156impl<'tcx> rustc_type_ir::inherent::BoundVarKinds<TyCtxt<'tcx>>
157 for &'tcx RawList<(), crate::ty::BoundVariableKind<'tcx>>
158{
159 fn from_vars(
160 tcx: TyCtxt<'tcx>,
161 iter: impl IntoIterator<Item = crate::ty::BoundVariableKind<'tcx>>,
162 ) -> Self {
163 tcx.mk_bound_variable_kinds_from_iter(iter.into_iter())
164 }
165}
166
167macro_rules! impl_list_empty {
168 ($header_ty:ty, $header_init:expr) => {
169 impl<T> RawList<$header_ty, T> {
170 #[inline(always)]
172 pub fn empty<'a>() -> &'a RawList<$header_ty, T> {
173 #[repr(align(64))]
174 struct MaxAlign;
175
176 static EMPTY: ListSkeleton<$header_ty, MaxAlign> =
177 ListSkeleton { header: $header_init, len: 0, data: [] };
178
179 assert!(align_of::<T>() <= align_of::<MaxAlign>());
180
181 unsafe { &*((&raw const EMPTY) as *const RawList<$header_ty, T>) }
184 }
185 }
186 };
187}
188
189impl<T> RawList<(), T> {
#[inline(always)]
pub fn empty<'a>() -> &'a RawList<(), T> {
#[repr(align(64))]
struct MaxAlign;
static EMPTY: ListSkeleton<(), MaxAlign> =
ListSkeleton { header: (), len: 0, data: [] };
if !(align_of::<T>() <= align_of::<MaxAlign>()) {
::core::panicking::panic("assertion failed: align_of::<T>() <= align_of::<MaxAlign>()")
};
unsafe { &*((&raw const EMPTY) as *const RawList<(), T>) }
}
}impl_list_empty!((), ());
190
191impl<H, T: fmt::Debug> fmt::Debug for RawList<H, T> {
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 (**self).fmt(f)
194 }
195}
196
197impl<H, S: Encoder, T: Encodable<S>> Encodable<S> for RawList<H, T> {
198 #[inline]
199 fn encode(&self, s: &mut S) {
200 (**self).encode(s);
201 }
202}
203
204impl<H, T: PartialEq> PartialEq for RawList<H, T> {
205 #[inline]
206 fn eq(&self, other: &RawList<H, T>) -> bool {
207 ptr::eq(self, other)
210 }
211}
212
213impl<H, T: Eq> Eq for RawList<H, T> {}
214
215impl<H, T> Ord for RawList<H, T>
216where
217 T: Ord,
218{
219 fn cmp(&self, other: &RawList<H, T>) -> Ordering {
220 if self == other { Ordering::Equal } else { <[T] as Ord>::cmp(&**self, &**other) }
223 }
224}
225
226impl<H, T> PartialOrd for RawList<H, T>
227where
228 T: PartialOrd,
229{
230 fn partial_cmp(&self, other: &RawList<H, T>) -> Option<Ordering> {
231 if self == other {
234 Some(Ordering::Equal)
235 } else {
236 <[T] as PartialOrd>::partial_cmp(&**self, &**other)
237 }
238 }
239}
240
241impl<Hdr, T> Hash for RawList<Hdr, T> {
242 #[inline]
243 fn hash<H: Hasher>(&self, s: &mut H) {
244 ptr::from_ref(self).hash(s)
247 }
248}
249
250impl<H, T> Deref for RawList<H, T> {
251 type Target = [T];
252 #[inline(always)]
253 fn deref(&self) -> &[T] {
254 self.as_ref()
255 }
256}
257
258impl<H, T> AsRef<[T]> for RawList<H, T> {
259 #[inline(always)]
260 fn as_ref(&self) -> &[T] {
261 let data_ptr = (&raw const self.skel.data).cast::<T>();
262 unsafe { slice::from_raw_parts(data_ptr, self.skel.len) }
267 }
268}
269
270impl<'a, H, T: Copy> IntoIterator for &'a RawList<H, T> {
271 type Item = T;
272 type IntoIter = iter::Copied<<&'a [T] as IntoIterator>::IntoIter>;
273 #[inline(always)]
274 fn into_iter(self) -> Self::IntoIter {
275 self[..].iter().copied()
276 }
277}
278
279unsafe impl<H: Sync, T: Sync> Sync for RawList<H, T> {}
280
281unsafe impl<H: DynSync, T: DynSync> DynSync for RawList<H, T> {}
283
284unsafe impl<H, T> Aligned for RawList<H, T> {
289 const ALIGN: mem::Alignment = align_of::<ListSkeleton<H, T>>();
290}
291
292pub type ListWithCachedTypeInfo<T> = RawList<TypeInfo, T>;
295
296impl<T> ListWithCachedTypeInfo<T> {
297 #[inline(always)]
298 pub fn flags(&self) -> TypeFlags {
299 self.skel.header.flags
300 }
301
302 #[inline(always)]
303 pub fn outer_exclusive_binder(&self) -> DebruijnIndex {
304 self.skel.header.outer_exclusive_binder
305 }
306}
307
308impl<T> RawList<TypeInfo, T> {
#[inline(always)]
pub fn empty<'a>() -> &'a RawList<TypeInfo, T> {
#[repr(align(64))]
struct MaxAlign;
static EMPTY: ListSkeleton<TypeInfo, MaxAlign> =
ListSkeleton { header: TypeInfo::empty(), len: 0, data: [] };
if !(align_of::<T>() <= align_of::<MaxAlign>()) {
::core::panicking::panic("assertion failed: align_of::<T>() <= align_of::<MaxAlign>()")
};
unsafe { &*((&raw const EMPTY) as *const RawList<TypeInfo, T>) }
}
}impl_list_empty!(TypeInfo, TypeInfo::empty());
309
310#[repr(C)]
312#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TypeInfo {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "TypeInfo",
"flags", &self.flags, "outer_exclusive_binder",
&&self.outer_exclusive_binder)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for TypeInfo {
#[inline]
fn clone(&self) -> TypeInfo {
let _: ::core::clone::AssertParamIsClone<TypeFlags>;
let _: ::core::clone::AssertParamIsClone<DebruijnIndex>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TypeInfo { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for TypeInfo {
#[inline]
fn eq(&self, other: &TypeInfo) -> bool {
self.flags == other.flags &&
self.outer_exclusive_binder == other.outer_exclusive_binder
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for TypeInfo {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<TypeFlags>;
let _: ::core::cmp::AssertParamIsEq<DebruijnIndex>;
}
}Eq)]
313pub struct TypeInfo {
314 flags: TypeFlags,
315 outer_exclusive_binder: DebruijnIndex,
316}
317
318impl TypeInfo {
319 const fn empty() -> Self {
320 Self { flags: TypeFlags::empty(), outer_exclusive_binder: super::INNERMOST }
321 }
322}
323
324impl<'tcx> From<FlagComputation<TyCtxt<'tcx>>> for TypeInfo {
325 fn from(computation: FlagComputation<TyCtxt<'tcx>>) -> TypeInfo {
326 TypeInfo {
327 flags: computation.flags,
328 outer_exclusive_binder: computation.outer_exclusive_binder,
329 }
330 }
331}
332
333#[cfg(target_pointer_width = "64")]
334mod size_asserts {
335 use rustc_data_structures::static_assert_size;
336
337 use super::*;
338 const _: [(); 8] = [(); ::std::mem::size_of::<&List<u32>>()];static_assert_size!(&List<u32>, 8); const _: [(); 8] = [(); ::std::mem::size_of::<&RawList<u8, u32>>()];static_assert_size!(&RawList<u8, u32>, 8); }