// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! ### Inferring borrow kinds for upvars
//!
//! Whenever there is a closure expression, we need to determine how each
//! upvar is used. We do this by initially assigning each upvar an
//! immutable "borrow kind" (see `ty::BorrowKind` for details) and then
//! "escalating" the kind as needed. The borrow kind proceeds according to
//! the following lattice:
//!
//!     ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow
//!
//! So, for example, if we see an assignment `x = 5` to an upvar `x`, we
//! will promote its borrow kind to mutable borrow. If we see an `&mut x`
//! we'll do the same. Naturally, this applies not just to the upvar, but
//! to everything owned by `x`, so the result is the same for something
//! like `x.f = 5` and so on (presuming `x` is not a borrowed pointer to a
//! struct). These adjustments are performed in
//! `adjust_upvar_borrow_kind()` (you can trace backwards through the code
//! from there).
//!
//! The fact that we are inferring borrow kinds as we go results in a
//! semi-hacky interaction with mem-categorization. In particular,
//! mem-categorization will query the current borrow kind as it
//! categorizes, and we'll return the *current* value, but this may get
//! adjusted later. Therefore, in this module, we generally ignore the
//! borrow kind (and derived mutabilities) that are returned from
//! mem-categorization, since they may be inaccurate. (Another option
//! would be to use a unification scheme, where instead of returning a
//! concrete borrow kind like `ty::ImmBorrow`, we return a
//! `ty::InferBorrow(upvar_id)` or something like that, but this would
//! then mean that all later passes would have to check for these figments
//! and report an error, and it just seems like more mess in the end.)

use super::FnCtxt;

use middle::expr_use_visitor as euv;
use middle::mem_categorization as mc;
use middle::mem_categorization::Categorization;
use rustc::hir::def_id::DefId;
use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
use rustc::infer::UpvarRegion;
use syntax::ast;
use syntax_pos::Span;
use rustc::hir;
use rustc::hir::def_id::LocalDefId;
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};

impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
    pub fn closure_analyze(&self, body: &'gcx hir::Body) {
        InferBorrowKindVisitor { fcx: self }.visit_body(body);

        // it's our job to process these.
        assert!(self.deferred_call_resolutions.borrow().is_empty());
    }
}

struct InferBorrowKindVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
}

impl<'a, 'gcx, 'tcx> Visitor<'gcx> for InferBorrowKindVisitor<'a, 'gcx, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
        NestedVisitorMap::None
    }

    fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
        if let hir::ExprKind::Closure(cc, _, body_id, _, _) = expr.node {
            let body = self.fcx.tcx.hir.body(body_id);
            self.visit_body(body);
            self.fcx
                .analyze_closure(expr.id, expr.hir_id, expr.span, body, cc);
        }

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

impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
    fn analyze_closure(
        &self,
        closure_node_id: ast::NodeId,
        closure_hir_id: hir::HirId,
        span: Span,
        body: &hir::Body,
        capture_clause: hir::CaptureClause,
    ) {
        /*!
         * Analysis starting point.
         */

        debug!(
            "analyze_closure(id={:?}, body.id={:?})",
            closure_node_id,
            body.id()
        );

        // Extract the type of the closure.
        let (closure_def_id, substs) = match self.node_ty(closure_hir_id).sty {
            ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
            ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
            ty::Error => {
                // #51714: skip analysis when we have already encountered type errors
                return;
            }
            ref t => {
                span_bug!(
                    span,
                    "type of closure expr {:?} is not a closure {:?}",
                    closure_node_id,
                    t
                );
            }
        };

        let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs{
            if self.closure_kind(closure_def_id, closure_substs).is_none() {
                Some(closure_substs)
            } else {
                None
            }
        } else {
            None
        };

        self.tcx.with_freevars(closure_node_id, |freevars| {
            for freevar in freevars {
                let upvar_id = ty::UpvarId {
                    var_id: self.tcx.hir.node_to_hir_id(freevar.var_id()),
                    closure_expr_id: LocalDefId::from_def_id(closure_def_id),
                };
                debug!("seed upvar_id {:?}", upvar_id);

                let capture_kind = match capture_clause {
                    hir::CaptureByValue => ty::UpvarCapture::ByValue,
                    hir::CaptureByRef => {
                        let origin = UpvarRegion(upvar_id, span);
                        let freevar_region = self.next_region_var(origin);
                        let upvar_borrow = ty::UpvarBorrow {
                            kind: ty::ImmBorrow,
                            region: freevar_region,
                        };
                        ty::UpvarCapture::ByRef(upvar_borrow)
                    }
                };

                self.tables
                    .borrow_mut()
                    .upvar_capture_map
                    .insert(upvar_id, capture_kind);
            }
        });

        let body_owner_def_id = self.tcx.hir.body_owner_def_id(body.id());
        let region_scope_tree = &self.tcx.region_scope_tree(body_owner_def_id);
        let mut delegate = InferBorrowKind {
            fcx: self,
            closure_def_id: closure_def_id,
            current_closure_kind: ty::ClosureKind::LATTICE_BOTTOM,
            current_origin: None,
            adjust_upvar_captures: ty::UpvarCaptureMap::default(),
        };
        euv::ExprUseVisitor::with_infer(
            &mut delegate,
            &self.infcx,
            self.param_env,
            region_scope_tree,
            &self.tables.borrow(),
        ).consume_body(body);

        if let Some(closure_substs) = infer_kind {
            // Unify the (as yet unbound) type variable in the closure
            // substs with the kind we inferred.
            let inferred_kind = delegate.current_closure_kind;
            let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx);
            self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty);

            // If we have an origin, store it.
            if let Some(origin) = delegate.current_origin {
                self.tables
                    .borrow_mut()
                    .closure_kind_origins_mut()
                    .insert(closure_hir_id, origin);
            }
        }

        self.tables
            .borrow_mut()
            .upvar_capture_map
            .extend(delegate.adjust_upvar_captures);

        // Now that we've analyzed the closure, we know how each
        // variable is borrowed, and we know what traits the closure
        // implements (Fn vs FnMut etc). We now have some updates to do
        // with that information.
        //
        // Note that no closure type C may have an upvar of type C
        // (though it may reference itself via a trait object). This
        // results from the desugaring of closures to a struct like
        // `Foo<..., UV0...UVn>`. If one of those upvars referenced
        // C, then the type would have infinite size (and the
        // inference algorithm will reject it).

        // Equate the type variables for the upvars with the actual types.
        let final_upvar_tys = self.final_upvar_tys(closure_node_id);
        debug!(
            "analyze_closure: id={:?} substs={:?} final_upvar_tys={:?}",
            closure_node_id,
            substs,
            final_upvar_tys
        );
        for (upvar_ty, final_upvar_ty) in substs.upvar_tys(closure_def_id, self.tcx)
                                                .zip(final_upvar_tys)
        {
            self.demand_suptype(span, upvar_ty, final_upvar_ty);
        }

        // If we are also inferred the closure kind here,
        // process any deferred resolutions.
        let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id);
        for deferred_call_resolution in deferred_call_resolutions {
            deferred_call_resolution.resolve(self);
        }
    }

    // Returns a list of `ClosureUpvar`s for each upvar.
    fn final_upvar_tys(&self, closure_id: ast::NodeId) -> Vec<Ty<'tcx>> {
        // Presently an unboxed closure type cannot "escape" out of a
        // function, so we will only encounter ones that originated in the
        // local crate or were inlined into it along with some function.
        // This may change if abstract return types of some sort are
        // implemented.
        let tcx = self.tcx;
        let closure_def_index = tcx.hir.local_def_id(closure_id);

        tcx.with_freevars(closure_id, |freevars| {
            freevars
                .iter()
                .map(|freevar| {
                    let var_node_id = freevar.var_id();
                    let var_hir_id = tcx.hir.node_to_hir_id(var_node_id);
                    let freevar_ty = self.node_ty(var_hir_id);
                    let upvar_id = ty::UpvarId {
                        var_id: var_hir_id,
                        closure_expr_id: LocalDefId::from_def_id(closure_def_index),
                    };
                    let capture = self.tables.borrow().upvar_capture(upvar_id);

                    debug!(
                        "var_id={:?} freevar_ty={:?} capture={:?}",
                        var_node_id,
                        freevar_ty,
                        capture
                    );

                    match capture {
                        ty::UpvarCapture::ByValue => freevar_ty,
                        ty::UpvarCapture::ByRef(borrow) => tcx.mk_ref(
                            borrow.region,
                            ty::TypeAndMut {
                                ty: freevar_ty,
                                mutbl: borrow.kind.to_mutbl_lossy(),
                            },
                        ),
                    }
                })
                .collect()
        })
    }
}

struct InferBorrowKind<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,

    // The def-id of the closure whose kind and upvar accesses are being inferred.
    closure_def_id: DefId,

    // The kind that we have inferred that the current closure
    // requires. Note that we *always* infer a minimal kind, even if
    // we don't always *use* that in the final result (i.e., sometimes
    // we've taken the closure kind from the expectations instead, and
    // for generators we don't even implement the closure traits
    // really).
    current_closure_kind: ty::ClosureKind,

    // If we modified `current_closure_kind`, this field contains a `Some()` with the
    // variable access that caused us to do so.
    current_origin: Option<(Span, ast::Name)>,

    // For each upvar that we access, we track the minimal kind of
    // access we need (ref, ref mut, move, etc).
    adjust_upvar_captures: ty::UpvarCaptureMap<'tcx>,
}

impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
    fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: &mc::cmt_<'tcx>,
                                            mode: euv::ConsumeMode) {
        debug!(
            "adjust_upvar_borrow_kind_for_consume(cmt={:?}, mode={:?})",
            cmt,
            mode
        );

        // we only care about moves
        match mode {
            euv::Copy => {
                return;
            }
            euv::Move(_) => {}
        }

        let tcx = self.fcx.tcx;

        // watch out for a move of the deref of a borrowed pointer;
        // for that to be legal, the upvar would have to be borrowed
        // by value instead
        let guarantor = cmt.guarantor();
        debug!(
            "adjust_upvar_borrow_kind_for_consume: guarantor={:?}",
            guarantor
        );
        debug!(
            "adjust_upvar_borrow_kind_for_consume: guarantor.cat={:?}",
            guarantor.cat
        );
        if let Categorization::Deref(_, mc::BorrowedPtr(..)) = guarantor.cat {
            debug!(
                "adjust_upvar_borrow_kind_for_consume: found deref with note {:?}",
                cmt.note
            );
            match guarantor.note {
                mc::NoteUpvarRef(upvar_id) => {
                    debug!(
                        "adjust_upvar_borrow_kind_for_consume: \
                         setting upvar_id={:?} to by value",
                        upvar_id
                    );

                    // to move out of an upvar, this must be a FnOnce closure
                    self.adjust_closure_kind(
                        upvar_id.closure_expr_id,
                        ty::ClosureKind::FnOnce,
                        guarantor.span,
                        var_name(tcx, upvar_id.var_id),
                    );

                    self.adjust_upvar_captures
                        .insert(upvar_id, ty::UpvarCapture::ByValue);
                }
                mc::NoteClosureEnv(upvar_id) => {
                    // we get just a closureenv ref if this is a
                    // `move` closure, or if the upvar has already
                    // been inferred to by-value. In any case, we
                    // must still adjust the kind of the closure
                    // to be a FnOnce closure to permit moves out
                    // of the environment.
                    self.adjust_closure_kind(
                        upvar_id.closure_expr_id,
                        ty::ClosureKind::FnOnce,
                        guarantor.span,
                        var_name(tcx, upvar_id.var_id),
                    );
                }
                mc::NoteIndex | mc::NoteNone => {}
            }
        }
    }

    /// Indicates that `cmt` is being directly mutated (e.g., assigned
    /// to). If cmt contains any by-ref upvars, this implies that
    /// those upvars must be borrowed using an `&mut` borrow.
    fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: &mc::cmt_<'tcx>) {
        debug!("adjust_upvar_borrow_kind_for_mut(cmt={:?})", cmt);

        match cmt.cat.clone() {
            Categorization::Deref(base, mc::Unique) |
            Categorization::Interior(base, _) |
            Categorization::Downcast(base, _) => {
                // Interior or owned data is mutable if base is
                // mutable, so iterate to the base.
                self.adjust_upvar_borrow_kind_for_mut(&base);
            }

            Categorization::Deref(base, mc::BorrowedPtr(..)) => {
                if !self.try_adjust_upvar_deref(cmt, ty::MutBorrow) {
                    // assignment to deref of an `&mut`
                    // borrowed pointer implies that the
                    // pointer itself must be unique, but not
                    // necessarily *mutable*
                    self.adjust_upvar_borrow_kind_for_unique(&base);
                }
            }

            Categorization::Deref(_, mc::UnsafePtr(..)) |
            Categorization::StaticItem |
            Categorization::Rvalue(..) |
            Categorization::Local(_) |
            Categorization::Upvar(..) => {
                return;
            }
        }
    }

    fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: &mc::cmt_<'tcx>) {
        debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})", cmt);

        match cmt.cat.clone() {
            Categorization::Deref(base, mc::Unique) |
            Categorization::Interior(base, _) |
            Categorization::Downcast(base, _) => {
                // Interior or owned data is unique if base is
                // unique.
                self.adjust_upvar_borrow_kind_for_unique(&base);
            }

            Categorization::Deref(base, mc::BorrowedPtr(..)) => {
                if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) {
                    // for a borrowed pointer to be unique, its
                    // base must be unique
                    self.adjust_upvar_borrow_kind_for_unique(&base);
                }
            }

            Categorization::Deref(_, mc::UnsafePtr(..)) |
            Categorization::StaticItem |
            Categorization::Rvalue(..) |
            Categorization::Local(_) |
            Categorization::Upvar(..) => {}
        }
    }

    fn try_adjust_upvar_deref(&mut self, cmt: &mc::cmt_<'tcx>, borrow_kind: ty::BorrowKind)
                              -> bool
    {
        assert!(match borrow_kind {
            ty::MutBorrow => true,
            ty::UniqueImmBorrow => true,

            // imm borrows never require adjusting any kinds, so we don't wind up here
            ty::ImmBorrow => false,
        });

        let tcx = self.fcx.tcx;

        match cmt.note {
            mc::NoteUpvarRef(upvar_id) => {
                // if this is an implicit deref of an
                // upvar, then we need to modify the
                // borrow_kind of the upvar to make sure it
                // is inferred to mutable if necessary
                self.adjust_upvar_borrow_kind(upvar_id, borrow_kind);

                // also need to be in an FnMut closure since this is not an ImmBorrow
                self.adjust_closure_kind(
                    upvar_id.closure_expr_id,
                    ty::ClosureKind::FnMut,
                    cmt.span,
                    var_name(tcx, upvar_id.var_id),
                );

                true
            }
            mc::NoteClosureEnv(upvar_id) => {
                // this kind of deref occurs in a `move` closure, or
                // for a by-value upvar; in either case, to mutate an
                // upvar, we need to be an FnMut closure
                self.adjust_closure_kind(
                    upvar_id.closure_expr_id,
                    ty::ClosureKind::FnMut,
                    cmt.span,
                    var_name(tcx, upvar_id.var_id),
                );

                true
            }
            mc::NoteIndex | mc::NoteNone => false,
        }
    }

    /// We infer the borrow_kind with which to borrow upvars in a stack closure.
    /// The borrow_kind basically follows a lattice of `imm < unique-imm < mut`,
    /// moving from left to right as needed (but never right to left).
    /// Here the argument `mutbl` is the borrow_kind that is required by
    /// some particular use.
    fn adjust_upvar_borrow_kind(&mut self, upvar_id: ty::UpvarId, kind: ty::BorrowKind) {
        let upvar_capture = self.adjust_upvar_captures
            .get(&upvar_id)
            .cloned()
            .unwrap_or_else(|| self.fcx.tables.borrow().upvar_capture(upvar_id));
        debug!(
            "adjust_upvar_borrow_kind(upvar_id={:?}, upvar_capture={:?}, kind={:?})",
            upvar_id,
            upvar_capture,
            kind
        );

        match upvar_capture {
            ty::UpvarCapture::ByValue => {
                // Upvar is already by-value, the strongest criteria.
            }
            ty::UpvarCapture::ByRef(mut upvar_borrow) => {
                match (upvar_borrow.kind, kind) {
                    // Take RHS:
                    (ty::ImmBorrow, ty::UniqueImmBorrow) |
                    (ty::ImmBorrow, ty::MutBorrow) |
                    (ty::UniqueImmBorrow, ty::MutBorrow) => {
                        upvar_borrow.kind = kind;
                        self.adjust_upvar_captures
                            .insert(upvar_id, ty::UpvarCapture::ByRef(upvar_borrow));
                    }
                    // Take LHS:
                    (ty::ImmBorrow, ty::ImmBorrow) |
                    (ty::UniqueImmBorrow, ty::ImmBorrow) |
                    (ty::UniqueImmBorrow, ty::UniqueImmBorrow) |
                    (ty::MutBorrow, _) => {}
                }
            }
        }
    }

    fn adjust_closure_kind(
        &mut self,
        closure_id: LocalDefId,
        new_kind: ty::ClosureKind,
        upvar_span: Span,
        var_name: ast::Name,
    ) {
        debug!(
            "adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, var_name={})",
            closure_id,
            new_kind,
            upvar_span,
            var_name
        );

        // Is this the closure whose kind is currently being inferred?
        if closure_id.to_def_id() != self.closure_def_id {
            debug!("adjust_closure_kind: not current closure");
            return;
        }

        // closures start out as `Fn`.
        let existing_kind = self.current_closure_kind;

        debug!(
            "adjust_closure_kind: closure_id={:?}, existing_kind={:?}, new_kind={:?}",
            closure_id,
            existing_kind,
            new_kind
        );

        match (existing_kind, new_kind) {
            (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
            (ty::ClosureKind::FnMut, ty::ClosureKind::Fn) |
            (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
            (ty::ClosureKind::FnOnce, _) => {
                // no change needed
            }

            (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) |
            (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
            (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
                // new kind is stronger than the old kind
                self.current_closure_kind = new_kind;
                self.current_origin = Some((upvar_span, var_name));
            }
        }
    }
}

impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> {
    fn consume(
        &mut self,
        _consume_id: ast::NodeId,
        _consume_span: Span,
        cmt: &mc::cmt_<'tcx>,
        mode: euv::ConsumeMode,
    ) {
        debug!("consume(cmt={:?},mode={:?})", cmt, mode);
        self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
    }

    fn matched_pat(&mut self, _matched_pat: &hir::Pat, _cmt: &mc::cmt_<'tcx>,
                   _mode: euv::MatchMode) {
    }

    fn consume_pat(&mut self, _consume_pat: &hir::Pat, cmt: &mc::cmt_<'tcx>,
                   mode: euv::ConsumeMode) {
        debug!("consume_pat(cmt={:?},mode={:?})", cmt, mode);
        self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
    }

    fn borrow(
        &mut self,
        borrow_id: ast::NodeId,
        _borrow_span: Span,
        cmt: &mc::cmt_<'tcx>,
        _loan_region: ty::Region<'tcx>,
        bk: ty::BorrowKind,
        _loan_cause: euv::LoanCause,
    ) {
        debug!(
            "borrow(borrow_id={}, cmt={:?}, bk={:?})",
            borrow_id,
            cmt,
            bk
        );

        match bk {
            ty::ImmBorrow => {}
            ty::UniqueImmBorrow => {
                self.adjust_upvar_borrow_kind_for_unique(cmt);
            }
            ty::MutBorrow => {
                self.adjust_upvar_borrow_kind_for_mut(cmt);
            }
        }
    }

    fn decl_without_init(&mut self, _id: ast::NodeId, _span: Span) {}

    fn mutate(
        &mut self,
        _assignment_id: ast::NodeId,
        _assignment_span: Span,
        assignee_cmt: &mc::cmt_<'tcx>,
        _mode: euv::MutateMode,
    ) {
        debug!("mutate(assignee_cmt={:?})", assignee_cmt);

        self.adjust_upvar_borrow_kind_for_mut(assignee_cmt);
    }
}

fn var_name(tcx: TyCtxt, var_hir_id: hir::HirId) -> ast::Name {
    let var_node_id = tcx.hir.hir_to_node_id(var_hir_id);
    tcx.hir.name(var_node_id)
}
