1pub mod keys {
28 use std::marker::PhantomData;
29
30 use hir_expand::{MacroCallId, attrs::AttrId};
31 use rustc_hash::FxHashMap;
32 use syntax::{AstNode, AstPtr, ast};
33
34 use crate::{
35 BlockId, ConstId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, FieldId, FunctionId,
36 ImplId, LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitId,
37 TypeAliasId, TypeOrConstParamId, UnionId, UseId,
38 dyn_map::{DynMap, Policy},
39 };
40
41 pub type Key<K, V> = crate::dyn_map::Key<AstPtr<K>, V, AstPtrPolicy<K, V>>;
42
43 pub const BLOCK: Key<ast::BlockExpr, BlockId> = Key::new();
44 pub const FUNCTION: Key<ast::Fn, FunctionId> = Key::new();
45 pub const CONST: Key<ast::Const, ConstId> = Key::new();
46 pub const STATIC: Key<ast::Static, StaticId> = Key::new();
47 pub const TYPE_ALIAS: Key<ast::TypeAlias, TypeAliasId> = Key::new();
48 pub const IMPL: Key<ast::Impl, ImplId> = Key::new();
49 pub const EXTERN_BLOCK: Key<ast::ExternBlock, ExternBlockId> = Key::new();
50 pub const TRAIT: Key<ast::Trait, TraitId> = Key::new();
51 pub const STRUCT: Key<ast::Struct, StructId> = Key::new();
52 pub const UNION: Key<ast::Union, UnionId> = Key::new();
53 pub const ENUM: Key<ast::Enum, EnumId> = Key::new();
54 pub const EXTERN_CRATE: Key<ast::ExternCrate, ExternCrateId> = Key::new();
55 pub const USE: Key<ast::Use, UseId> = Key::new();
56
57 pub const ENUM_VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
58 pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
59 pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
60 pub const TYPE_PARAM: Key<ast::TypeParam, TypeOrConstParamId> = Key::new();
61 pub const CONST_PARAM: Key<ast::ConstParam, TypeOrConstParamId> = Key::new();
62 pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
63
64 pub const MACRO_RULES: Key<ast::MacroRules, MacroRulesId> = Key::new();
65 pub const MACRO2: Key<ast::MacroDef, Macro2Id> = Key::new();
66 pub const PROC_MACRO: Key<ast::Fn, ProcMacroId> = Key::new();
67 pub const MACRO_CALL: Key<ast::MacroCall, MacroCallId> = Key::new();
68 pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new();
69 pub const DERIVE_MACRO_CALL: Key<
70 ast::Attr,
71 (
72 AttrId,
73 MacroCallId,
74 Box<[Option<MacroCallId>]>,
75 ),
76 > = Key::new();
77
78 pub struct AstPtrPolicy<AST, ID> {
85 _phantom: PhantomData<(AST, ID)>,
86 }
87
88 impl<AST: AstNode + 'static, ID: 'static> Policy for AstPtrPolicy<AST, ID> {
89 type K = AstPtr<AST>;
90 type V = ID;
91 fn insert(map: &mut DynMap, key: AstPtr<AST>, value: ID) {
92 map.map
93 .entry::<FxHashMap<AstPtr<AST>, ID>>()
94 .or_insert_with(Default::default)
95 .insert(key, value);
96 }
97 fn get<'a>(map: &'a DynMap, key: &AstPtr<AST>) -> Option<&'a ID> {
98 map.map.get::<FxHashMap<AstPtr<AST>, ID>>()?.get(key)
99 }
100 fn is_empty(map: &DynMap) -> bool {
101 map.map.get::<FxHashMap<AstPtr<AST>, ID>>().is_none_or(|it| it.is_empty())
102 }
103 }
104}
105
106use std::{
107 hash::Hash,
108 marker::PhantomData,
109 ops::{Index, IndexMut},
110};
111
112use rustc_hash::FxHashMap;
113use stdx::anymap::Map;
114
115pub struct Key<K, V, P = (K, V)> {
116 _phantom: PhantomData<(K, V, P)>,
117}
118
119impl<K, V, P> Key<K, V, P> {
120 #[allow(
121 clippy::new_without_default,
122 reason = "this a const fn, so it can't be default yet. See <https://github.com/rust-lang/rust/issues/63065>"
123 )]
124 pub(crate) const fn new() -> Key<K, V, P> {
125 Key { _phantom: PhantomData }
126 }
127}
128
129impl<K, V, P> Copy for Key<K, V, P> {}
130
131impl<K, V, P> Clone for Key<K, V, P> {
132 fn clone(&self) -> Key<K, V, P> {
133 *self
134 }
135}
136
137pub trait Policy {
138 type K;
139 type V;
140
141 fn insert(map: &mut DynMap, key: Self::K, value: Self::V);
142 fn get<'a>(map: &'a DynMap, key: &Self::K) -> Option<&'a Self::V>;
143 fn is_empty(map: &DynMap) -> bool;
144}
145
146impl<K: Hash + Eq + 'static, V: 'static> Policy for (K, V) {
147 type K = K;
148 type V = V;
149 fn insert(map: &mut DynMap, key: K, value: V) {
150 map.map.entry::<FxHashMap<K, V>>().or_insert_with(Default::default).insert(key, value);
151 }
152 fn get<'a>(map: &'a DynMap, key: &K) -> Option<&'a V> {
153 map.map.get::<FxHashMap<K, V>>()?.get(key)
154 }
155 fn is_empty(map: &DynMap) -> bool {
156 map.map.get::<FxHashMap<K, V>>().is_none_or(|it| it.is_empty())
157 }
158}
159
160#[derive(Default)]
161pub struct DynMap {
162 pub(crate) map: Map,
163}
164
165#[repr(transparent)]
166pub struct KeyMap<KEY> {
167 map: DynMap,
168 _phantom: PhantomData<KEY>,
169}
170
171impl<P: Policy> KeyMap<Key<P::K, P::V, P>> {
172 pub fn insert(&mut self, key: P::K, value: P::V) {
173 P::insert(&mut self.map, key, value)
174 }
175 pub fn get(&self, key: &P::K) -> Option<&P::V> {
176 P::get(&self.map, key)
177 }
178
179 pub fn is_empty(&self) -> bool {
180 P::is_empty(&self.map)
181 }
182}
183
184impl<P: Policy> Index<Key<P::K, P::V, P>> for DynMap {
185 type Output = KeyMap<Key<P::K, P::V, P>>;
186 fn index(&self, _key: Key<P::K, P::V, P>) -> &Self::Output {
187 unsafe { std::mem::transmute::<&DynMap, &KeyMap<Key<P::K, P::V, P>>>(self) }
189 }
190}
191
192impl<P: Policy> IndexMut<Key<P::K, P::V, P>> for DynMap {
193 fn index_mut(&mut self, _key: Key<P::K, P::V, P>) -> &mut Self::Output {
194 unsafe { std::mem::transmute::<&mut DynMap, &mut KeyMap<Key<P::K, P::V, P>>>(self) }
196 }
197}