(constant_info: &ConstantInfo)
| 98 | Some(acc) |
| 99 | }) |
| 100 | .reduce(Acc::default, |mut l, r| { |
| 101 | l.out_refs = merge_ref_maps(l.out_refs, r.out_refs); |
| 102 | l.in_refs = merge_ref_maps(l.in_refs, r.in_refs); |
| 103 | l.ungrounded.extend(r.ungrounded); |
| 104 | for (k, v) in r.ind_groups { |
| 105 | l.ind_groups.entry(k).or_insert(v); |
| 106 | } |
| 107 | l |
| 108 | }); |
| 109 | |
| 110 | SetupScan { |
| 111 | graph: RefGraph { out_refs: acc.out_refs, in_refs: acc.in_refs }, |
| 112 | immediate_ungrounded: acc.ungrounded, |
| 113 | ind_groups: acc.ind_groups, |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | /// `name → {name} ∪ deps`-shaped reverse-edge fragment for one |
| 118 | /// constant, merged across the parallel scan. |
| 119 | fn mk_in_refs(name: &Name, deps: &NameSet) -> RefMap { |
| 120 | let mut in_refs = RefMap::from_iter([(name.clone(), NameSet::default())]); |
| 121 | for dep in deps { |
| 122 | match in_refs.entry(dep.clone()) { |
| 123 | Entry::Vacant(entry) => { |
| 124 | entry.insert(NameSet::from_iter([name.clone()])); |
| 125 | }, |
| 126 | Entry::Occupied(mut entry) => { |
| 127 | entry.get_mut().insert(name.clone()); |
| 128 | }, |
| 129 | } |
| 130 | } |
| 131 | in_refs |
| 132 | } |
| 133 | |
| 134 | /// Size-aware map union (drain the smaller side into the bigger). |
| 135 | fn merge_ref_maps(l: RefMap, r: RefMap) -> RefMap { |
| 136 | let (smaller, mut bigger) = if l.len() < r.len() { (l, r) } else { (r, l) }; |
| 137 | for (name, set) in smaller { |
| 138 | match bigger.entry(name) { |
no test coverage detected