Skip to main content

luaur_analysis/methods/
data_flow_graph_builder_join_bindings.rs

1use crate::records::data_flow_graph_builder::DataFlowGraphBuilder;
2use crate::records::dfg_scope::DfgScope;
3use crate::records::symbol::Symbol;
4use crate::type_aliases::def_id_def::DefId;
5use alloc::vec::Vec;
6
7impl DataFlowGraphBuilder {
8    /// `void DataFlowGraphBuilder::joinBindings(...)`.
9    ///
10    /// Same borrow-safety concern as [`join_props`](DataFlowGraphBuilder::join_props):
11    /// the `while`-loop visitor calls `join(scope, scope, whileScope)`, so `p` aliases
12    /// `a`. Iterating `a.bindings` while `get_or_insert` mutates `p.bindings` (the same
13    /// map) is `&`/`&mut` aliasing UB. Snapshot `a`/`b` bindings into owned vectors first
14    /// so no borrow of a scope's `bindings` is held across the mutation of `p.bindings`.
15    pub fn join_bindings(&mut self, p: *mut DfgScope, a: &DfgScope, b: &DfgScope) {
16        unsafe {
17            let a_bindings: Vec<(Symbol, DefId)> =
18                a.bindings.iter().map(|(s, d)| (s.clone(), *d)).collect();
19            let b_bindings: Vec<(Symbol, DefId)> =
20                b.bindings.iter().map(|(s, d)| (s.clone(), *d)).collect();
21            let b_find = |sym: &Symbol| -> Option<DefId> {
22                b_bindings.iter().find(|(s, _)| s == sym).map(|(_, d)| *d)
23            };
24
25            for (sym, def1) in a_bindings.iter() {
26                if let Some(def2) = b_find(sym) {
27                    let phi = (*self.def_arena).phi_def_id_def_id(*def1, def2);
28                    *(*p).bindings.get_or_insert(sym.clone()) = phi;
29                } else if let Some(def2) = (*p).lookup_symbol(sym.clone()) {
30                    let phi = (*self.def_arena).phi_def_id_def_id(*def1, def2);
31                    *(*p).bindings.get_or_insert(sym.clone()) = phi;
32                }
33            }
34
35            for (sym, def1) in b_bindings.iter() {
36                if let Some(def2) = (*p).lookup_symbol(sym.clone()) {
37                    let phi = (*self.def_arena).phi_def_id_def_id(*def1, def2);
38                    *(*p).bindings.get_or_insert(sym.clone()) = phi;
39                }
40            }
41        }
42    }
43}