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