fn propagate_used_with()

in amzn-smt-string-transformer/src/callgraph.rs [436:504]


    fn propagate_used_with(
        &mut self,
        var: NodeId,
        cliques: &HashMap<NodeId, NodeSetData>,
    ) -> Result<(NodeSetData, AffectOk), AffectErr> {
        let nodes = self.forest.nodes().clone();
        let cur_node = match nodes.get(&var) {
            Some(n) => n,
            None => {
                // if the node is not in the callgraph, error out
                return Err(AffectErr::InvalidNode);
            }
        };

        // if already done, bail early
        if let Some(contrib) = &cur_node.data.used_with {
            return Ok((contrib.clone(), AffectOk::AlreadyDone));
        }

        // if it's in a partition we've already formed, just collect this
        if let Some(contrib) = self.get_contribs_for_var(var) {
            self.update_node_with_contribs(
                var,
                contrib.clone(),
                cur_node.data.clone(),
                GraphTraversalDir::UsedWith,
            )?;
            return Ok((contrib, AffectOk::AlreadyDone));
        }

        // now, we're tracking the literals, vars, and string functions that the current var are used WITH
        // these are all the nodes that are in cliques with the current var

        let mut contrib_vars = BTreeSet::<NodeId>::new();
        contrib_vars.insert(var);
        let mut contrib_string_fcts = HashSet::<(StringFct, StringFctArgs)>::new();
        contrib_string_fcts.insert(cur_node.data.get_string_fct_arg_pair());
        let mut contrib_string_lits: BTreeSet<String> =
            cur_node.data.string_lits_built_from.clone();

        // iterate over the cliques and collect the info from those who contain the current var
        let mut cids: Vec<&NodeId> = cliques.keys().collect::<Vec<_>>();
        cids.sort();

        for cid in cids {
            let clique = &cliques[cid];
            if clique.vars.contains(&var) {
                contrib_vars.extend(clique.vars.iter().cloned());
                contrib_string_fcts.extend(clique.string_fcts.iter().cloned());
                contrib_string_lits.extend(clique.string_lits.iter().cloned());
            }
        }

        // finally, once the data has all been collected, update the current node with the contribs
        let new_node_data = cur_node.data.clone();
        let new_nodeset_data = NodeSetData {
            vars: contrib_vars,
            string_fcts: contrib_string_fcts,
            string_lits: contrib_string_lits,
        };
        self.update_node_with_contribs(
            var,
            new_nodeset_data.clone(),
            new_node_data,
            GraphTraversalDir::UsedWith,
        )?;
        self.partitions.push(new_nodeset_data.clone());
        Ok((new_nodeset_data, AffectOk::Done))
    }