in amzn-smt-string-transformer/src/callgraph.rs [342:413]
fn propagate_through_relnodes(
&mut self,
var: NodeId,
rel_nodes: &BTreeSet<NodeId>,
cur_data: &CallnodeData,
direction: GraphTraversalDir,
) -> Result<(NodeSetData, AffectOk), AffectErr> {
// now the work begins
// definitely take current literals and immediate neighbour nodes (in the direction specified)
// then, depending on the type of each node, recurse back
// need to keep track to detect cycles (if there is one, bail with a cycle error)
let mut contrib_vars = rel_nodes.iter().cloned().collect::<BTreeSet<_>>();
// if the nodes include the var itself, cycle detected
if contrib_vars.contains(&var) {
return Err(AffectErr::CycleDetected);
}
let mut contrib_string_fcts = HashSet::<(StringFct, StringFctArgs)>::new();
contrib_string_fcts.insert(cur_data.get_string_fct_arg_pair());
let mut contrib_string_lits = cur_data
.string_lits_built_from
.iter()
.cloned()
.collect::<BTreeSet<_>>();
let rel_nodes = rel_nodes.iter().cloned().collect::<BTreeSet<_>>();
// now actually collect the data from the relevant nodes
for node in rel_nodes {
if let Some(node) = self.forest.nodes().get(&node) {
contrib_string_fcts.insert(node.data.get_string_fct_arg_pair());
// information doesn't propagate through functions that return a Bool
if matches!(
node.data.string_fct.string_fct_return_type(),
IdentType::StringType
| IdentType::RegexStringType
| IdentType::IntType // int also requires the string chars potentially
| IdentType::ConstraintVarType
) {
let cur_ind = *node.ind();
let node_contribs_res = self.propagate_along_path(cur_ind, direction);
if let Ok((node_contribs, _)) = node_contribs_res {
contrib_vars.extend(node_contribs.vars.iter().cloned());
// check again for cycles
if contrib_vars.contains(&var) {
return Err(AffectErr::CycleDetected);
}
contrib_string_fcts.extend(node_contribs.string_fcts);
contrib_string_lits.extend(node_contribs.string_lits);
} else {
// if there was an error in processing the affects of rel_node, bail with this error
return node_contribs_res;
}
}
} else {
// rel_node is not found in the callgraph
return Err(AffectErr::InvalidNode);
}
}
// finally, once the data has all been collected, update the current node with the contribs
let new_node_data = cur_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, direction)?;
Ok((new_nodeset_data, AffectOk::Done))
}