1use {
2 rustc_hash::FxBuildHasher,
3 std::{
4 borrow::Borrow,
5 fmt,
6 hash::{BuildHasher, Hash},
7 sync::RwLock,
8 },
9};
10
11pub struct Interner<T> {
12 inner: RwLock<crate::Interner<T>>,
13}
14
15impl<T> Default for Interner<T> {
16 fn default() -> Self {
17 Self::new()
18 }
19}
20
21impl<T> Interner<T> {
22 #[must_use]
25 pub const fn new() -> Self {
26 Self { inner: RwLock::new(crate::Interner::new()) }
27 }
28
29 #[expect(clippy::missing_panics_doc)]
31 pub fn len(&self) -> usize {
32 self.inner.read().unwrap().len()
33 }
34
35 pub fn is_empty(&self) -> bool {
37 self.len() == 0
38 }
39
40 pub fn insert_arena(&self, value: T) -> &mut T {
43 let inner = self.inner.write().unwrap();
44 unsafe { longer_mut(inner.insert_arena(value)) }
45 }
46}
47
48impl<T: Hash + Eq> Interner<T> {
49 #[expect(clippy::missing_panics_doc)]
51 #[must_use]
52 pub fn try_resolve<Q>(&self, value: &Q) -> Option<&T>
53 where
54 T: Borrow<Q>,
55 Q: ?Sized + Hash + Eq,
56 {
57 self.inner.read().unwrap().try_resolve(value).map(|cached| unsafe { longer(cached) })
58 }
59
60 #[expect(clippy::missing_panics_doc, clippy::readonly_write_lock)]
62 pub fn intern(&self, value: T) -> &T {
63 let hash = FxBuildHasher.hash_one(&value);
64
65 let inner = self.inner.read().unwrap();
66 if let Some(cached) = inner.try_resolve_with(&value, hash) {
67 return unsafe { longer(cached) };
68 }
69
70 drop(inner);
71 let inner = self.inner.write().unwrap();
72
73 if let Some(cached) = inner.try_resolve_with(&value, hash) {
76 return unsafe { longer(cached) };
77 }
78
79 unsafe { longer(inner.insert(hash, value)) }
80 }
81
82 #[expect(clippy::missing_panics_doc, clippy::readonly_write_lock)]
83 pub fn intern_new(&self, value: T) -> &T {
85 let hash = FxBuildHasher.hash_one(&value);
86 let inner = self.inner.write().unwrap();
87 unsafe { longer(inner.insert(hash, value)) }
88 }
89
90 pub fn intern_ref_unique(&self, value: &'static T) {
96 self.inner.write().unwrap().intern_ref_unique(value)
97 }
98}
99
100impl<T: fmt::Debug> fmt::Debug for Interner<T> {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 let Ok(inner) = self.inner.try_read() else {
103 return f.debug_set().finish_non_exhaustive();
104 };
105 inner.fmt(f)
106 }
107}
108
109unsafe fn longer<'b, T>(short: &T) -> &'b T {
110 unsafe { std::mem::transmute(short) }
111}
112
113unsafe fn longer_mut<'b, T>(short: &mut T) -> &'b mut T {
114 unsafe { std::mem::transmute(short) }
115}
116
117unsafe impl<T: Send> Send for Interner<T> {}
118unsafe impl<T: Sync> Sync for Interner<T> {}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 #[test]
124 fn addr() {
125 static INTERNER: Interner<i32> = Interner::new();
126
127 let a1: *const _ = INTERNER.intern(1);
128 let b1: *const _ = INTERNER.intern(1);
129 INTERNER.intern(2);
130
131 assert!(INTERNER.try_resolve(&1) == Some(&1));
132
133 assert_eq!(a1.addr(), b1.addr());
134 }
135 #[test]
136 fn recursive() {
137 #[derive(Debug, PartialEq, Eq, Hash)]
138 enum Type<'tcx> {
139 Int,
140 Array(&'tcx Type<'tcx>),
141 }
142
143 let interner = Interner::new();
144 let int = interner.intern(Type::Int);
145 let array = interner.intern(Type::Array(int));
146 println!("{array:?}");
147 }
148 #[test]
149 fn insert_arena() {
150 let interner = Interner::new();
151 let a1: *const _ = interner.insert_arena(1);
152 let a2: *const _ = interner.intern(1);
153 assert_ne!(a1.addr(), a2.addr());
154 }
155 #[test]
156 fn test_grow() {
157 let interner = Interner::new();
158 let one: *const _ = interner.intern(1);
159
160 for i in 2..1000 {
162 interner.intern(i);
163 }
164
165 let one2: *const _ = interner.intern(1);
166 assert_eq!(one.addr(), one2.addr())
167 }
168 #[test]
169 fn test_intern_ref_unique() {
170 let interner = Interner::new();
171
172 static ONE: i32 = 1;
173 let a1 = &ONE;
174
175 interner.intern_ref_unique(a1);
176 let a2: *const _ = interner.intern(1);
177 assert_eq!((a1 as *const i32).addr(), a2.addr());
178 }
179}