You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: free_vars.rs
    path of file: ./repos/nickel/core/src/transform
    
    the code of the file until where you have to start completion: //! Annotate recursive record fields with the intersection of the set of their free variables and
//! the fields of the record. This way, we can track dependencies between recursive fields, which
//! make it possible in particular to avoid potential memory leaks by providing only references to
//! the recursive fields that actually appear in the definition of each field when computing the
//! fixpoint.
use crate::{
    identifier::Ident,
    term::pattern::*,
    term::{
        record::{Field, FieldDeps, RecordDeps},
        IndexMap, RichTerm, SharedTerm, StrChunk, Term,
    },
    typ::{RecordRowF, RecordRows, RecordRowsF, Type, TypeF},
};

use std::collections::HashSet;

/// Apply the full free var transformation on a term.
pub fn transform(rt: &mut RichTerm) {
    rt.collect_free_vars(&mut HashSet::new())
}

pub trait CollectFreeVars {
    /// Collect the free variables of a term or type inside the provided hashset. Doing so, fill
    /// the recursive record dependencies data accordingly.
    fn collect_free_vars(&mut self, working_set: &mut HashSet<Ident>);
}

impl CollectFreeVars for RichTerm {
    fn collect_free_vars(&mut self, free_vars: &mut HashSet<Ident>) {
        match SharedTerm::make_mut(&mut self.term) {
            Term::Var(id) => {
                free_vars.insert(id.ident());
            }
            Term::ParseError(_)
            | Term::RuntimeError(_)
            | Term::Null
            | Term::Bool(_)
            | Term::Num(_)
            | Term::Str(_)
            | Term::Lbl(_)
            | Term::SealingKey(_)
            | Term::Enum(_)
            | Term::Import(_)
            | Term::ResolvedImport(_) => (),
            Term::Fun(id, t) => {
                let mut fresh = HashSet::new();

                t.collect_free_vars(&mut fresh);
                fresh.remove(&id.ident());

                free_vars.extend(fresh);
            }
            Term::FunPattern(pat, body) => {
                let mut fresh = HashSet::new();

                body.collect_free_vars(&mut fresh);
                pat.remove_bindings(&mut fresh);

                free_vars.extend(fresh);
            }
            Term::Let(id, t1, t2, attrs) => {
                let mut fresh = HashSet::new();

                if attrs.rec {
                    t1.collect_free_vars(&mut fresh);
                } else {
                    t1.collect_free_vars(free_vars);
                }

                t2.collect_free_vars(&mut fresh);
                fresh.remove(&id.ident());

                free_vars.extend(fresh);
            }
            Term::LetPattern(pat, t1, t2) => {
                let mut fresh = HashSet::new();

                t1.collect_free_vars(free_vars);
                t2.collect_free_vars(&mut fresh);
                pat.remove_bindings(&mut fresh);

                free_vars.extend(fresh);
            }
            Term::App(t1, t2) | Term::Op2(_, t1, t2) => {
                t1.collect_free_vars(free_vars);
                t2.collect_free_vars(free_vars);
            }
            Term::Match(data) => {
                for (pat, branch) in data.branches.iter_mut() {
                    let mut fresh = HashSet::new();

                    branch.collect_free_vars(&mut fresh);
                    pat.remove_bindings(&mut fresh);

                    free_vars.extend(fresh);
                }

                if let Some(default) = &mut data.default {
                    default.collect_free_vars(free_vars);
                }
            }
            Term::Op1(_, t) | Term::Sealed(_, t, _) | Term::EnumVariant { arg: t, .. } => {
                t.collect_free_vars(free_vars)
            }
            Term::OpN(_, ts) => {
                for t in ts {
                    t.collect_free_vars(free_vars);
                }
            }
            Term::Record(record) => {
                for t in record.fields.values_mut() {
                    t.collect_free_vars(free_vars);
                }
            }
            Term::RecRecord(record, dyn_fields, deps) => {
                let rec_fields: HashSet<Ident> =
                    record.fields.keys().map(|id| id.ident()).collect();
                let mut fresh = HashSet::new();
                let mut new_deps = RecordDeps {
                    stat_fields: IndexMap::with_capacity(record.fields.len()),
                    dyn_fields: Vec::with_capacity(dyn_fields.len()),
                };

                for (id, t) in record.fields.iter_mut() {
                    fresh.clear();

                    t.collect_free_vars(&mut fresh);
                    new_deps
                        .stat_fields
                        .insert(id.ident(), FieldDeps::from(&fresh & &rec_fields));

                    free_vars.extend(&fresh - &rec_fields);
                }
                for (t1, t2) in dyn_fields.iter_mut() {
                    fresh.clear();

                    // Currently, the identifier part of a dynamic definition i
    
    fn collect_free_vars(&mut self, free_vars: &mut HashSet<Ident>) {
        match SharedTerm::make_mut(&mut self.term) {
            Term::Var(id) => {
                free_vars.insert(id.ident());
            }
            Term::ParseError(_)
            | Term::RuntimeError(_)
            | Term::Null
            | Term::Bool(_)
            | Term::Num(_)
            | Term::Str(_)
            | Term::Lbl(_)
            | Term::SealingKey(_)
            | Term::Enum(_)
            | Term::Import(_)
            | Term::ResolvedImport(_) => (),
            Term::Fun(id, t) => {
                let mut fresh = HashSet::new();

                t.collect_free_vars(&mut fresh);
                fresh.remove(&id.ident());

                free_vars.extend(fresh);
            }
            Term::FunPattern(pat, body) => {
                let mut fresh = HashSet::new();

                body.collect_free_vars(&mut fresh);
                pat.remove_bindings(&mut fresh);

                free_vars.extend(fresh);
            }
            Term::Let(id, t1, t2, attrs) => {
                let mut fresh = HashSet::new();

                if attrs.rec {
                    t1.collect_free_vars(&mut fresh);
                } else {
                    t1.collect_free_vars(free_vars);
                }

                t2.collect_free_vars(&mut fresh);
                fresh.remove(&id.ident());

                free_vars.extend(fresh);
            }
            Term::LetPattern(pat, t1, t2) => {
                let mut fresh = HashSet::new();

                t1.collect_free_vars(free_vars);
                t2.collect_free_vars(&mut fresh);
                pat.remove_bindings(&mut fresh);

                free_vars.extend(fresh);
            }
            Term::App(t1, t2) | Term::Op2(_, t1, t2) => {
                t1.collect_free_vars(free_vars);
                t2.collect_free_vars(free_vars);
            }
            Term::Match(data) => {
                for (pat, branch) in data.branches.iter_mut() {
                    let mut fresh = HashSet::new();

                    branch.collect_free_vars(&mut fresh);
                    pat.remove_bindings(&mut fresh);

                    free_vars.extend(fresh);
                }

                if let Some(default) = &mut data.default {
                    default.collect_free_vars(free_vars);
                }
            }
            Term::Op1(_, t) | Term::Sealed(_, t, _) | Term::EnumVariant { arg: t, .. } => {
                t.collect_free_vars(free_vars)
            }
            Term::OpN(_, ts) => {
                for t in ts {
                    t.collect_free_vars(free_vars);
                }
            }
            Term::Record(record) => {
                for t in record.fields.values_mut() {
                    t.collect_free_vars(free_vars);
                }
            }
            Term::RecRecord(record, dyn_fields, deps) => {
                let rec_fields: HashSet<Ident> =
                    record.fields.keys().map(|id| id.ident()).collect();
                let mut fresh = HashSet::new();
                let mut new_deps = RecordDeps {
                    stat_fields: IndexMap::with_capacity(record.fields.len()),
                    dyn_fields: Vec::with_capacity(dyn_fields.len()),
                };

                for (id, t) in record.fields.iter_mut() {
                    fresh.clear();

                    t.collect_free_vars(&mut fresh);
                    new_deps
                        .stat_fields
                        .insert(id.ident(), FieldDeps::from(&fresh & &rec_fields));

                    free_vars.extend(&fresh - &rec_fields);
                }
                for (t1, t2) in dyn_fields.iter_mut() {
                    fresh.clear();

                    // Currently, the identifier part of a dynamic definition is not recursive, i.e.
                    // one can't write `{foo = "hey", "%{foo}" = 5}`. Hence, we add their free
                    // variables directly in the final set without taking them into account for
                    // recursive dependencies.
                    t1.collect_free_vars(free_vars);
                    t2.collect_free_vars(&mut fresh);
                    new_deps
                        .dyn_fields
                        .push(FieldDeps::from(&fresh & &rec_fields));

                    free_vars.extend(&fresh - &rec_fields);
                }

                // Even if deps were previously filled (it shouldn't), we had to recompute the free
                // variables anyway for the nodes higher up, because deps alone is not sufficient to
                // reconstruct the full set of free variables. At this point, we override it in any
                // case.
                *deps = Some(new_deps);
            }
            Term::Array(ts, _) => {
                for t in ts.make_mut().iter_mut() {
                    t.collect_free_vars(free_vars);
                }
            }
            Term::StrChunks(chunks) => {
                for chunk in chunks {
                    if let StrChunk::Expr(t, _) = chunk {
                        t.collect_free_vars(free_vars)
                    }
                }
            }
            Term::Annotated(annot, t) => {
                for ctr in annot.iter_mut() {
                    ctr.typ.collect_free_vars(free_vars)
                }

                t.collect_free_vars(free_vars);
            }
            Term::Type(ty) => {
                ty.collect_free_vars(free_vars);
            }
            Term::Closure(_) => {
                unreachable!("should never see closures at the transformation stage");
            }
        }
    }