Skip to main content

mago_codex/ttype/
flags.rs

1/// Flags representing various properties of a type union.
2///
3/// This replaces 9 individual boolean fields with a compact 16-bit representation,
4/// reducing memory usage from 9 bytes to 2 bytes per TUnion instance.
5#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7pub struct UnionFlags(u16);
8
9impl UnionFlags {
10    /// Indicates the union had a template type at some point.
11    pub const HAD_TEMPLATE: UnionFlags = UnionFlags(1 << 0);
12    /// Indicates the value is passed by reference.
13    pub const BY_REFERENCE: UnionFlags = UnionFlags(1 << 1);
14    /// Indicates no references exist to this type.
15    pub const REFERENCE_FREE: UnionFlags = UnionFlags(1 << 2);
16    /// Indicates the type may be undefined due to a try block.
17    pub const POSSIBLY_UNDEFINED_FROM_TRY: UnionFlags = UnionFlags(1 << 3);
18    /// Indicates the type may be undefined.
19    pub const POSSIBLY_UNDEFINED: UnionFlags = UnionFlags(1 << 4);
20    /// Indicates nullable issues should be ignored for this type.
21    pub const IGNORE_NULLABLE_ISSUES: UnionFlags = UnionFlags(1 << 5);
22    /// Indicates falsable issues should be ignored for this type.
23    pub const IGNORE_FALSABLE_ISSUES: UnionFlags = UnionFlags(1 << 6);
24    /// Indicates the type came from a template default value.
25    pub const FROM_TEMPLATE_DEFAULT: UnionFlags = UnionFlags(1 << 7);
26    /// Indicates the type has been populated with codebase information.
27    pub const POPULATED: UnionFlags = UnionFlags(1 << 8);
28    /// Indicates the null in this union came from nullsafe short-circuit.
29    pub const NULLSAFE_NULL: UnionFlags = UnionFlags(1 << 9);
30    /// Indicates this union fills an omitted template argument that has no declared default.
31    pub const FROM_UNSPECIFIED_TEMPLATE: UnionFlags = UnionFlags(1 << 10);
32}
33
34impl UnionFlags {
35    #[inline]
36    #[must_use]
37    pub const fn empty() -> Self {
38        UnionFlags(0)
39    }
40
41    #[inline]
42    pub const fn insert(&mut self, flag: UnionFlags) {
43        self.0 |= flag.0;
44    }
45
46    #[inline]
47    pub const fn set(&mut self, flag: UnionFlags, value: bool) {
48        if value {
49            self.insert(flag);
50        } else {
51            self.0 &= !flag.0;
52        }
53    }
54
55    #[inline]
56    #[must_use]
57    pub const fn contains(self, flag: UnionFlags) -> bool {
58        (self.0 & flag.0) == flag.0
59    }
60
61    #[inline]
62    #[must_use]
63    pub const fn union(&self, other: UnionFlags) -> UnionFlags {
64        UnionFlags(self.0 | other.0)
65    }
66
67    #[inline]
68    #[must_use]
69    pub const fn intersection(&self, other: UnionFlags) -> UnionFlags {
70        UnionFlags(self.0 & other.0)
71    }
72}
73
74impl std::ops::BitAnd for UnionFlags {
75    type Output = Self;
76
77    #[inline]
78    fn bitand(self, rhs: Self) -> Self::Output {
79        UnionFlags(self.0 & rhs.0)
80    }
81}
82
83impl std::ops::Not for UnionFlags {
84    type Output = Self;
85
86    #[inline]
87    fn not(self) -> Self::Output {
88        UnionFlags(!self.0)
89    }
90}