// Copyright 2017 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.

//! From the NLL RFC: "The deep [aka 'supporting'] prefixes for an
//! place are formed by stripping away fields and derefs, except that
//! we stop when we reach the deref of a shared reference. [...] "
//!
//! "Shallow prefixes are found by stripping away fields, but stop at
//! any dereference. So: writing a path like `a` is illegal if `a.b`
//! is borrowed. But: writing `a` is legal if `*a` is borrowed,
//! whether or not `a` is a shared or mutable reference. [...] "

use super::MirBorrowckCtxt;

use rustc::hir;
use rustc::ty::{self, TyCtxt};
use rustc::mir::{Mir, Place, ProjectionElem};

pub trait IsPrefixOf<'tcx> {
    fn is_prefix_of(&self, other: &Place<'tcx>) -> bool;
}

impl<'tcx> IsPrefixOf<'tcx> for Place<'tcx> {
    fn is_prefix_of(&self, other: &Place<'tcx>) -> bool {
        let mut cursor = other;
        loop {
            if self == cursor {
                return true;
            }

            match *cursor {
                Place::Promoted(_) |
                Place::Local(_) | Place::Static(_) => return false,
                Place::Projection(ref proj) => {
                    cursor = &proj.base;
                }
            }
        }
    }
}


pub(super) struct Prefixes<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
    mir: &'cx Mir<'tcx>,
    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
    kind: PrefixSet,
    next: Option<&'cx Place<'tcx>>,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[allow(dead_code)]
pub(super) enum PrefixSet {
    /// Doesn't stop until it returns the base case (a Local or
    /// Static prefix).
    All,
    /// Stops at any dereference.
    Shallow,
    /// Stops at the deref of a shared reference.
    Supporting,
}

impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
    /// Returns an iterator over the prefixes of `place`
    /// (inclusive) from longest to smallest, potentially
    /// terminating the iteration early based on `kind`.
    pub(super) fn prefixes(
        &self,
        place: &'cx Place<'tcx>,
        kind: PrefixSet,
    ) -> Prefixes<'cx, 'gcx, 'tcx> {
        Prefixes {
            next: Some(place),
            kind,
            mir: self.mir,
            tcx: self.infcx.tcx,
        }
    }
}

impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> {
    type Item = &'cx Place<'tcx>;
    fn next(&mut self) -> Option<Self::Item> {
        let mut cursor = match self.next {
            None => return None,
            Some(place) => place,
        };

        // Post-processing `place`: Enqueue any remaining
        // work. Also, `place` may not be a prefix itself, but
        // may hold one further down (e.g. we never return
        // downcasts here, but may return a base of a downcast).

        'cursor: loop {
            let proj = match *cursor {
                Place::Promoted(_) |
                Place::Local(_) | // search yielded this leaf
                Place::Static(_) => {
                    self.next = None;
                    return Some(cursor);
                }

                Place::Projection(ref proj) => proj,
            };

            match proj.elem {
                ProjectionElem::Field(_ /*field*/, _ /*ty*/) => {
                        // FIXME: add union handling
                    self.next = Some(&proj.base);
                    return Some(cursor);
                }
                ProjectionElem::Downcast(..) |
                ProjectionElem::Subslice { .. } |
                ProjectionElem::ConstantIndex { .. } |
                ProjectionElem::Index(_) => {
                    cursor = &proj.base;
                    continue 'cursor;
                }
                ProjectionElem::Deref => {
                    // (handled below)
                }
            }

            assert_eq!(proj.elem, ProjectionElem::Deref);

            match self.kind {
                PrefixSet::Shallow => {
                    // shallow prefixes are found by stripping away
                    // fields, but stop at *any* dereference.
                    // So we can just stop the traversal now.
                    self.next = None;
                    return Some(cursor);
                }
                PrefixSet::All => {
                    // all prefixes: just blindly enqueue the base
                    // of the projection
                    self.next = Some(&proj.base);
                    return Some(cursor);
                }
                PrefixSet::Supporting => {
                    // fall through!
                }
            }

            assert_eq!(self.kind, PrefixSet::Supporting);
            // supporting prefixes: strip away fields and
            // derefs, except we stop at the deref of a shared
            // reference.

            let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
            match ty.sty {
                ty::RawPtr(_) |
                ty::Ref(
                    _, /*rgn*/
                    _, /*ty*/
                    hir::MutImmutable
                    ) => {
                    // don't continue traversing over derefs of raw pointers or shared borrows.
                    self.next = None;
                    return Some(cursor);
                }

                ty::Ref(
                    _, /*rgn*/
                    _, /*ty*/
                    hir::MutMutable,
                    ) => {
                    self.next = Some(&proj.base);
                    return Some(cursor);
                }

                ty::Adt(..) if ty.is_box() => {
                    self.next = Some(&proj.base);
                    return Some(cursor);
                }

                _ => panic!("unknown type fed to Projection Deref."),
            }
        }
    }
}
