//! Upvar (closure capture) collection from cross-body HIR uses of `Res::Local`s.

use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self, HirId};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;

pub(crate) fn provide(providers: &mut Providers) {
    providers.upvars_mentioned = |tcx, def_id| {
        if !tcx.is_closure_like(def_id) {
            return None;
        }

        let local_def_id = def_id.expect_local();
        let body = tcx.hir_maybe_body_owned_by(local_def_id)?;

        let mut local_collector = LocalCollector::default();
        local_collector.visit_body(&body);

        let mut capture_collector = CaptureCollector {
            tcx,
            locals: &local_collector.locals,
            upvars: FxIndexMap::default(),
        };
        capture_collector.visit_body(&body);

        if !capture_collector.upvars.is_empty() {
            Some(tcx.arena.alloc(capture_collector.upvars))
        } else {
            None
        }
    };
}

#[derive(Default)]
struct LocalCollector {
    // FIXME(eddyb) perhaps use `ItemLocalId` instead?
    locals: FxHashSet<HirId>,
}

impl<'tcx> Visitor<'tcx> for LocalCollector {
    fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
        if let hir::PatKind::Binding(_, hir_id, ..) = pat.kind {
            self.locals.insert(hir_id);
        }
        intravisit::walk_pat(self, pat);
    }
}

struct CaptureCollector<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    locals: &'a FxHashSet<HirId>,
    upvars: FxIndexMap<HirId, hir::Upvar>,
}

impl CaptureCollector<'_, '_> {
    fn visit_local_use(&mut self, var_id: HirId, span: Span) {
        if !self.locals.contains(&var_id) {
            self.upvars.entry(var_id).or_insert(hir::Upvar { span });
        }
    }
}

impl<'tcx> Visitor<'tcx> for CaptureCollector<'_, 'tcx> {
    fn visit_path(&mut self, path: &hir::Path<'tcx>, _: HirId) {
        if let Res::Local(var_id) = path.res {
            self.visit_local_use(var_id, path.span);
        }

        intravisit::walk_path(self, path);
    }

    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
        if let hir::ExprKind::Closure(closure) = expr.kind
            && let Some(upvars) = self.tcx.upvars_mentioned(closure.def_id)
        {
            // Every capture of a closure expression is a local in scope,
            // that is moved/copied/borrowed into the closure value, and
            // for this analysis they are like any other access to a local.
            //
            // E.g. in `|b| |c| (a, b, c)`, the upvars of the inner closure
            // are `a` and `b`, and while `a` is not directly used in the
            // outer closure, it needs to be an upvar there too, so that
            // the inner closure can take it (from the outer closure's env).
            for (&var_id, upvar) in upvars {
                self.visit_local_use(var_id, upvar.span);
            }
        }

        intravisit::walk_expr(self, expr);
    }
}
