hax_rust_engine/ast/identifiers/global_id/
generated_names.rs1#[allow(
18 unused,
19 non_snake_case,
20 rustdoc::broken_intra_doc_links,
21 missing_docs,
22 clippy::module_inception,
23 unused_qualifications,
24 non_upper_case_globals
25)]
26pub mod root {
27 include!("generated.rs");
28}
29
30pub mod codegen {
35 use itertools::*;
36 use std::iter;
37
38 use crate::ast::Item;
39 use crate::ast::identifiers::{
40 GlobalId,
41 global_id::{ExplicitDefId, compact_serialization},
42 };
43 use hax_frontend_exporter::DefKind;
44
45 use std::collections::{HashMap, HashSet};
46
47 fn rename_krate(def_id: &mut ExplicitDefId) {
49 if def_id.def_id.krate == "hax_engine_names" {
50 def_id.rename_krate("rust_primitives");
51 }
52 }
53
54 fn collect_def_ids(items: Vec<Item>) -> Vec<ExplicitDefId> {
56 #[derive(Default)]
57 struct DefIdCollector(HashSet<ExplicitDefId>);
58 use crate::ast::visitors::*;
59 impl AstVisitor for DefIdCollector {
60 fn visit_global_id(&mut self, x: &GlobalId) {
61 let mut current = x.0.explicit_def_id();
62 while let Some(def_id) = current {
63 self.0.insert(def_id.clone());
64 current = def_id.parent();
65 }
66 }
67 }
68
69 let mut names: Vec<_> = DefIdCollector::default()
71 .visit_by_val(&items)
72 .0
73 .into_iter()
74 .collect();
75
76 names.iter_mut().for_each(rename_krate);
78
79 names.sort();
89 names.dedup();
90 names
91 }
92
93 fn docstring(explicit_id: &ExplicitDefId) -> String {
96 let id = &explicit_id.def_id;
97 let path = path_of_def_id(explicit_id);
98 let (parent_path, def) = match &path[..] {
99 [init @ .., last] => (init, last.clone()),
100 _ => (&[] as &[_], id.krate.to_string()),
101 };
102 let parent_path_str = format!("::{}", parent_path.join("::"));
103 let path_str = format!("::{}", path_of_def_id(explicit_id).join("::"));
104 let subject = match &id.kind {
105 DefKind::Mod => format!("module [`{path_str}`]"),
106 DefKind::Struct => format!("struct [`{path_str}`]"),
107 DefKind::Union => format!("union [`{path_str}`]"),
108 DefKind::Enum => format!("enum [`{path_str}`]"),
109 DefKind::Variant => format!("variant [`{path_str}`]"),
110 DefKind::Trait => format!("trait [`{path_str}`]"),
111 DefKind::TyAlias => format!("type alias [`{path_str}`]"),
112 DefKind::ForeignTy => format!("foreign type [`{path_str}`]"),
113 DefKind::TraitAlias => format!("trait alias [`{path_str}`]"),
114 DefKind::AssocTy => format!("associated type [`{path_str}`]"),
115 DefKind::TyParam => format!("type parameter from [`{parent_path_str}`]"),
116 DefKind::Fn => format!("function [`{path_str}`]"),
117 DefKind::Const => format!("const [`{path_str}`]"),
118 DefKind::ConstParam => format!("const parameter from [`{parent_path_str}`]"),
119 DefKind::Static { .. } => format!("static [`{path_str}`]"),
120 DefKind::Ctor { .. } => format!("constructor for [`{parent_path_str}`]"),
121 DefKind::AssocFn => format!("associated function [`{path_str}`]"),
122 DefKind::AssocConst => format!("associated constant [`{path_str}`]"),
123 DefKind::Macro { .. } => format!("macro [`{path_str}`]"),
124 DefKind::ExternCrate => format!("extern crate [`{path_str}`]"),
125 DefKind::Use => format!("use item [`{path_str}`]"),
126 DefKind::ForeignMod => format!("foreign module [`{path_str}`]"),
127 DefKind::AnonConst => return "This is an anonymous constant.".to_string(),
128 DefKind::PromotedConst | DefKind::InlineConst => {
129 format!("This is an inline const from [`{parent_path_str}`]")
130 }
131 DefKind::OpaqueTy => {
132 return format!("This is an opaque type for [`{parent_path_str}`]");
133 }
134 DefKind::Field => format!("field [`{def}`] from {parent_path_str}"),
135 DefKind::LifetimeParam => return "This is a lifetime parameter.".to_string(),
136 DefKind::GlobalAsm => return "This is a global ASM block.".to_string(),
137 DefKind::Impl { .. } => return "This is an impl block.".to_string(),
138 DefKind::Closure => return "This is a closure.".to_string(),
139 DefKind::SyntheticCoroutineBody => return "This is a coroutine body.".to_string(),
140 };
141 format!("This is the {subject}.")
142 }
143
144 fn path_of_def_id(explicit_id: &ExplicitDefId) -> Vec<String> {
146 let id = &explicit_id.def_id;
147 fn name_to_string(mut s: String) -> String {
148 if s == "_" {
149 s = "_anonymous".into();
150 };
151 if s.parse::<i32>().is_ok() {
152 s = format!("_{s}");
153 }
154 s
155 }
156 iter::once(id.krate.to_string())
157 .chain(id.path.iter().map(|item| {
158 let data = match item.data.clone() {
159 hax_frontend_exporter::DefPathItem::CrateRoot { name } => name,
160 hax_frontend_exporter::DefPathItem::TypeNs(s)
161 | hax_frontend_exporter::DefPathItem::ValueNs(s)
162 | hax_frontend_exporter::DefPathItem::MacroNs(s)
163 | hax_frontend_exporter::DefPathItem::LifetimeNs(s) => s,
164 data => format!("{data:?}"),
165 };
166 if item.disambiguator == 0 {
167 data
168 } else {
169 format!("{data}__{}", item.disambiguator)
170 }
171 }))
172 .chain(if explicit_id.is_constructor {
173 Some("Constructor".to_string())
174 } else {
175 None
176 })
177 .chain(if matches!(id.kind, DefKind::Ctor(..)) {
178 Some("ctor".to_string())
180 } else {
181 None
182 })
183 .map(name_to_string)
184 .collect()
185 }
186
187 fn generate_names_hierachy(def_ids: Vec<ExplicitDefId>) -> String {
199 #[derive(Debug, Default)]
201 struct Module {
202 attached_def_id: Option<ExplicitDefId>,
203 submodules: HashMap<String, Module>,
204 definitions: Vec<(String, ExplicitDefId)>,
205 }
206 impl Module {
207 fn new(def_ids: Vec<ExplicitDefId>) -> Self {
208 let mut node = Self::default();
209 for def_id in &def_ids {
210 node.insert(def_id);
211 }
212 for def_id in def_ids {
213 let modpath = path_of_def_id(&def_id);
214 if let Some(module) = node.find_module(&modpath) {
215 module.attached_def_id = Some(def_id.clone());
216 }
217 }
218 node
219 }
220 fn insert(&mut self, def_id: &ExplicitDefId) {
222 let fullpath = path_of_def_id(def_id);
223 let [modpath @ .., def] = &fullpath[..] else {
224 return;
225 };
226
227 let mut node = self;
228 for chunk in modpath {
229 node = node.submodules.entry(chunk.clone()).or_default();
230 }
231
232 node.definitions.push((def.clone(), def_id.clone()));
233 }
234 fn find_module(&mut self, modpath: &Vec<String>) -> Option<&mut Self> {
236 let mut node = self;
237 for chunk in modpath {
238 node = node.submodules.get_mut(chunk)?;
239 }
240 Some(node)
241 }
242 fn render(self, path: String, indexes: &HashMap<ExplicitDefId, usize>) -> String {
244 fn restriction(path: &str) -> &'static str {
246 if path.starts_with("::rust_primitives::hax::Tuple") {
251 "(in crate::ast::identifiers::global_id)"
252 } else {
253 ""
254 }
255 }
256 let Self {
257 submodules,
258 definitions,
259 attached_def_id,
260 } = self;
261 let submodules = submodules
262 .into_iter()
263 .sorted_by(|(a, _), (b, _)| a.cmp(b))
264 .map(|(name, contents)| {
265 let path = format!("{path}::{name}");
266 let restriction = restriction(&path);
267 format!(
268 r###"pub{restriction} mod {name} {{ {} }}"###,
269 contents.render(path, indexes)
270 )
271 });
272 let definitions = definitions
273 .into_iter()
274 .sorted_by(|(a, _), (b, _)| a.cmp(b))
275 .map(|(name, def_id)| {
276 let docstring = docstring(&def_id);
277 let index = indexes.get(&def_id).unwrap();
278 let restriction = restriction(&format!("{path}::{name}"));
279 format!(r###"
280 #[doc = r##"{docstring}"##]
281 pub{restriction} const {name}: crate::ast::identifiers::global_id::GlobalId = crate::ast::identifiers::global_id::GlobalId(root::INTERNED_GLOBAL_IDS[{index}]);
282 "###)
283 });
284 let docstring = attached_def_id
285 .iter()
286 .map(docstring)
287 .map(|s| format!(r###"#![doc=r##"{s}"##]"###));
288 docstring
289 .chain(iter::once("use super::root;".to_string()))
290 .chain(submodules)
291 .chain(definitions)
292 .collect::<Vec<_>>()
293 .join("\n")
294 }
295 }
296 let enumerated_def_ids = def_ids
297 .iter()
298 .cloned()
299 .enumerate()
300 .map(|(n, def_id)| (def_id, n))
301 .collect::<Vec<_>>();
302 let indexes = HashMap::from_iter(enumerated_def_ids.iter().cloned());
303 let tree = Module::new(def_ids).render(String::new(), &indexes);
304 let functions = {
305 enumerated_def_ids.iter().map(|(did, i)| {
306 let serialized = compact_serialization::serialize(did);
307 let parent = did.parent().as_ref().map(|parent| *indexes.get(parent).unwrap()).map(|parent| format!("Some(did_{parent}())")).unwrap_or("None".into());
308 format!(r###"fn did_{i}() -> ExplicitDefId {{deserialize(r##"{serialized}"##, {parent})}}"###)
309 }).collect::<Vec<_>>().join("\n")
310 };
311 let array_literal = enumerated_def_ids
312 .iter()
313 .map(|(_, i)| format!("did_{i}().into_global_id_inner()"))
314 .collect::<Vec<_>>()
315 .join(",");
316 let n = indexes.len();
317 format!(
318 r#"// This file was generated by `cargo hax into generate-rust-engine-names`.
319// To regenerate it, please use `just regenerate-names`. Under the hood, `cargo
320// hax into generate-rust-engine-names` runs the Rust engine, which in turn
321// calls `rust_engine::names::export_def_ids_to_mod`.
322
323static TABLE_AND_INTERNED_GLOBAL_IDS: (crate::interning::LazyLockNewWithValue<crate::ast::identifiers::global_id::GlobalIdInner, {n}>, [crate::interning::Interned<crate::ast::identifiers::global_id::GlobalIdInner>; {n}]) = {{
324 crate::interning::InterningTable::new_with_values(|| {{
325 use crate::ast::identifiers::global_id::ExplicitDefId;
326 use crate::ast::identifiers::global_id::compact_serialization::deserialize;
327 {functions}
328 [{array_literal}]
329 }})
330}};
331
332static INTERNED_GLOBAL_IDS: [crate::interning::Interned<crate::ast::identifiers::global_id::GlobalIdInner>; {n}] = TABLE_AND_INTERNED_GLOBAL_IDS.1;
333
334impl crate::interning::Internable for crate::ast::identifiers::global_id::GlobalIdInner {{
335 fn interning_table() -> &'static std::sync::Mutex<crate::interning::InterningTable<Self>> {{
336 &TABLE_AND_INTERNED_GLOBAL_IDS.0
337 }}
338}}
339
340{tree}
341"#
342 )
343 }
344
345 pub fn export_def_ids_to_mod(items: Vec<Item>) -> String {
347 generate_names_hierachy(collect_def_ids(items))
348 }
349}