MCPcopy Create free account
hub / github.com/argumentcomputer/ix / build_collapse_const_map

Function build_collapse_const_map

crates/ffi/src/lean_env.rs:262–322  ·  view source on GitHub ↗

Build the `B → A` rename map for an alpha-collapsed mutual block. When two primary inductives (e.g. `A` and `B`) compile to the same canonical address, the original Lean env still emits separate `B`/`B.below`/`B.rec`/`B.b`/... declarations whose bodies reference `A`/`B` as distinct names. The decompiled (canonical) form, however, has those references collapsed onto a single representative — typic

(
  all: &[Name],
  env: &Env,
  stt: &ix_compile::compile::CompileState,
)

Source from the content-addressed store, hash-verified

260/// representatives so [`const_alpha_eq_with_perm`] can compare the two
261/// sides structurally.
262fn build_collapse_const_map(
263 all: &[Name],
264 env: &Env,
265 stt: &ix_compile::compile::CompileState,
266) -> FxHashMap<Name, Name> {
267 use ix_common::env::ConstantInfo as LeanCI;
268 let mut map: FxHashMap<Name, Name> = FxHashMap::default();
269 // Group primary members by canonical address; the first member with a
270 // given address is the representative.
271 let mut rep_by_addr: FxHashMap<ix_common::address::Address, &Name> =
272 FxHashMap::default();
273 for member in all {
274 let Some(addr) = stt.resolve_addr(member) else {
275 continue;
276 };
277 rep_by_addr.entry(addr).or_insert(member);
278 }
279 for member in all {
280 let Some(addr) = stt.resolve_addr(member) else {
281 continue;
282 };
283 let Some(&rep) = rep_by_addr.get(&addr) else {
284 continue;
285 };
286 if rep == member {
287 continue;
288 }
289 map.insert(member.clone(), rep.clone());
290 // Derived names: `.rec`, `.below`, `.brecOn`, `.brecOn.go`,
291 // `.brecOn.eq`, `.casesOn`, `.recOn`.
292 for suffix in ["rec", "below", "brecOn", "casesOn", "recOn"] {
293 let from = Name::str(member.clone(), suffix.to_string());
294 let to = Name::str(rep.clone(), suffix.to_string());
295 map.insert(from, to);
296 }
297 for suffix in ["go", "eq"] {
298 let from = Name::str(
299 Name::str(member.clone(), "brecOn".to_string()),
300 suffix.to_string(),
301 );
302 let to = Name::str(
303 Name::str(rep.clone(), "brecOn".to_string()),
304 suffix.to_string(),
305 );
306 map.insert(from, to);
307 }
308 // Constructors: positional mapping. Both members are alpha-collapsed,
309 // so they have the same number of constructors in the same order.
310 if let (Some(LeanCI::InductInfo(m_ind)), Some(LeanCI::InductInfo(r_ind))) =
311 (env.get(member).as_deref(), env.get(rep).as_deref())
312 && m_ind.ctors.len() == r_ind.ctors.len()
313 {
314 for (m_ctor, r_ctor) in m_ind.ctors.iter().zip(r_ind.ctors.iter()) {
315 if m_ctor != r_ctor {
316 map.insert(m_ctor.clone(), r_ctor.clone());
317 }
318 }
319 }

Callers 1

build_aux_perm_ctxFunction · 0.85

Calls 7

resolve_addrMethod · 0.80
entryMethod · 0.80
getMethod · 0.45
insertMethod · 0.45
cloneMethod · 0.45
lenMethod · 0.45
iterMethod · 0.45

Tested by

no test coverage detected