//! Borrow checker diagnostics.

use rustc::hir;
use rustc::hir::def::Namespace;
use rustc::hir::def_id::DefId;
use rustc::hir::GeneratorKind;
use rustc::mir::{
    AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand,
    Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind,
    Static, StaticKind, Terminator, TerminatorKind,
};
use rustc::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc::ty::layout::VariantIdx;
use rustc::ty::print::Print;
use rustc_errors::DiagnosticBuilder;
use syntax_pos::Span;

use super::borrow_set::BorrowData;
use super::MirBorrowckCtxt;
use crate::dataflow::move_paths::{InitLocation, LookupResult};

mod find_use;
mod var_name;
mod region_name;
mod outlives_suggestion;

mod conflict_errors;
mod move_errors;
mod mutability_errors;
mod region_errors;
mod explain_borrow;

crate use mutability_errors::AccessKind;
crate use region_name::{RegionName, RegionNameSource, RegionErrorNamingCtx};
crate use region_errors::{ErrorReportingCtx, ErrorConstraintInfo};
crate use outlives_suggestion::OutlivesSuggestionBuilder;

pub(super) struct IncludingDowncast(pub(super) bool);

impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
    /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure
    /// is moved after being invoked.
    ///
    /// ```text
    /// note: closure cannot be invoked more than once because it moves the variable `dict` out of
    ///       its environment
    ///   --> $DIR/issue-42065.rs:16:29
    ///    |
    /// LL |         for (key, value) in dict {
    ///    |                             ^^^^
    /// ```
    pub(super) fn add_moved_or_invoked_closure_note(
        &self,
        location: Location,
        place: PlaceRef<'cx, 'tcx>,
        diag: &mut DiagnosticBuilder<'_>,
    ) {
        debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
        let mut target = place.local_or_deref_local();
        for stmt in &self.body[location.block].statements[location.statement_index..] {
            debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target);
            if let StatementKind::Assign(box(into, Rvalue::Use(from))) = &stmt.kind {
                debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from);
                match from {
                    Operand::Copy(ref place) |
                    Operand::Move(ref place) if target == place.local_or_deref_local() =>
                        target = into.local_or_deref_local(),
                    _ => {},
                }
            }
        }

        // Check if we are attempting to call a closure after it has been invoked.
        let terminator = self.body[location.block].terminator();
        debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator);
        if let TerminatorKind::Call {
            func: Operand::Constant(box Constant {
                literal: ty::Const {
                    ty: &ty::TyS { kind: ty::FnDef(id, _), ..  },
                    ..
                },
                ..
            }),
            args,
            ..
        } = &terminator.kind {
            debug!("add_moved_or_invoked_closure_note: id={:?}", id);
            if self.infcx.tcx.parent(id) == self.infcx.tcx.lang_items().fn_once_trait() {
                let closure = match args.first() {
                    Some(Operand::Copy(ref place)) |
                    Some(Operand::Move(ref place)) if target == place.local_or_deref_local() =>
                        place.local_or_deref_local().unwrap(),
                    _ => return,
                };

                debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
                if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind {
                    let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap();

                    if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did)
                        .closure_kind_origins()
                        .get(hir_id)
                    {
                        diag.span_note(
                            *span,
                            &format!(
                                "closure cannot be invoked more than once because it moves the \
                                 variable `{}` out of its environment",
                                name,
                            ),
                        );
                        return;
                    }
                }
            }
        }

        // Check if we are just moving a closure after it has been invoked.
        if let Some(target) = target {
            if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind {
                let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap();

                if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did)
                    .closure_kind_origins()
                    .get(hir_id)
                {
                    diag.span_note(
                        *span,
                        &format!(
                            "closure cannot be moved more than once as it is not `Copy` due to \
                             moving the variable `{}` out of its environment",
                             name
                        ),
                    );
                }
            }
        }
    }

    /// End-user visible description of `place` if one can be found. If the
    /// place is a temporary for instance, None will be returned.
    pub(super) fn describe_place(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option<String> {
        self.describe_place_with_options(place_ref, IncludingDowncast(false))
    }

    /// End-user visible description of `place` if one can be found. If the
    /// place is a temporary for instance, None will be returned.
    /// `IncludingDowncast` parameter makes the function return `Err` if `ProjectionElem` is
    /// `Downcast` and `IncludingDowncast` is true
    pub(super) fn describe_place_with_options(
        &self,
        place: PlaceRef<'cx, 'tcx>,
        including_downcast: IncludingDowncast,
    ) -> Option<String> {
        let mut buf = String::new();
        match self.append_place_to_string(place, &mut buf, false, &including_downcast) {
            Ok(()) => Some(buf),
            Err(()) => None,
        }
    }

    /// Appends end-user visible description of `place` to `buf`.
    fn append_place_to_string(
        &self,
        place: PlaceRef<'cx, 'tcx>,
        buf: &mut String,
        mut autoderef: bool,
        including_downcast: &IncludingDowncast,
    ) -> Result<(), ()> {
        match place {
            PlaceRef {
                base: PlaceBase::Local(local),
                projection: [],
            } => {
                self.append_local_to_string(*local, buf)?;
            }
            PlaceRef {
                base:
                    PlaceBase::Static(box Static {
                        kind: StaticKind::Promoted(..),
                        ..
                    }),
                projection: [],
            } => {
                buf.push_str("promoted");
            }
            PlaceRef {
                base:
                    PlaceBase::Static(box Static {
                        kind: StaticKind::Static,
                        def_id,
                        ..
                    }),
                projection: [],
            } => {
                buf.push_str(&self.infcx.tcx.item_name(*def_id).to_string());
            }
            PlaceRef {
                base: &PlaceBase::Local(local),
                projection: [ProjectionElem::Deref]
            } if self.body.local_decls[local].is_ref_for_guard() => {
                self.append_place_to_string(
                    PlaceRef {
                        base: &PlaceBase::Local(local),
                        projection: &[],
                    },
                    buf,
                    autoderef,
                    &including_downcast,
                )?;
            },
            PlaceRef {
                base: &PlaceBase::Local(local),
                projection: [ProjectionElem::Deref]
            } if self.body.local_decls[local].is_ref_to_static() => {
                let local_info = &self.body.local_decls[local].local_info;
                if let LocalInfo::StaticRef { def_id, .. } = *local_info {
                    buf.push_str(&self.infcx.tcx.item_name(def_id).as_str());
                } else {
                    unreachable!();
                }
            },
            PlaceRef {
                base,
                projection: [proj_base @ .., elem],
            } => {
                match elem {
                    ProjectionElem::Deref => {
                        let upvar_field_projection =
                            self.is_upvar_field_projection(place);
                        if let Some(field) = upvar_field_projection {
                            let var_index = field.index();
                            let name = self.upvars[var_index].name.to_string();
                            if self.upvars[var_index].by_ref {
                                buf.push_str(&name);
                            } else {
                                buf.push_str(&format!("*{}", &name));
                            }
                        } else {
                            if autoderef {
                                // FIXME turn this recursion into iteration
                                self.append_place_to_string(
                                    PlaceRef {
                                        base,
                                        projection: proj_base,
                                    },
                                    buf,
                                    autoderef,
                                    &including_downcast,
                                )?;
                            } else {
                                match (proj_base, base) {
                                    _ => {
                                        buf.push_str(&"*");
                                        self.append_place_to_string(
                                            PlaceRef {
                                                base,
                                                projection: proj_base,
                                            },
                                            buf,
                                            autoderef,
                                            &including_downcast,
                                        )?;
                                    }
                                }
                            }
                        }
                    }
                    ProjectionElem::Downcast(..) => {
                        self.append_place_to_string(
                            PlaceRef {
                                base,
                                projection: proj_base,
                            },
                            buf,
                            autoderef,
                            &including_downcast,
                        )?;
                        if including_downcast.0 {
                            return Err(());
                        }
                    }
                    ProjectionElem::Field(field, _ty) => {
                        autoderef = true;

                        let upvar_field_projection =
                            self.is_upvar_field_projection(place);
                        if let Some(field) = upvar_field_projection {
                            let var_index = field.index();
                            let name = self.upvars[var_index].name.to_string();
                            buf.push_str(&name);
                        } else {
                            let field_name = self.describe_field(PlaceRef {
                                base,
                                projection: proj_base,
                            }, *field);
                            self.append_place_to_string(
                                PlaceRef {
                                    base,
                                    projection: proj_base,
                                },
                                buf,
                                autoderef,
                                &including_downcast,
                            )?;
                            buf.push_str(&format!(".{}", field_name));
                        }
                    }
                    ProjectionElem::Index(index) => {
                        autoderef = true;

                        self.append_place_to_string(
                            PlaceRef {
                                base,
                                projection: proj_base,
                            },
                            buf,
                            autoderef,
                            &including_downcast,
                        )?;
                        buf.push_str("[");
                        if self.append_local_to_string(*index, buf).is_err() {
                            buf.push_str("_");
                        }
                        buf.push_str("]");
                    }
                    ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
                        autoderef = true;
                        // Since it isn't possible to borrow an element on a particular index and
                        // then use another while the borrow is held, don't output indices details
                        // to avoid confusing the end-user
                        self.append_place_to_string(
                            PlaceRef {
                                base,
                                projection: proj_base,
                            },
                            buf,
                            autoderef,
                            &including_downcast,
                        )?;
                        buf.push_str(&"[..]");
                    }
                };
            }
        }

        Ok(())
    }

    /// Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have
    /// a name, or its name was generated by the compiler, then `Err` is returned
    fn append_local_to_string(&self, local: Local, buf: &mut String) -> Result<(), ()> {
        let decl = &self.body.local_decls[local];
        match self.local_names[local] {
            Some(name) if !decl.from_compiler_desugaring() => {
                buf.push_str(&name.as_str());
                Ok(())
            }
            _ => Err(()),
        }
    }

    /// End-user visible description of the `field`nth field of `base`
    fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String {
        // FIXME Place2 Make this work iteratively
        match place {
            PlaceRef {
                base: PlaceBase::Local(local),
                projection: [],
            } => {
                let local = &self.body.local_decls[*local];
                self.describe_field_from_ty(&local.ty, field, None)
            }
            PlaceRef {
                base: PlaceBase::Static(static_),
                projection: [],
            } =>
                self.describe_field_from_ty(&static_.ty, field, None),
            PlaceRef {
                base,
                projection: [proj_base @ .., elem],
            } => match elem {
                ProjectionElem::Deref => {
                    self.describe_field(PlaceRef {
                        base,
                        projection: proj_base,
                    }, field)
                }
                ProjectionElem::Downcast(_, variant_index) => {
                    let base_ty = Place::ty_from(
                        place.base,
                        place.projection,
                        *self.body,
                        self.infcx.tcx).ty;
                    self.describe_field_from_ty(&base_ty, field, Some(*variant_index))
                }
                ProjectionElem::Field(_, field_type) => {
                    self.describe_field_from_ty(&field_type, field, None)
                }
                ProjectionElem::Index(..)
                | ProjectionElem::ConstantIndex { .. }
                | ProjectionElem::Subslice { .. } => {
                    self.describe_field(PlaceRef {
                        base,
                        projection: proj_base,
                    }, field)
                }
            },
        }
    }

    /// End-user visible description of the `field_index`nth field of `ty`
    fn describe_field_from_ty(
        &self,
        ty: Ty<'_>,
        field: Field,
        variant_index: Option<VariantIdx>
    ) -> String {
        if ty.is_box() {
            // If the type is a box, the field is described from the boxed type
            self.describe_field_from_ty(&ty.boxed_ty(), field, variant_index)
        } else {
            match ty.kind {
                ty::Adt(def, _) => {
                    let variant = if let Some(idx) = variant_index {
                        assert!(def.is_enum());
                        &def.variants[idx]
                    } else {
                        def.non_enum_variant()
                    };
                    variant.fields[field.index()]
                        .ident
                        .to_string()
                },
                ty::Tuple(_) => field.index().to_string(),
                ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
                    self.describe_field_from_ty(&ty, field, variant_index)
                }
                ty::Array(ty, _) | ty::Slice(ty) =>
                    self.describe_field_from_ty(&ty, field, variant_index),
                ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
                    // `tcx.upvars(def_id)` returns an `Option`, which is `None` in case
                    // the closure comes from another crate. But in that case we wouldn't
                    // be borrowck'ing it, so we can just unwrap:
                    let (&var_id, _) = self.infcx.tcx.upvars(def_id).unwrap()
                        .get_index(field.index()).unwrap();

                    self.infcx.tcx.hir().name(var_id).to_string()
                }
                _ => {
                    // Might need a revision when the fields in trait RFC is implemented
                    // (https://github.com/rust-lang/rfcs/pull/1546)
                    bug!(
                        "End-user description not implemented for field access on `{:?}`",
                        ty
                    );
                }
            }
        }
    }

    /// Add a note that a type does not implement `Copy`
    pub(super) fn note_type_does_not_implement_copy(
        &self,
        err: &mut DiagnosticBuilder<'a>,
        place_desc: &str,
        ty: Ty<'tcx>,
        span: Option<Span>,
    ) {
        let message = format!(
            "move occurs because {} has type `{}`, which does not implement the `Copy` trait",
            place_desc,
            ty,
        );
        if let Some(span) = span {
            err.span_label(span, message);
        } else {
            err.note(&message);
        }
    }

    pub(super) fn borrowed_content_source(
        &self,
        deref_base: PlaceRef<'cx, 'tcx>,
    ) -> BorrowedContentSource<'tcx> {
        let tcx = self.infcx.tcx;

        // Look up the provided place and work out the move path index for it,
        // we'll use this to check whether it was originally from an overloaded
        // operator.
        match self.move_data.rev_lookup.find(deref_base) {
            LookupResult::Exact(mpi) | LookupResult::Parent(Some(mpi)) => {
                debug!("borrowed_content_source: mpi={:?}", mpi);

                for i in &self.move_data.init_path_map[mpi] {
                    let init = &self.move_data.inits[*i];
                    debug!("borrowed_content_source: init={:?}", init);
                    // We're only interested in statements that initialized a value, not the
                    // initializations from arguments.
                    let loc = match init.location {
                        InitLocation::Statement(stmt) => stmt,
                        _ => continue,
                    };

                    let bbd = &self.body[loc.block];
                    let is_terminator = bbd.statements.len() == loc.statement_index;
                    debug!(
                        "borrowed_content_source: loc={:?} is_terminator={:?}",
                        loc,
                        is_terminator,
                    );
                    if !is_terminator {
                        continue;
                    } else if let Some(Terminator {
                        kind: TerminatorKind::Call {
                            ref func,
                            from_hir_call: false,
                            ..
                        },
                        ..
                    }) = bbd.terminator {
                        if let Some(source) = BorrowedContentSource::from_call(
                            func.ty(*self.body, tcx),
                            tcx
                        ) {
                            return source;
                        }
                    }
                }
            }
            // Base is a `static` so won't be from an overloaded operator
            _ => (),
        };

        // If we didn't find an overloaded deref or index, then assume it's a
        // built in deref and check the type of the base.
        let base_ty = Place::ty_from(
            deref_base.base,
            deref_base.projection,
            *self.body,
            tcx
        ).ty;
        if base_ty.is_unsafe_ptr() {
            BorrowedContentSource::DerefRawPointer
        } else if base_ty.is_mutable_ptr() {
            BorrowedContentSource::DerefMutableRef
        } else {
            BorrowedContentSource::DerefSharedRef
        }
    }
}

impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
    /// Return the name of the provided `Ty` (that must be a reference) with a synthesized lifetime
    /// name where required.
    pub(super) fn get_name_for_ty(&self, ty: Ty<'tcx>, counter: usize) -> String {
        let mut s = String::new();
        let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS);

        // We need to add synthesized lifetimes where appropriate. We do
        // this by hooking into the pretty printer and telling it to label the
        // lifetimes without names with the value `'0`.
        match ty.kind {
            ty::Ref(ty::RegionKind::ReLateBound(_, br), _, _)
            | ty::Ref(
                ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }),
                _,
                _,
            ) => printer.region_highlight_mode.highlighting_bound_region(*br, counter),
            _ => {}
        }

        let _ = ty.print(printer);
        s
    }

    /// Returns the name of the provided `Ty` (that must be a reference)'s region with a
    /// synthesized lifetime name where required.
    pub(super) fn get_region_name_for_ty(&self, ty: Ty<'tcx>, counter: usize) -> String {
        let mut s = String::new();
        let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS);

        let region = match ty.kind {
            ty::Ref(region, _, _) => {
                match region {
                    ty::RegionKind::ReLateBound(_, br)
                    | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
                        printer.region_highlight_mode.highlighting_bound_region(*br, counter)
                    }
                    _ => {}
                }

                region
            }
            _ => bug!("ty for annotation of borrow region is not a reference"),
        };

        let _ = region.print(printer);
        s
    }
}

// The span(s) associated to a use of a place.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub(super) enum UseSpans {
    // The access is caused by capturing a variable for a closure.
    ClosureUse {
        // This is true if the captured variable was from a generator.
        generator_kind: Option<GeneratorKind>,
        // The span of the args of the closure, including the `move` keyword if
        // it's present.
        args_span: Span,
        // The span of the first use of the captured variable inside the closure.
        var_span: Span,
    },
    // This access has a single span associated to it: common case.
    OtherUse(Span),
}

impl UseSpans {
    pub(super) fn args_or_use(self) -> Span {
        match self {
            UseSpans::ClosureUse {
                args_span: span, ..
            }
            | UseSpans::OtherUse(span) => span,
        }
    }

    pub(super) fn var_or_use(self) -> Span {
        match self {
            UseSpans::ClosureUse { var_span: span, .. } | UseSpans::OtherUse(span) => span,
        }
    }

    pub(super) fn generator_kind(self) -> Option<GeneratorKind> {
        match self {
            UseSpans::ClosureUse { generator_kind, .. } => generator_kind,
            _ => None,
        }
    }

    // Add a span label to the arguments of the closure, if it exists.
    pub(super) fn args_span_label(
        self,
        err: &mut DiagnosticBuilder<'_>,
        message: impl Into<String>,
    ) {
        if let UseSpans::ClosureUse { args_span, .. } = self {
            err.span_label(args_span, message);
        }
    }

    // Add a span label to the use of the captured variable, if it exists.
    pub(super) fn var_span_label(
        self,
        err: &mut DiagnosticBuilder<'_>,
        message: impl Into<String>,
    ) {
        if let UseSpans::ClosureUse { var_span, .. } = self {
            err.span_label(var_span, message);
        }
    }

    /// Returns `false` if this place is not used in a closure.
    pub(super) fn for_closure(&self) -> bool {
        match *self {
            UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_none(),
            _ => false,
        }
    }

    /// Returns `false` if this place is not used in a generator.
    pub(super) fn for_generator(&self) -> bool {
        match *self {
            UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_some(),
            _ => false,
        }
    }

    /// Describe the span associated with a use of a place.
    pub(super) fn describe(&self) -> String {
        match *self {
            UseSpans::ClosureUse { generator_kind, .. } => if generator_kind.is_some() {
                " in generator".to_string()
            } else {
                " in closure".to_string()
            },
            _ => "".to_string(),
        }
    }

    pub(super) fn or_else<F>(self, if_other: F) -> Self
    where
        F: FnOnce() -> Self,
    {
        match self {
            closure @ UseSpans::ClosureUse { .. } => closure,
            UseSpans::OtherUse(_) => if_other(),
        }
    }
}

pub(super) enum BorrowedContentSource<'tcx> {
    DerefRawPointer,
    DerefMutableRef,
    DerefSharedRef,
    OverloadedDeref(Ty<'tcx>),
    OverloadedIndex(Ty<'tcx>),
}

impl BorrowedContentSource<'tcx> {
    pub(super) fn describe_for_unnamed_place(&self) -> String {
        match *self {
            BorrowedContentSource::DerefRawPointer => format!("a raw pointer"),
            BorrowedContentSource::DerefSharedRef => format!("a shared reference"),
            BorrowedContentSource::DerefMutableRef => {
                format!("a mutable reference")
            }
            BorrowedContentSource::OverloadedDeref(ty) => {
                if ty.is_rc() {
                   format!("an `Rc`")
                } else if ty.is_arc() {
                    format!("an `Arc`")
                } else {
                    format!("dereference of `{}`", ty)
                }
            }
            BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty),
        }
    }

    pub(super) fn describe_for_named_place(&self) -> Option<&'static str> {
        match *self {
            BorrowedContentSource::DerefRawPointer => Some("raw pointer"),
            BorrowedContentSource::DerefSharedRef => Some("shared reference"),
            BorrowedContentSource::DerefMutableRef => Some("mutable reference"),
            // Overloaded deref and index operators should be evaluated into a
            // temporary. So we don't need a description here.
            BorrowedContentSource::OverloadedDeref(_)
            | BorrowedContentSource::OverloadedIndex(_) => None
        }
    }

    pub(super) fn describe_for_immutable_place(&self) -> String {
        match *self {
            BorrowedContentSource::DerefRawPointer => format!("a `*const` pointer"),
            BorrowedContentSource::DerefSharedRef => format!("a `&` reference"),
            BorrowedContentSource::DerefMutableRef => {
                 bug!("describe_for_immutable_place: DerefMutableRef isn't immutable")
            },
            BorrowedContentSource::OverloadedDeref(ty) => {
                if ty.is_rc() {
                   format!("an `Rc`")
                } else if ty.is_arc() {
                    format!("an `Arc`")
                } else {
                    format!("a dereference of `{}`", ty)
                }
            }
            BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty),
        }
    }

    fn from_call(func: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<Self> {
        match func.kind {
            ty::FnDef(def_id, substs) => {
                let trait_id = tcx.trait_of_item(def_id)?;

                let lang_items = tcx.lang_items();
                if Some(trait_id) == lang_items.deref_trait()
                    || Some(trait_id) == lang_items.deref_mut_trait()
                {
                    Some(BorrowedContentSource::OverloadedDeref(substs.type_at(0)))
                } else if Some(trait_id) == lang_items.index_trait()
                    || Some(trait_id) == lang_items.index_mut_trait()
                {
                    Some(BorrowedContentSource::OverloadedIndex(substs.type_at(0)))
                } else {
                    None
                }
            }
            _ => None,
        }
    }
}

impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
    /// Finds the spans associated to a move or copy of move_place at location.
    pub(super) fn move_spans(
        &self,
        moved_place: PlaceRef<'cx, 'tcx>, // Could also be an upvar.
        location: Location,
    ) -> UseSpans {
        use self::UseSpans::*;

        let stmt = match self.body[location.block].statements.get(location.statement_index) {
            Some(stmt) => stmt,
            None => return OtherUse(self.body.source_info(location).span),
        };

        debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
        if let  StatementKind::Assign(
            box(_, Rvalue::Aggregate(ref kind, ref places))
        ) = stmt.kind {
            let def_id = match kind {
                box AggregateKind::Closure(def_id, _)
                | box AggregateKind::Generator(def_id, _, _) => def_id,
                _ => return OtherUse(stmt.source_info.span),
            };

            debug!(
                "move_spans: def_id={:?} places={:?}",
                def_id, places
            );
            if let Some((args_span, generator_kind, var_span))
                = self.closure_span(*def_id, moved_place, places) {
                return ClosureUse {
                    generator_kind,
                    args_span,
                    var_span,
                };
            }
        }

        OtherUse(stmt.source_info.span)
    }

    /// Finds the span of arguments of a closure (within `maybe_closure_span`)
    /// and its usage of the local assigned at `location`.
    /// This is done by searching in statements succeeding `location`
    /// and originating from `maybe_closure_span`.
    pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpans {
        use self::UseSpans::*;
        debug!("borrow_spans: use_span={:?} location={:?}", use_span, location);

        let target = match self.body[location.block]
            .statements
            .get(location.statement_index)
        {
            Some(&Statement {
                kind: StatementKind::Assign(box(ref place, _)),
                ..
            }) => {
                if let Some(local) = place.as_local() {
                    local
                } else {
                    return OtherUse(use_span);
                }
            }
            _ => return OtherUse(use_span),
        };

        if self.body.local_kind(target) != LocalKind::Temp {
            // operands are always temporaries.
            return OtherUse(use_span);
        }

        for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
            if let StatementKind::Assign(
                box(_, Rvalue::Aggregate(ref kind, ref places))
            ) = stmt.kind {
                let (def_id, is_generator) = match kind {
                    box AggregateKind::Closure(def_id, _) => (def_id, false),
                    box AggregateKind::Generator(def_id, _, _) => (def_id, true),
                    _ => continue,
                };

                debug!(
                    "borrow_spans: def_id={:?} is_generator={:?} places={:?}",
                    def_id, is_generator, places
                );
                if let Some((args_span, generator_kind, var_span)) = self.closure_span(
                    *def_id, Place::from(target).as_ref(), places
                ) {
                    return ClosureUse {
                        generator_kind,
                        args_span,
                        var_span,
                    };
                } else {
                    return OtherUse(use_span);
                }
            }

            if use_span != stmt.source_info.span {
                break;
            }
        }

        OtherUse(use_span)
    }

    /// Finds the span of a captured variable within a closure or generator.
    fn closure_span(
        &self,
        def_id: DefId,
        target_place: PlaceRef<'cx, 'tcx>,
        places: &Vec<Operand<'tcx>>,
    ) -> Option<(Span, Option<GeneratorKind>, Span)> {
        debug!(
            "closure_span: def_id={:?} target_place={:?} places={:?}",
            def_id, target_place, places
        );
        let hir_id = self.infcx.tcx.hir().as_local_hir_id(def_id)?;
        let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
        debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
        if let hir::ExprKind::Closure(
            .., body_id, args_span, _
        ) = expr {
            for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) {
                match place {
                    Operand::Copy(place) |
                    Operand::Move(place) if target_place == place.as_ref() => {
                        debug!("closure_span: found captured local {:?}", place);
                        let body = self.infcx.tcx.hir().body(*body_id);
                        let generator_kind = body.generator_kind();
                        return Some((*args_span, generator_kind, upvar.span));
                    },
                    _ => {}
                }
            }

        }
        None
    }

    /// Helper to retrieve span(s) of given borrow from the current MIR
    /// representation
    pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData<'_>) -> UseSpans {
        let span = self.body.source_info(borrow.reserve_location).span;
        self.borrow_spans(span, borrow.reserve_location)
    }
}
