fn count_symbols(expr: &Expr, usage: &mut FnvHashMap<Symbol, SymbolTracker>) {
    match expr.kind {
        For { ref func, .. }
        | Iterate {
            update_func: ref func,
            ..
        }
        | Sort {
            cmpfunc: ref func, ..
        }
        | Apply { ref func, .. } => {
            // Mark all symbols seen so far as "in a loop"
            for value in usage.values_mut() {
                value.loop_nest += 1;
            }

            count_symbols(func, usage);

            for value in usage.values_mut() {
                value.loop_nest -= 1;
            }
        }
        Let { ref name, .. } => {
            debug_assert!(!usage.contains_key(name));
            let _ = usage.insert(name.clone(), SymbolTracker::default());
        }
        Ident(ref symbol) => {
            if let Some(ref mut tracker) = usage.get_mut(symbol) {
                if tracker.loop_nest == 0 {
                    tracker.count += 1;
                } else {
                    // Used in a loop!
                    tracker.count += 3;
                }
            }
        }
        _ => (),
    };

    // Recurse into children - skip functions that expressions may call repeatedly. We handled
    // those already.
    for child in expr.children() {
        match child.kind {
            Lambda { .. } => (),
            _ => count_symbols(child, usage),
        }
    }
}
Count the occurances of each symbol defined by a `Let` statement.
weld/src/optimizer/transforms/inliner.rs