Builds a [`RefGraph`] from a Lean [`Env`] by collecting all constant references in parallel. For each constant, extracts the set of names it references (from types, values, constructors, and recursor rules), then assembles both the forward and reverse edge maps.
(env: &Env)
| 48 | /// For each constant, extracts the set of names it references (from types, values, constructors, |
| 49 | /// and recursor rules), then assembles both the forward and reverse edge maps. |
| 50 | /// Everything the compile-env setup needs from a whole-env pass: the |
| 51 | /// reference graph, the immediately-ungrounded set (before transitive |
| 52 | /// proliferation), and the inductive mutual-block groups |
| 53 | /// (`all[0] → all`, for flag validation). |
| 54 | pub struct SetupScan { |
| 55 | pub graph: RefGraph, |
| 56 | pub immediate_ungrounded: FxHashMap<Name, crate::ground::GroundError>, |
| 57 | pub ind_groups: FxHashMap<Name, Vec<Name>>, |
| 58 | } |
| 59 | |
| 60 | /// Fused whole-env setup pass: one decode per constant feeding the ref |
| 61 | /// graph, the groundedness check, and inductive-group collection. |
| 62 | /// One pass instead of separate `build_ref_graph` / |
| 63 | /// `ground_consts`' scan, `validate_lean_ind_flags`' scan) — under |
| 64 | /// (the compile path'''s default) decodes a constant per access, so |
| 65 | /// visiting the whole env once instead of three times cuts the setup |
| 66 | /// decode count to a third. Outputs are identical to the separate passes. |
| 67 | pub fn setup_scan(env: &Env) -> SetupScan { |
| 68 | #[derive(Default)] |
| 69 | struct Acc { |
| 70 | out_refs: RefMap, |
| 71 | in_refs: RefMap, |
| 72 | ungrounded: FxHashMap<Name, crate::ground::GroundError>, |
| 73 | ind_groups: FxHashMap<Name, Vec<Name>>, |
| 74 | } |
| 75 | |
| 76 | let names: Vec<&Name> = env.keys().collect(); |
| 77 | let acc = names |
| 78 | .into_par_iter() |
| 79 | .filter_map(|name| { |
| 80 | let constant = env.get(name)?; |
| 81 | let deps = get_constant_info_references(&constant); |
| 82 | let mut acc = Acc { |
| 83 | in_refs: mk_in_refs(name, &deps), |
| 84 | out_refs: RefMap::from_iter([(name.clone(), deps)]), |
| 85 | ..Acc::default() |
| 86 | }; |
| 87 | if let Err(err) = crate::ground::ground_const_check(&constant, env) { |
| 88 | acc.ungrounded.insert(name.clone(), err); |
| 89 | } |
| 90 | // Members of one mutual family share the same `all`, so |
| 91 | // first-wins insertion is value-identical regardless of which |
| 92 | // member lands first. |
| 93 | if let ConstantInfo::InductInfo(v) = &*constant |
| 94 | && let Some(first) = v.all.first() |
| 95 | { |
| 96 | acc.ind_groups.entry(first.clone()).or_insert_with(|| v.all.clone()); |
| 97 | } |
| 98 | Some(acc) |
| 99 | }) |
| 100 | .reduce(Acc::default, |mut l, r| { |
| 101 | l.out_refs = merge_ref_maps(l.out_refs, r.out_refs); |