fn sir_param_correction_helper(
    prog: &mut SirProgram,
    func_id: FunctionId,
    env: &mut HashMap<Symbol, Type>,
    closure: &mut HashSet<Symbol>,
    visited: &mut HashSet<FunctionId>,
) {
    // this is needed for cases where params are added outside of sir_param_correction and are not
    // based on variable reads in the function (e.g. in the Iterate case);
    // and when there are loops in the call graph (also in the Iterate case)
    for name in prog.funcs[func_id].params.keys() {
        closure.insert(name.clone());
    }
    if !visited.insert(func_id) {
        return;
    }
    for (name, ty) in &prog.funcs[func_id].params {
        env.insert(name.clone(), ty.clone());
    }
    for (name, ty) in &prog.funcs[func_id].locals {
        env.insert(name.clone(), ty.clone());
    }

    // All symbols are unique, so there is no need to remove stuff from env at any point.
    for block in prog.funcs[func_id].blocks.clone() {
        let mut vars = vec![];
        for statement in &block.statements {
            vars.extend(statement.kind.children().cloned());
        }
        vars.extend(block.terminator.children().cloned());
        for var in &vars {
            if prog.funcs[func_id].locals.get(&var) == None {
                prog.funcs[func_id]
                    .params
                    .insert(var.clone(), env.get(&var).unwrap().clone());
                closure.insert(var.clone());
            }
        }
        let mut inner_closure = HashSet::new();

        // Recurse into other called functions.
        for statement in &block.statements {
            use self::StatementKind::ParallelFor;
            if let ParallelFor(ref pf) = statement.kind {
                sir_param_correction_helper(prog, pf.body, env, &mut inner_closure, visited);
            }
        }

        for var in inner_closure {
            if prog.funcs[func_id].locals.get(&var) == None {
                prog.funcs[func_id]
                    .params
                    .insert(var.clone(), env.get(&var).unwrap().clone());
                closure.insert(var.clone());
            }
        }
    }
}
Recursive helper function for sir_param_correction. `env` contains the symbol to type mappings
that have been defined previously in the program. Any symbols that need to be passed in
as closure parameters to func_id will be added to `closure` (so that `func_id`'s
callers can also add these symbols to their parameters list, if necessary).
`visited` contains functions we have already seen on the way down the function call tree,
to prevent infinite recursion when there are loops.
weld/src/sir/mod.rs