use std::any; use std::fmt::{Debug, Display, Error, Formatter}; use std::marker::PhantomData; use serde::{Deserialize, Serialize}; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Id { inner: V, _phantom: PhantomData, } impl Id { /// Creates a new `Id`. /// /// Using a distinct type like `Id` instead of `usize` helps us avoid mixing plain integers /// with identifiers. #[inline] pub const fn new(inner: V) -> Self { Self { inner, _phantom: PhantomData, } } } impl Id where V: Copy, { /// Returns the inner value. /// /// This requires an explicit call, ensuring we only use the raw value when intended. #[inline] pub const fn get(self) -> V { self.inner } } impl Debug for Id where V: Display, { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { let marker = any::type_name::().split("::").last().expect("not empty"); write!(f, "{marker}Id({})", self.inner) } } impl Serialize for Id where V: Serialize, { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { self.inner.serialize(serializer) } } impl<'de, M, V> Deserialize<'de> for Id where V: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { let inner = V::deserialize(deserializer)?; Ok(Self { inner, _phantom: PhantomData, }) } } pub mod marker { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Var; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Decl; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Block; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Module; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Overlay; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct File; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct VirtualPath; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Span; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Reg; } pub type VarId = Id; pub type DeclId = Id; pub type BlockId = Id; pub type ModuleId = Id; pub type OverlayId = Id; pub type FileId = Id; pub type VirtualPathId = Id; pub type SpanId = Id; /// An ID for an [IR](crate::ir) register. /// /// `%n` is a common shorthand for `RegId(n)`. /// /// Note: `%0` is allocated with the block input at the beginning of a compiled block. pub type RegId = Id; impl Display for RegId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "%{}", self.get()) } }