use std::{fmt, hash::Hash}; use intern::{Interned, InternedRef, impl_internable}; use macros::GenericTypeVisitable; use rustc_type_ir::GenericTypeVisitable; use crate::{ MemoryMap, next_solver::{Ty, impl_stored_interned}, }; #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct Allocation<'db> { interned: InternedRef<'db, AllocationInterned>, } impl<'db> Allocation<'db> { pub fn new(data: AllocationData<'db>) -> Self { let data = unsafe { std::mem::transmute::, AllocationData<'static>>(data) }; Self { interned: Interned::new_gc(AllocationInterned(data)) } } } impl<'db> std::ops::Deref for Allocation<'db> { type Target = AllocationData<'db>; #[inline] fn deref(&self) -> &Self::Target { let inner = &self.interned.0; unsafe { std::mem::transmute::<&AllocationData<'static>, &AllocationData<'db>>(inner) } } } impl<'db, V: super::WorldExposer> GenericTypeVisitable for Allocation<'db> { fn generic_visit_with(&self, visitor: &mut V) { if visitor.on_interned(self.interned).is_continue() { (**self).generic_visit_with(visitor); } } } impl fmt::Debug for Allocation<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let AllocationData { ty, memory, memory_map } = &**self; f.debug_struct("Allocation") .field("ty", ty) .field("memory", memory) .field("memory_map", memory_map) .finish() } } #[derive(PartialEq, Eq, Hash, GenericTypeVisitable)] pub(super) struct AllocationInterned(AllocationData<'static>); #[derive(Debug, PartialEq, Eq, GenericTypeVisitable)] pub struct AllocationData<'db> { pub ty: Ty<'db>, pub memory: Box<[u8]>, pub memory_map: MemoryMap<'db>, } impl<'db> Hash for AllocationData<'db> { fn hash(&self, state: &mut H) { let Self { ty, memory, memory_map: _ } = self; ty.hash(state); memory.hash(state); } } impl_internable!(gc; AllocationInterned); impl_stored_interned!(AllocationInterned, Allocation, StoredAllocation);