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

use borrow_check::nll::explain_borrow::BorrowExplanation;
use borrow_check::nll::region_infer::{RegionName, RegionNameSource};
use borrow_check::prefixes::IsPrefixOf;
use borrow_check::WriteKind;
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::middle::region::ScopeTree;
use rustc::mir::{
    self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant,
    ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand,
    Place, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
    TerminatorKind, VarBindingForm,
};
use rustc::ty::{self, DefIdTree};
use rustc::util::ppaux::with_highlight_region_for_bound_region;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, DiagnosticBuilder};
use syntax_pos::Span;

use super::borrow_set::BorrowData;
use super::{Context, MirBorrowckCtxt};
use super::{InitializationRequiringAction, PrefixSet};
use dataflow::drop_flag_effects;
use dataflow::move_paths::indexes::MoveOutIndex;
use dataflow::move_paths::MovePathIndex;
use util::borrowck_errors::{BorrowckErrors, Origin};

#[derive(Debug)]
struct MoveSite {
    /// Index of the "move out" that we found. The `MoveData` can
    /// then tell us where the move occurred.
    moi: MoveOutIndex,

    /// True if we traversed a back edge while walking from the point
    /// of error to the move site.
    traversed_back_edge: bool
}

impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
    pub(super) fn report_use_of_moved_or_uninitialized(
        &mut self,
        context: Context,
        desired_action: InitializationRequiringAction,
        (moved_place, used_place, span): (&Place<'tcx>, &Place<'tcx>, Span),
        mpi: MovePathIndex,
    ) {
        debug!(
            "report_use_of_moved_or_uninitialized: context={:?} desired_action={:?} \
             moved_place={:?} used_place={:?} span={:?} mpi={:?}",
            context, desired_action, moved_place, used_place, span, mpi
        );

        let use_spans = self.move_spans(moved_place, context.loc)
            .or_else(|| self.borrow_spans(span, context.loc));
        let span = use_spans.args_or_use();

        let move_site_vec = self.get_moved_indexes(context, mpi);
        debug!(
            "report_use_of_moved_or_uninitialized: move_site_vec={:?}",
            move_site_vec
        );
        let move_out_indices: Vec<_> = move_site_vec
            .iter()
            .map(|move_site| move_site.moi)
            .collect();

        if move_out_indices.is_empty() {
            let root_place = self.prefixes(&used_place, PrefixSet::All).last().unwrap();

            if self.uninitialized_error_reported.contains(root_place) {
                debug!(
                    "report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
                    root_place
                );
                return;
            }

            self.uninitialized_error_reported.insert(root_place.clone());

            let item_msg = match self.describe_place_with_options(used_place,
                                                                  IncludingDowncast(true)) {
                Some(name) => format!("`{}`", name),
                None => "value".to_owned(),
            };
            let mut err = self.infcx.tcx.cannot_act_on_uninitialized_variable(
                span,
                desired_action.as_noun(),
                &self.describe_place_with_options(moved_place, IncludingDowncast(true))
                    .unwrap_or_else(|| "_".to_owned()),
                Origin::Mir,
            );
            err.span_label(span, format!("use of possibly uninitialized {}", item_msg));

            use_spans.var_span_label(
                &mut err,
                format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
            );

            err.buffer(&mut self.errors_buffer);
        } else {
            if let Some((reported_place, _)) = self.move_error_reported.get(&move_out_indices) {
                if self.prefixes(&reported_place, PrefixSet::All)
                    .any(|p| p == used_place)
                {
                    debug!(
                        "report_use_of_moved_or_uninitialized place: error suppressed \
                         mois={:?}",
                        move_out_indices
                    );
                    return;
                }
            }

            let msg = ""; //FIXME: add "partially " or "collaterally "

            let mut err = self.infcx.tcx.cannot_act_on_moved_value(
                span,
                desired_action.as_noun(),
                msg,
                self.describe_place_with_options(&moved_place, IncludingDowncast(true)),
                Origin::Mir,
            );

            self.add_closure_invoked_twice_with_moved_variable_suggestion(
                context.loc,
                used_place,
                &mut err,
            );

            let mut is_loop_move = false;
            for move_site in &move_site_vec {
                let move_out = self.move_data.moves[(*move_site).moi];
                let moved_place = &self.move_data.move_paths[move_out.path].place;

                let move_spans = self.move_spans(moved_place, move_out.source);
                let move_span = move_spans.args_or_use();

                let move_msg = if move_spans.for_closure() {
                    " into closure"
                } else {
                    ""
                };

                if span == move_span {
                    err.span_label(
                        span,
                        format!("value moved{} here, in previous iteration of loop", move_msg),
                    );
                    is_loop_move = true;
                } else if move_site.traversed_back_edge {
                    err.span_label(
                        move_span,
                        format!(
                            "value moved{} here, in previous iteration of loop",
                            move_msg
                        ),
                    );
                } else {
                    err.span_label(move_span, format!("value moved{} here", move_msg));
                    move_spans.var_span_label(
                        &mut err,
                        format!("variable moved due to use{}", move_spans.describe()),
                    );
                };
            }

            use_spans.var_span_label(
                &mut err,
                format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
            );

            if !is_loop_move {
                err.span_label(
                    span,
                    format!(
                        "value {} here after move",
                        desired_action.as_verb_in_past_tense()
                    ),
                );
            }

            if let Some(ty) = self.retrieve_type_for_place(used_place) {
                let needs_note = match ty.sty {
                    ty::Closure(id, _) => {
                        let tables = self.infcx.tcx.typeck_tables_of(id);
                        let node_id = self.infcx.tcx.hir.as_local_node_id(id).unwrap();
                        let hir_id = self.infcx.tcx.hir.node_to_hir_id(node_id);

                        tables.closure_kind_origins().get(hir_id).is_none()
                    }
                    _ => true,
                };

                if needs_note {
                    let mpi = self.move_data.moves[move_out_indices[0]].path;
                    let place = &self.move_data.move_paths[mpi].place;

                    if let Some(ty) = self.retrieve_type_for_place(place) {
                        let note_msg = match self.describe_place_with_options(
                            place,
                            IncludingDowncast(true),
                        ) {
                            Some(name) => format!("`{}`", name),
                            None => "value".to_owned(),
                        };

                        err.note(&format!(
                            "move occurs because {} has type `{}`, \
                             which does not implement the `Copy` trait",
                            note_msg, ty
                        ));
                    }
                }
            }

            if let Some((_, mut old_err)) = self.move_error_reported
                .insert(move_out_indices, (used_place.clone(), err))
            {
                // Cancel the old error so it doesn't ICE.
                old_err.cancel();
            }
        }
    }

    pub(super) fn report_move_out_while_borrowed(
        &mut self,
        context: Context,
        (place, span): (&Place<'tcx>, Span),
        borrow: &BorrowData<'tcx>,
    ) {
        debug!(
            "report_move_out_while_borrowed: context={:?} place={:?} span={:?} borrow={:?}",
            context, place, span, borrow
        );
        let tcx = self.infcx.tcx;
        let value_msg = match self.describe_place(place) {
            Some(name) => format!("`{}`", name),
            None => "value".to_owned(),
        };
        let borrow_msg = match self.describe_place(&borrow.borrowed_place) {
            Some(name) => format!("`{}`", name),
            None => "value".to_owned(),
        };

        let borrow_spans = self.retrieve_borrow_spans(borrow);
        let borrow_span = borrow_spans.args_or_use();

        let move_spans = self.move_spans(place, context.loc);
        let span = move_spans.args_or_use();

        let mut err = tcx.cannot_move_when_borrowed(
            span,
            &self.describe_place(place).unwrap_or_else(|| "_".to_owned()),
            Origin::Mir,
        );
        err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg));
        err.span_label(span, format!("move out of {} occurs here", value_msg));

        borrow_spans.var_span_label(
            &mut err,
            format!("borrow occurs due to use{}", borrow_spans.describe())
        );

        move_spans.var_span_label(
            &mut err,
            format!("move occurs due to use{}", move_spans.describe())
        );

        self.explain_why_borrow_contains_point(context, borrow, None)
            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
        err.buffer(&mut self.errors_buffer);
    }

    pub(super) fn report_use_while_mutably_borrowed(
        &mut self,
        context: Context,
        (place, _span): (&Place<'tcx>, Span),
        borrow: &BorrowData<'tcx>,
    ) {
        let tcx = self.infcx.tcx;

        let borrow_spans = self.retrieve_borrow_spans(borrow);
        let borrow_span = borrow_spans.args_or_use();

        // Conflicting borrows are reported separately, so only check for move
        // captures.
        let use_spans = self.move_spans(place, context.loc);
        let span = use_spans.var_or_use();

        let mut err = tcx.cannot_use_when_mutably_borrowed(
            span,
            &self.describe_place(place).unwrap_or_else(|| "_".to_owned()),
            borrow_span,
            &self.describe_place(&borrow.borrowed_place)
                .unwrap_or_else(|| "_".to_owned()),
            Origin::Mir,
        );

        borrow_spans.var_span_label(&mut err, {
            let place = &borrow.borrowed_place;
            let desc_place = self.describe_place(place).unwrap_or_else(|| "_".to_owned());

            format!("borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe())
        });

        self.explain_why_borrow_contains_point(context, borrow, None)
            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
        err.buffer(&mut self.errors_buffer);
    }

    pub(super) fn report_conflicting_borrow(
        &mut self,
        context: Context,
        (place, span): (&Place<'tcx>, Span),
        gen_borrow_kind: BorrowKind,
        issued_borrow: &BorrowData<'tcx>,
    ) {
        let issued_spans = self.retrieve_borrow_spans(issued_borrow);
        let issued_span = issued_spans.args_or_use();

        let borrow_spans = self.borrow_spans(span, context.loc);
        let span = borrow_spans.args_or_use();

        let container_name = if issued_spans.for_generator() || borrow_spans.for_generator() {
            "generator"
        } else {
            "closure"
        };

        let desc_place = self.describe_place(place).unwrap_or_else(|| "_".to_owned());
        let tcx = self.infcx.tcx;

        let first_borrow_desc;

        // FIXME: supply non-"" `opt_via` when appropriate
        let mut err = match (
            gen_borrow_kind,
            "immutable",
            "mutable",
            issued_borrow.kind,
            "immutable",
            "mutable",
        ) {
            (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) => {
                first_borrow_desc = "mutable ";
                tcx.cannot_reborrow_already_borrowed(
                    span,
                    &desc_place,
                    "",
                    lft,
                    issued_span,
                    "it",
                    rgt,
                    "",
                    None,
                    Origin::Mir,
                )
            }
            (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => {
                first_borrow_desc = "immutable ";
                tcx.cannot_reborrow_already_borrowed(
                    span,
                    &desc_place,
                    "",
                    lft,
                    issued_span,
                    "it",
                    rgt,
                    "",
                    None,
                    Origin::Mir,
                )
            }

            (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => {
                first_borrow_desc = "first ";
                tcx.cannot_mutably_borrow_multiply(
                    span,
                    &desc_place,
                    "",
                    issued_span,
                    "",
                    None,
                    Origin::Mir,
                )
            }

            (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => {
                first_borrow_desc = "first ";
                tcx.cannot_uniquely_borrow_by_two_closures(
                    span,
                    &desc_place,
                    issued_span,
                    None,
                    Origin::Mir,
                )
            }

            (BorrowKind::Mut { .. }, _, _, BorrowKind::Shallow, _, _)
            | (BorrowKind::Unique, _, _, BorrowKind::Shallow, _, _) => {
                let mut err = tcx.cannot_mutate_in_match_guard(
                    span,
                    issued_span,
                    &desc_place,
                    "mutably borrow",
                    Origin::Mir,
                );
                borrow_spans.var_span_label(
                    &mut err,
                    format!(
                        "borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe()
                    ),
                );
                err.buffer(&mut self.errors_buffer);

                return;
            }

            (BorrowKind::Unique, _, _, _, _, _) => {
                first_borrow_desc = "first ";
                tcx.cannot_uniquely_borrow_by_one_closure(
                    span,
                    container_name,
                    &desc_place,
                    "",
                    issued_span,
                    "it",
                    "",
                    None,
                    Origin::Mir,
                )
            },

            (BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => {
                first_borrow_desc = "first ";
                tcx.cannot_reborrow_already_uniquely_borrowed(
                    span,
                    container_name,
                    &desc_place,
                    "",
                    lft,
                    issued_span,
                    "",
                    None,
                    Origin::Mir,
                )
            }

            (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => {
                first_borrow_desc = "first ";
                tcx.cannot_reborrow_already_uniquely_borrowed(
                    span,
                    container_name,
                    &desc_place,
                    "",
                    lft,
                    issued_span,
                    "",
                    None,
                    Origin::Mir,
                )
            }

            (BorrowKind::Shallow, _, _, BorrowKind::Unique, _, _)
            | (BorrowKind::Shallow, _, _, BorrowKind::Mut { .. }, _, _) => {
                // Shallow borrows are uses from the user's point of view.
                self.report_use_while_mutably_borrowed(context, (place, span), issued_borrow);
                return;
            }
            (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _)
            | (BorrowKind::Shared, _, _, BorrowKind::Shallow, _, _)
            | (BorrowKind::Shallow, _, _, BorrowKind::Shared, _, _)
            | (BorrowKind::Shallow, _, _, BorrowKind::Shallow, _, _) => unreachable!(),
        };

        if issued_spans == borrow_spans {
            borrow_spans.var_span_label(
                &mut err,
                format!("borrows occur due to use of `{}`{}", desc_place, borrow_spans.describe()),
            );
        } else {
            let borrow_place = &issued_borrow.borrowed_place;
            let borrow_place_desc = self.describe_place(borrow_place)
                                        .unwrap_or_else(|| "_".to_owned());
            issued_spans.var_span_label(
                &mut err,
                format!(
                    "first borrow occurs due to use of `{}`{}",
                    borrow_place_desc,
                    issued_spans.describe(),
                ),
            );

            borrow_spans.var_span_label(
                &mut err,
                format!(
                    "second borrow occurs due to use of `{}`{}",
                    desc_place,
                    borrow_spans.describe(),
                ),
            );
        }

        self.explain_why_borrow_contains_point(context, issued_borrow, None)
            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, first_borrow_desc);

        err.buffer(&mut self.errors_buffer);
    }

    /// Reports StorageDeadOrDrop of `place` conflicts with `borrow`.
    ///
    /// This means that some data referenced by `borrow` needs to live
    /// past the point where the StorageDeadOrDrop of `place` occurs.
    /// This is usually interpreted as meaning that `place` has too
    /// short a lifetime. (But sometimes it is more useful to report
    /// it as a more direct conflict between the execution of a
    /// `Drop::drop` with an aliasing borrow.)
    pub(super) fn report_borrowed_value_does_not_live_long_enough(
        &mut self,
        context: Context,
        borrow: &BorrowData<'tcx>,
        place_span: (&Place<'tcx>, Span),
        kind: Option<WriteKind>,
    ) {
        debug!(
            "report_borrowed_value_does_not_live_long_enough(\
             {:?}, {:?}, {:?}, {:?}\
             )",
            context, borrow, place_span, kind
        );

        let drop_span = place_span.1;
        let scope_tree = self.infcx.tcx.region_scope_tree(self.mir_def_id);
        let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
            .last()
            .unwrap();

        let borrow_spans = self.retrieve_borrow_spans(borrow);
        let borrow_span = borrow_spans.var_or_use();

        let proper_span = match *root_place {
            Place::Local(local) => self.mir.local_decls[local].source_info.span,
            _ => drop_span,
        };

        if self.access_place_error_reported
            .contains(&(root_place.clone(), borrow_span))
        {
            debug!(
                "suppressing access_place error when borrow doesn't live long enough for {:?}",
                borrow_span
            );
            return;
        }

        self.access_place_error_reported
            .insert((root_place.clone(), borrow_span));

        if let StorageDeadOrDrop::Destructor(dropped_ty) =
            self.classify_drop_access_kind(&borrow.borrowed_place)
        {
            // If a borrow of path `B` conflicts with drop of `D` (and
            // we're not in the uninteresting case where `B` is a
            // prefix of `D`), then report this as a more interesting
            // destructor conflict.
            if !borrow.borrowed_place.is_prefix_of(place_span.0) {
                self.report_borrow_conflicts_with_destructor(
                    context, borrow, place_span, kind, dropped_ty,
                );
                return;
            }
        }

        let place_desc = self.describe_place(&borrow.borrowed_place);

        let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0));
        let explanation = self.explain_why_borrow_contains_point(context, &borrow, kind_place);

        let err = match (place_desc, explanation) {
            (Some(_), _) if self.is_place_thread_local(root_place) => {
                self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span)
            }
            // If the outlives constraint comes from inside the closure,
            // for example:
            //
            // let x = 0;
            // let y = &x;
            // Box::new(|| y) as Box<Fn() -> &'static i32>
            //
            // then just use the normal error. The closure isn't escaping
            // and `move` will not help here.
            (
                Some(ref name),
                BorrowExplanation::MustBeValidFor {
                    category: category @ ConstraintCategory::Return,
                    from_closure: false,
                    ref region_name,
                    span,
                    ..
                },
            )
            | (
                Some(ref name),
                BorrowExplanation::MustBeValidFor {
                    category: category @ ConstraintCategory::CallArgument,
                    from_closure: false,
                    ref region_name,
                    span,
                    ..
                },
            ) if borrow_spans.for_closure() => self.report_escaping_closure_capture(
                borrow_spans.args_or_use(),
                borrow_span,
                region_name,
                category,
                span,
                &format!("`{}`", name),
            ),
            (
                ref name,
                BorrowExplanation::MustBeValidFor {
                    category: ConstraintCategory::Assignment,
                    from_closure: false,
                    region_name: RegionName {
                        source: RegionNameSource::AnonRegionFromUpvar(upvar_span, ref upvar_name),
                        ..
                    },
                    span,
                    ..
                },
            ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span),
            (Some(name), explanation) => self.report_local_value_does_not_live_long_enough(
                context,
                &name,
                &scope_tree,
                &borrow,
                drop_span,
                borrow_spans,
                explanation,
            ),
            (None, explanation) => self.report_temporary_value_does_not_live_long_enough(
                context,
                &scope_tree,
                &borrow,
                drop_span,
                borrow_spans,
                proper_span,
                explanation,
            ),
        };

        err.buffer(&mut self.errors_buffer);
    }

    fn report_local_value_does_not_live_long_enough(
        &mut self,
        context: Context,
        name: &str,
        scope_tree: &Lrc<ScopeTree>,
        borrow: &BorrowData<'tcx>,
        drop_span: Span,
        borrow_spans: UseSpans,
        explanation: BorrowExplanation,
    ) -> DiagnosticBuilder<'cx> {
        debug!(
            "report_local_value_does_not_live_long_enough(\
             {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\
             )",
            context, name, scope_tree, borrow, drop_span, borrow_spans
        );

        let borrow_span = borrow_spans.var_or_use();
        if let BorrowExplanation::MustBeValidFor {
            category: ConstraintCategory::Return,
            span,
            ref opt_place_desc,
            from_closure: false,
            ..
        } = explanation {
            return self.report_cannot_return_reference_to_local(
                borrow,
                borrow_span,
                span,
                opt_place_desc.as_ref(),
            );
        }

        let mut err = self.infcx.tcx.path_does_not_live_long_enough(
            borrow_span,
            &format!("`{}`", name),
            Origin::Mir,
        );

        if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) {
            let region_name = annotation.emit(&mut err);

            err.span_label(
                borrow_span,
                format!("`{}` would have to be valid for `{}`...", name, region_name),
            );

            if let Some(fn_node_id) = self.infcx.tcx.hir.as_local_node_id(self.mir_def_id) {
                err.span_label(
                    drop_span,
                    format!(
                        "...but `{}` will be dropped here, when the function `{}` returns",
                        name,
                        self.infcx.tcx.hir.name(fn_node_id),
                    ),
                );

                err.note(
                    "functions cannot return a borrow to data owned within the function's scope, \
                     functions can only return borrows to data passed as arguments",
                );
                err.note(
                    "to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch04-02-\
                     references-and-borrowing.html#dangling-references>",
                );
            } else {
                err.span_label(
                    drop_span,
                    format!("...but `{}` dropped here while still borrowed", name),
                );
            }

            if let BorrowExplanation::MustBeValidFor { .. } = explanation {
            } else {
                explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
            }
        } else {
            err.span_label(borrow_span, "borrowed value does not live long enough");
            err.span_label(
                drop_span,
                format!("`{}` dropped here while still borrowed", name),
            );

            let within = if borrow_spans.for_generator() {
                " by generator"
            } else {
                ""
            };

            borrow_spans.args_span_label(
                &mut err,
                format!("value captured here{}", within),
            );

            explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
        }

        err
    }

    fn report_borrow_conflicts_with_destructor(
        &mut self,
        context: Context,
        borrow: &BorrowData<'tcx>,
        (place, drop_span): (&Place<'tcx>, Span),
        kind: Option<WriteKind>,
        dropped_ty: ty::Ty<'tcx>,
    ) {
        debug!(
            "report_borrow_conflicts_with_destructor(\
             {:?}, {:?}, ({:?}, {:?}), {:?}\
             )",
            context, borrow, place, drop_span, kind,
        );

        let borrow_spans = self.retrieve_borrow_spans(borrow);
        let borrow_span = borrow_spans.var_or_use();

        let mut err = self.infcx
            .tcx
            .cannot_borrow_across_destructor(borrow_span, Origin::Mir);

        let what_was_dropped = match self.describe_place(place) {
            Some(name) => format!("`{}`", name.as_str()),
            None => format!("temporary value"),
        };

        let label = match self.describe_place(&borrow.borrowed_place) {
            Some(borrowed) => format!(
                "here, drop of {D} needs exclusive access to `{B}`, \
                 because the type `{T}` implements the `Drop` trait",
                D = what_was_dropped,
                T = dropped_ty,
                B = borrowed
            ),
            None => format!(
                "here is drop of {D}; whose type `{T}` implements the `Drop` trait",
                D = what_was_dropped,
                T = dropped_ty
            ),
        };
        err.span_label(drop_span, label);

        // Only give this note and suggestion if they could be relevant.
        let explanation =
            self.explain_why_borrow_contains_point(context, borrow, kind.map(|k| (k, place)));
        match explanation {
            BorrowExplanation::UsedLater { .. }
            | BorrowExplanation::UsedLaterWhenDropped { .. } => {
                err.note("consider using a `let` binding to create a longer lived value");
            }
            _ => {}
        }

        explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");

        err.buffer(&mut self.errors_buffer);
    }

    fn report_thread_local_value_does_not_live_long_enough(
        &mut self,
        drop_span: Span,
        borrow_span: Span,
    ) -> DiagnosticBuilder<'cx> {
        debug!(
            "report_thread_local_value_does_not_live_long_enough(\
             {:?}, {:?}\
             )",
            drop_span, borrow_span
        );

        let mut err = self.infcx
            .tcx
            .thread_local_value_does_not_live_long_enough(borrow_span, Origin::Mir);

        err.span_label(
            borrow_span,
            "thread-local variables cannot be borrowed beyond the end of the function",
        );
        err.span_label(drop_span, "end of enclosing function is here");

        err
    }

    fn report_temporary_value_does_not_live_long_enough(
        &mut self,
        context: Context,
        scope_tree: &Lrc<ScopeTree>,
        borrow: &BorrowData<'tcx>,
        drop_span: Span,
        borrow_spans: UseSpans,
        proper_span: Span,
        explanation: BorrowExplanation,
    ) -> DiagnosticBuilder<'cx> {
        debug!(
            "report_temporary_value_does_not_live_long_enough(\
             {:?}, {:?}, {:?}, {:?}, {:?}\
             )",
            context, scope_tree, borrow, drop_span, proper_span
        );

        if let BorrowExplanation::MustBeValidFor {
            category: ConstraintCategory::Return,
            span,
            from_closure: false,
            ..
        } = explanation {
            return self.report_cannot_return_reference_to_local(
                borrow,
                proper_span,
                span,
                None,
            );
        }

        let tcx = self.infcx.tcx;
        let mut err = tcx.temporary_value_borrowed_for_too_long(proper_span, Origin::Mir);
        err.span_label(
            proper_span,
            "creates a temporary which is freed while still in use",
        );
        err.span_label(
            drop_span,
            "temporary value is freed at the end of this statement",
        );

        match explanation {
            BorrowExplanation::UsedLater(..)
            | BorrowExplanation::UsedLaterInLoop(..)
            | BorrowExplanation::UsedLaterWhenDropped { .. } => {
                // Only give this note and suggestion if it could be relevant.
                err.note("consider using a `let` binding to create a longer lived value");
            }
            _ => {}
        }
        explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");

        let within = if borrow_spans.for_generator() {
            " by generator"
        } else {
            ""
        };

        borrow_spans.args_span_label(
            &mut err,
            format!("value captured here{}", within),
        );

        err
    }

    fn report_cannot_return_reference_to_local(
        &self,
        borrow: &BorrowData<'tcx>,
        borrow_span: Span,
        return_span: Span,
        opt_place_desc: Option<&String>,
    ) -> DiagnosticBuilder<'cx> {
        let tcx = self.infcx.tcx;

        // FIXME use a better heuristic than Spans
        let reference_desc = if return_span == self.mir.source_info(borrow.reserve_location).span {
            "reference to"
        } else {
            "value referencing"
        };

        let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
            let local_kind = match borrow.borrowed_place {
                Place::Local(local) => {
                    match self.mir.local_kind(local) {
                        LocalKind::ReturnPointer
                        | LocalKind::Temp => bug!("temporary or return pointer with a name"),
                        LocalKind::Var => "local variable ",
                        LocalKind::Arg
                        if !self.mir.upvar_decls.is_empty()
                            && local == Local::new(1) => {
                            "variable captured by `move` "
                        }
                        LocalKind::Arg => {
                            "function parameter "
                        }
                    }
                }
                _ => "local data ",
            };
            (
                format!("{}`{}`", local_kind, place_desc),
                format!("`{}` is borrowed here", place_desc),
            )
        } else {
            let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
                .last()
                .unwrap();
            let local = if let Place::Local(local) = *root_place {
                local
            } else {
                bug!("report_cannot_return_reference_to_local: not a local")
            };
            match self.mir.local_kind(local) {
                LocalKind::ReturnPointer | LocalKind::Temp => {
                    (
                        "temporary value".to_string(),
                        "temporary value created here".to_string(),
                    )
                }
                LocalKind::Arg => {
                    (
                        "function parameter".to_string(),
                        "function parameter borrowed here".to_string(),
                    )
                },
                LocalKind::Var => bug!("local variable without a name"),
            }
        };

        let mut err = tcx.cannot_return_reference_to_local(
            return_span,
            reference_desc,
            &place_desc,
            Origin::Mir,
        );

        if return_span != borrow_span {
            err.span_label(borrow_span, note);
        }

        err
    }

    fn report_escaping_closure_capture(
        &mut self,
        args_span: Span,
        var_span: Span,
        fr_name: &RegionName,
        category: ConstraintCategory,
        constraint_span: Span,
        captured_var: &str,
    ) -> DiagnosticBuilder<'cx> {
        let tcx = self.infcx.tcx;

        let mut err = tcx.cannot_capture_in_long_lived_closure(
            args_span,
            captured_var,
            var_span,
          Origin::Mir,
        );

        let suggestion = match tcx.sess.source_map().span_to_snippet(args_span) {
            Ok(string) => format!("move {}", string),
            Err(_) => "move |<args>| <body>".to_string()
        };

        err.span_suggestion_with_applicability(
            args_span,
            &format!("to force the closure to take ownership of {} (and any \
                      other referenced variables), use the `move` keyword",
                      captured_var),
            suggestion,
            Applicability::MachineApplicable,
        );

        match category {
            ConstraintCategory::Return => {
                err.span_note(constraint_span, &format!("closure is returned here"));
            }
            ConstraintCategory::CallArgument => {
                fr_name.highlight_region_name(&mut err);
                err.span_note(
                    constraint_span,
                    &format!("function requires argument type to outlive `{}`", fr_name),
                );
            }
            _ => bug!("report_escaping_closure_capture called with unexpected constraint \
                       category: `{:?}`", category),
        }
        err
    }

    fn report_escaping_data(
        &mut self,
        borrow_span: Span,
        name: &Option<String>,
        upvar_span: Span,
        upvar_name: &str,
        escape_span: Span,
    ) -> DiagnosticBuilder<'cx> {
        let tcx = self.infcx.tcx;

        let escapes_from = if tcx.is_closure(self.mir_def_id) {
            let tables = tcx.typeck_tables_of(self.mir_def_id);
            let mir_hir_id = tcx.hir.def_index_to_hir_id(self.mir_def_id.index);
            match tables.node_id_to_type(mir_hir_id).sty {
                ty::Closure(..) => "closure",
                ty::Generator(..) => "generator",
                _ => bug!("Closure body doesn't have a closure or generator type"),
            }
        } else {
            "function"
        };

        let mut err = tcx.borrowed_data_escapes_closure(escape_span, escapes_from, Origin::Mir);

        err.span_label(
            upvar_span,
            format!(
                "`{}` is declared here, outside of the {} body",
                upvar_name, escapes_from
            ),
        );

        err.span_label(
            borrow_span,
            format!(
                "borrow is only valid in the {} body",
                escapes_from
            ),
        );

        if let Some(name) = name {
            err.span_label(
                escape_span,
                format!("reference to `{}` escapes the {} body here", name, escapes_from),
            );
        } else {
            err.span_label(
                escape_span,
                format!("reference escapes the {} body here", escapes_from),
            );
        }

        err
    }

    fn get_moved_indexes(&mut self, context: Context, mpi: MovePathIndex) -> Vec<MoveSite> {
        let mir = self.mir;

        let mut stack = Vec::new();
        stack.extend(mir.predecessor_locations(context.loc).map(|predecessor| {
            let is_back_edge = context.loc.dominates(predecessor, &self.dominators);
            (predecessor, is_back_edge)
        }));

        let mut visited = FxHashSet::default();
        let mut result = vec![];

        'dfs: while let Some((location, is_back_edge)) = stack.pop() {
            debug!(
                "report_use_of_moved_or_uninitialized: (current_location={:?}, back_edge={})",
                location, is_back_edge
            );

            if !visited.insert(location) {
                continue;
            }

            // check for moves
            let stmt_kind = mir[location.block]
                .statements
                .get(location.statement_index)
                .map(|s| &s.kind);
            if let Some(StatementKind::StorageDead(..)) = stmt_kind {
                // this analysis only tries to find moves explicitly
                // written by the user, so we ignore the move-outs
                // created by `StorageDead` and at the beginning
                // of a function.
            } else {
                // If we are found a use of a.b.c which was in error, then we want to look for
                // moves not only of a.b.c but also a.b and a.
                //
                // Note that the moves data already includes "parent" paths, so we don't have to
                // worry about the other case: that is, if there is a move of a.b.c, it is already
                // marked as a move of a.b and a as well, so we will generate the correct errors
                // there.
                let mut mpis = vec![mpi];
                let move_paths = &self.move_data.move_paths;
                mpis.extend(move_paths[mpi].parents(move_paths));

                for moi in &self.move_data.loc_map[location] {
                    debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi);
                    if mpis.contains(&self.move_data.moves[*moi].path) {
                        debug!("report_use_of_moved_or_uninitialized: found");
                        result.push(MoveSite {
                            moi: *moi,
                            traversed_back_edge: is_back_edge,
                        });

                        // Strictly speaking, we could continue our DFS here. There may be
                        // other moves that can reach the point of error. But it is kind of
                        // confusing to highlight them.
                        //
                        // Example:
                        //
                        // ```
                        // let a = vec![];
                        // let b = a;
                        // let c = a;
                        // drop(a); // <-- current point of error
                        // ```
                        //
                        // Because we stop the DFS here, we only highlight `let c = a`,
                        // and not `let b = a`. We will of course also report an error at
                        // `let c = a` which highlights `let b = a` as the move.
                        continue 'dfs;
                    }
                }
            }

            // check for inits
            let mut any_match = false;
            drop_flag_effects::for_location_inits(
                self.infcx.tcx,
                self.mir,
                self.move_data,
                location,
                |m| {
                    if m == mpi {
                        any_match = true;
                    }
                },
            );
            if any_match {
                continue 'dfs;
            }

            stack.extend(mir.predecessor_locations(location).map(|predecessor| {
                let back_edge = location.dominates(predecessor, &self.dominators);
                (predecessor, is_back_edge || back_edge)
            }));
        }

        result
    }

    pub(super) fn report_illegal_mutation_of_borrowed(
        &mut self,
        context: Context,
        (place, span): (&Place<'tcx>, Span),
        loan: &BorrowData<'tcx>,
    ) {
        let loan_spans = self.retrieve_borrow_spans(loan);
        let loan_span = loan_spans.args_or_use();

        let tcx = self.infcx.tcx;
        let mut err = if loan.kind == BorrowKind::Shallow {
            tcx.cannot_mutate_in_match_guard(
                span,
                loan_span,
                &self.describe_place(place).unwrap_or_else(|| "_".to_owned()),
                "assign",
                Origin::Mir,
            )
        } else {
            tcx.cannot_assign_to_borrowed(
                span,
                loan_span,
                &self.describe_place(place).unwrap_or_else(|| "_".to_owned()),
                Origin::Mir,
            )
        };

        loan_spans.var_span_label(
            &mut err,
            format!("borrow occurs due to use{}", loan_spans.describe()),
        );

        self.explain_why_borrow_contains_point(context, loan, None)
            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");

        err.buffer(&mut self.errors_buffer);
    }

    /// Reports an illegal reassignment; for example, an assignment to
    /// (part of) a non-`mut` local that occurs potentially after that
    /// local has already been initialized. `place` is the path being
    /// assigned; `err_place` is a place providing a reason why
    /// `place` is not mutable (e.g. the non-`mut` local `x` in an
    /// assignment to `x.f`).
    pub(super) fn report_illegal_reassignment(
        &mut self,
        _context: Context,
        (place, span): (&Place<'tcx>, Span),
        assigned_span: Span,
        err_place: &Place<'tcx>,
    ) {
        let (from_arg, local_decl) = if let Place::Local(local) = *err_place {
            if let LocalKind::Arg = self.mir.local_kind(local) {
                (true, Some(&self.mir.local_decls[local]))
            } else {
                (false, Some(&self.mir.local_decls[local]))
            }
        } else {
            (false, None)
        };

        // If root local is initialized immediately (everything apart from let
        // PATTERN;) then make the error refer to that local, rather than the
        // place being assigned later.
        let (place_description, assigned_span) = match local_decl {
            Some(LocalDecl {
                is_user_variable: Some(ClearCrossCrate::Clear),
                ..
            })
            | Some(LocalDecl {
                is_user_variable:
                    Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
                        opt_match_place: None,
                        ..
                    }))),
                ..
            })
            | Some(LocalDecl {
                is_user_variable: None,
                ..
            })
            | None => (self.describe_place(place), assigned_span),
            Some(decl) => (self.describe_place(err_place), decl.source_info.span),
        };

        let mut err = self.infcx.tcx.cannot_reassign_immutable(
            span,
            place_description.as_ref().map(AsRef::as_ref).unwrap_or("_"),
            from_arg,
            Origin::Mir,
        );
        let msg = if from_arg {
            "cannot assign to immutable argument"
        } else {
            "cannot assign twice to immutable variable"
        };
        if span != assigned_span {
            if !from_arg {
                let value_msg = match place_description {
                    Some(name) => format!("`{}`", name),
                    None => "value".to_owned(),
                };
                err.span_label(assigned_span, format!("first assignment to {}", value_msg));
            }
        }
        if let Some(decl) = local_decl {
            if let Some(name) = decl.name {
                if decl.can_be_made_mutable() {
                    err.span_suggestion_with_applicability(
                        decl.source_info.span,
                        "make this binding mutable",
                        format!("mut {}", name),
                        Applicability::MachineApplicable,
                    );
                }
            }
        }
        err.span_label(span, msg);
        err.buffer(&mut self.errors_buffer);
    }
}

pub(super) struct IncludingDowncast(bool);

/// Which case a StorageDeadOrDrop is for.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum StorageDeadOrDrop<'tcx> {
    LocalStorageDead,
    BoxedStorageDead,
    Destructor(ty::Ty<'tcx>),
}

impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {

    /// Adds a suggestion when a closure is invoked twice with a moved variable.
    ///
    /// ```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_closure_invoked_twice_with_moved_variable_suggestion(
        &self,
        location: Location,
        place: &Place<'tcx>,
        diag: &mut DiagnosticBuilder<'_>,
    ) {
        let mut target = place.local();
        debug!(
            "add_closure_invoked_twice_with_moved_variable_suggestion: location={:?} place={:?} \
             target={:?}",
             location, place, target,
        );
        for stmt in &self.mir[location.block].statements[location.statement_index..] {
            debug!(
                "add_closure_invoked_twice_with_moved_variable_suggestion: stmt={:?} \
                 target={:?}",
                 stmt, target,
            );
            if let StatementKind::Assign(into, box Rvalue::Use(from)) = &stmt.kind {
                debug!(
                    "add_closure_invoked_twice_with_moved_variable_suggestion: into={:?} \
                     from={:?}",
                     into, from,
                );
                match from {
                    Operand::Copy(ref place) |
                    Operand::Move(ref place) if target == place.local() =>
                        target = into.local(),
                    _ => {},
                }
            }
        }


        let terminator = self.mir[location.block].terminator();
        debug!(
            "add_closure_invoked_twice_with_moved_variable_suggestion: terminator={:?}",
            terminator,
        );
        if let TerminatorKind::Call {
            func: Operand::Constant(box Constant {
                literal: ty::Const { ty: &ty::TyS { sty: ty::TyKind::FnDef(id, _), ..  }, ..  },
                ..
            }),
            args,
            ..
        } = &terminator.kind {
            debug!("add_closure_invoked_twice_with_moved_variable_suggestion: 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() =>
                        place.local().unwrap(),
                    _ => return,
                };
                debug!(
                    "add_closure_invoked_twice_with_moved_variable_suggestion: closure={:?}",
                     closure,
                );

                if let ty::TyKind::Closure(did, _substs) = self.mir.local_decls[closure].ty.sty {
                    let node_id = match self.infcx.tcx.hir.as_local_node_id(did) {
                        Some(node_id) => node_id,
                        _ => return,
                    };
                    let hir_id = self.infcx.tcx.hir.node_to_hir_id(node_id);

                    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,
                            ),
                        );
                    }
                }
            }
        }
    }

    /// 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: &Place<'tcx>) -> Option<String> {
        self.describe_place_with_options(place, 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: &Place<'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: &Place<'tcx>,
        buf: &mut String,
        mut autoderef: bool,
        including_downcast: &IncludingDowncast,
    ) -> Result<(), ()> {
        match *place {
            Place::Promoted(_) => {
                buf.push_str("promoted");
            }
            Place::Local(local) => {
                self.append_local_to_string(local, buf)?;
            }
            Place::Static(ref static_) => {
                buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
            }
            Place::Projection(ref proj) => {
                match proj.elem {
                    ProjectionElem::Deref => {
                        let upvar_field_projection =
                            place.is_upvar_field_projection(self.mir, &self.infcx.tcx);
                        if let Some(field) = upvar_field_projection {
                            let var_index = field.index();
                            let name = self.mir.upvar_decls[var_index].debug_name.to_string();
                            if self.mir.upvar_decls[var_index].by_ref {
                                buf.push_str(&name);
                            } else {
                                buf.push_str(&format!("*{}", &name));
                            }
                        } else {
                            if autoderef {
                                self.append_place_to_string(
                                    &proj.base,
                                    buf,
                                    autoderef,
                                    &including_downcast,
                                )?;
                            } else if let Place::Local(local) = proj.base {
                                if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
                                    self.mir.local_decls[local].is_user_variable
                                {
                                    self.append_place_to_string(
                                        &proj.base,
                                        buf,
                                        autoderef,
                                        &including_downcast,
                                    )?;
                                } else {
                                    buf.push_str(&"*");
                                    self.append_place_to_string(
                                        &proj.base,
                                        buf,
                                        autoderef,
                                        &including_downcast,
                                    )?;
                                }
                            } else {
                                buf.push_str(&"*");
                                self.append_place_to_string(
                                    &proj.base,
                                    buf,
                                    autoderef,
                                    &including_downcast,
                                )?;
                            }
                        }
                    }
                    ProjectionElem::Downcast(..) => {
                        self.append_place_to_string(
                            &proj.base,
                            buf,
                            autoderef,
                            &including_downcast,
                        )?;
                        if including_downcast.0 {
                            return Err(());
                        }
                    }
                    ProjectionElem::Field(field, _ty) => {
                        autoderef = true;

                        let upvar_field_projection =
                            place.is_upvar_field_projection(self.mir, &self.infcx.tcx);
                        if let Some(field) = upvar_field_projection {
                            let var_index = field.index();
                            let name = self.mir.upvar_decls[var_index].debug_name.to_string();
                            buf.push_str(&name);
                        } else {
                            let field_name = self.describe_field(&proj.base, field);
                            self.append_place_to_string(
                                &proj.base,
                                buf,
                                autoderef,
                                &including_downcast,
                            )?;
                            buf.push_str(&format!(".{}", field_name));
                        }
                    }
                    ProjectionElem::Index(index) => {
                        autoderef = true;

                        self.append_place_to_string(
                            &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(
                            &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, then `Err` is returned
    fn append_local_to_string(&self, local_index: Local, buf: &mut String) -> Result<(), ()> {
        let local = &self.mir.local_decls[local_index];
        match local.name {
            Some(name) => {
                buf.push_str(&name.to_string());
                Ok(())
            }
            None => Err(()),
        }
    }

    /// End-user visible description of the `field`nth field of `base`
    fn describe_field(&self, base: &Place, field: Field) -> String {
        match *base {
            Place::Local(local) => {
                let local = &self.mir.local_decls[local];
                self.describe_field_from_ty(&local.ty, field)
            }
            Place::Promoted(ref prom) => self.describe_field_from_ty(&prom.1, field),
            Place::Static(ref static_) => self.describe_field_from_ty(&static_.ty, field),
            Place::Projection(ref proj) => match proj.elem {
                ProjectionElem::Deref => self.describe_field(&proj.base, field),
                ProjectionElem::Downcast(def, variant_index) =>
                    def.variants[variant_index].fields[field.index()].ident.to_string(),
                ProjectionElem::Field(_, field_type) => {
                    self.describe_field_from_ty(&field_type, field)
                }
                ProjectionElem::Index(..)
                | ProjectionElem::ConstantIndex { .. }
                | ProjectionElem::Subslice { .. } => {
                    self.describe_field(&proj.base, field)
                }
            },
        }
    }

    /// End-user visible description of the `field_index`nth field of `ty`
    fn describe_field_from_ty(&self, ty: &ty::Ty, field: Field) -> 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)
        } else {
            match ty.sty {
                ty::Adt(def, _) => if def.is_enum() {
                    field.index().to_string()
                } else {
                    def.non_enum_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)
                }
                ty::Array(ty, _) | ty::Slice(ty) => self.describe_field_from_ty(&ty, field),
                ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
                    // Convert the def-id into a node-id. node-ids are only valid for
                    // the local code in the current crate, so this returns an `Option` 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 node_id = self.infcx.tcx.hir.as_local_node_id(def_id).unwrap();
                    let freevar = self.infcx
                        .tcx
                        .with_freevars(node_id, |fv| fv[field.index()]);

                    self.infcx.tcx.hir.name(freevar.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.sty
                    );
                }
            }
        }
    }

    /// Retrieve type of a place for the current MIR representation
    fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option<ty::Ty> {
        match place {
            Place::Local(local) => {
                let local = &self.mir.local_decls[*local];
                Some(local.ty)
            }
            Place::Promoted(ref prom) => Some(prom.1),
            Place::Static(ref st) => Some(st.ty),
            Place::Projection(ref proj) => match proj.elem {
                ProjectionElem::Field(_, ty) => Some(ty),
                _ => None,
            },
        }
    }

    /// Check if a place is a thread-local static.
    pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
        if let Place::Static(statik) = place {
            let attrs = self.infcx.tcx.get_attrs(statik.def_id);
            let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));

            debug!(
                "is_place_thread_local: attrs={:?} is_thread_local={:?}",
                attrs, is_thread_local
            );
            is_thread_local
        } else {
            debug!("is_place_thread_local: no");
            false
        }
    }

    fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> {
        let tcx = self.infcx.tcx;
        match place {
            Place::Local(_) | Place::Static(_) | Place::Promoted(_) => {
                StorageDeadOrDrop::LocalStorageDead
            }
            Place::Projection(box PlaceProjection { base, elem }) => {
                let base_access = self.classify_drop_access_kind(base);
                match elem {
                    ProjectionElem::Deref => match base_access {
                        StorageDeadOrDrop::LocalStorageDead
                        | StorageDeadOrDrop::BoxedStorageDead => {
                            assert!(
                                base.ty(self.mir, tcx).to_ty(tcx).is_box(),
                                "Drop of value behind a reference or raw pointer"
                            );
                            StorageDeadOrDrop::BoxedStorageDead
                        }
                        StorageDeadOrDrop::Destructor(_) => base_access,
                    },
                    ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
                        let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
                        match base_ty.sty {
                            ty::Adt(def, _) if def.has_dtor(tcx) => {
                                // Report the outermost adt with a destructor
                                match base_access {
                                    StorageDeadOrDrop::Destructor(_) => base_access,
                                    StorageDeadOrDrop::LocalStorageDead
                                    | StorageDeadOrDrop::BoxedStorageDead => {
                                        StorageDeadOrDrop::Destructor(base_ty)
                                    }
                                }
                            }
                            _ => base_access,
                        }
                    }

                    ProjectionElem::ConstantIndex { .. }
                    | ProjectionElem::Subslice { .. }
                    | ProjectionElem::Index(_) => base_access,
                }
            }
        }
    }

    /// Annotate argument and return type of function and closure with (synthesized) lifetime for
    /// borrow of local value that does not live long enough.
    fn annotate_argument_and_return_for_borrow(
        &self,
        borrow: &BorrowData<'tcx>,
    ) -> Option<AnnotatedBorrowFnSignature> {
        // Define a fallback for when we can't match a closure.
        let fallback = || {
            let is_closure = self.infcx.tcx.is_closure(self.mir_def_id);
            if is_closure {
                None
            } else {
                let ty = self.infcx.tcx.type_of(self.mir_def_id);
                match ty.sty {
                    ty::TyKind::FnDef(_, _) | ty::TyKind::FnPtr(_) => self.annotate_fn_sig(
                        self.mir_def_id,
                        self.infcx.tcx.fn_sig(self.mir_def_id),
                    ),
                    _ => None,
                }
            }
        };

        // In order to determine whether we need to annotate, we need to check whether the reserve
        // place was an assignment into a temporary.
        //
        // If it was, we check whether or not that temporary is eventually assigned into the return
        // place. If it was, we can add annotations about the function's return type and arguments
        // and it'll make sense.
        let location = borrow.reserve_location;
        debug!(
            "annotate_argument_and_return_for_borrow: location={:?}",
            location
        );
        if let Some(&Statement { kind: StatementKind::Assign(ref reservation, _), ..})
             = &self.mir[location.block].statements.get(location.statement_index)
        {
            debug!(
                "annotate_argument_and_return_for_borrow: reservation={:?}",
                reservation
            );
            // Check that the initial assignment of the reserve location is into a temporary.
            let mut target = *match reservation {
                Place::Local(local) if self.mir.local_kind(*local) == LocalKind::Temp => local,
                _ => return None,
            };

            // Next, look through the rest of the block, checking if we are assigning the
            // `target` (that is, the place that contains our borrow) to anything.
            let mut annotated_closure = None;
            for stmt in &self.mir[location.block].statements[location.statement_index + 1..] {
                debug!(
                    "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
                    target, stmt
                );
                if let StatementKind::Assign(Place::Local(assigned_to), box rvalue) = &stmt.kind
                {
                    debug!(
                        "annotate_argument_and_return_for_borrow: assigned_to={:?} \
                         rvalue={:?}",
                        assigned_to, rvalue
                    );
                    // Check if our `target` was captured by a closure.
                    if let Rvalue::Aggregate(
                        box AggregateKind::Closure(def_id, substs),
                        operands,
                    ) = rvalue
                    {
                        for operand in operands {
                            let assigned_from = match operand {
                                Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
                                    assigned_from
                                }
                                _ => continue,
                            };
                            debug!(
                                "annotate_argument_and_return_for_borrow: assigned_from={:?}",
                                assigned_from
                            );

                            // Find the local from the operand.
                            let assigned_from_local = match assigned_from.local() {
                                Some(local) => local,
                                None => continue,
                            };

                            if assigned_from_local != target {
                                continue;
                            }

                            // If a closure captured our `target` and then assigned
                            // into a place then we should annotate the closure in
                            // case it ends up being assigned into the return place.
                            annotated_closure = self.annotate_fn_sig(
                                *def_id,
                                self.infcx.closure_sig(*def_id, *substs),
                            );
                            debug!(
                                "annotate_argument_and_return_for_borrow: \
                                 annotated_closure={:?} assigned_from_local={:?} \
                                 assigned_to={:?}",
                                annotated_closure, assigned_from_local, assigned_to
                            );

                            if *assigned_to == mir::RETURN_PLACE {
                                // If it was assigned directly into the return place, then
                                // return now.
                                return annotated_closure;
                            } else {
                                // Otherwise, update the target.
                                target = *assigned_to;
                            }
                        }

                        // If none of our closure's operands matched, then skip to the next
                        // statement.
                        continue;
                    }

                    // Otherwise, look at other types of assignment.
                    let assigned_from = match rvalue {
                        Rvalue::Ref(_, _, assigned_from) => assigned_from,
                        Rvalue::Use(operand) => match operand {
                            Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
                                assigned_from
                            }
                            _ => continue,
                        },
                        _ => continue,
                    };
                    debug!(
                        "annotate_argument_and_return_for_borrow: \
                         assigned_from={:?}",
                        assigned_from,
                    );

                    // Find the local from the rvalue.
                    let assigned_from_local = match assigned_from.local() {
                        Some(local) => local,
                        None => continue,
                    };
                    debug!(
                        "annotate_argument_and_return_for_borrow: \
                         assigned_from_local={:?}",
                        assigned_from_local,
                    );

                    // Check if our local matches the target - if so, we've assigned our
                    // borrow to a new place.
                    if assigned_from_local != target {
                        continue;
                    }

                    // If we assigned our `target` into a new place, then we should
                    // check if it was the return place.
                    debug!(
                        "annotate_argument_and_return_for_borrow: \
                         assigned_from_local={:?} assigned_to={:?}",
                        assigned_from_local, assigned_to
                    );
                    if *assigned_to == mir::RETURN_PLACE {
                        // If it was then return the annotated closure if there was one,
                        // else, annotate this function.
                        return annotated_closure.or_else(fallback);
                    }

                    // If we didn't assign into the return place, then we just update
                    // the target.
                    target = *assigned_to;
                }
            }

            // Check the terminator if we didn't find anything in the statements.
            let terminator = &self.mir[location.block].terminator();
            debug!(
                "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}",
                target, terminator
            );
            if let TerminatorKind::Call {
                destination: Some((Place::Local(assigned_to), _)),
                args,
                ..
            } = &terminator.kind
            {
                debug!(
                    "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}",
                    assigned_to, args
                );
                for operand in args {
                    let assigned_from = match operand {
                        Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
                            assigned_from
                        }
                        _ => continue,
                    };
                    debug!(
                        "annotate_argument_and_return_for_borrow: assigned_from={:?}",
                        assigned_from,
                    );

                    if let Some(assigned_from_local) = assigned_from.local() {
                        debug!(
                            "annotate_argument_and_return_for_borrow: assigned_from_local={:?}",
                            assigned_from_local,
                        );

                        if *assigned_to == mir::RETURN_PLACE && assigned_from_local == target {
                            return annotated_closure.or_else(fallback);
                        }
                    }
                }
            }
        }

        // If we haven't found an assignment into the return place, then we need not add
        // any annotations.
        debug!("annotate_argument_and_return_for_borrow: none found");
        None
    }

    /// Annotate the first argument and return type of a function signature if they are
    /// references.
    fn annotate_fn_sig(
        &self,
        did: DefId,
        sig: ty::PolyFnSig<'tcx>,
    ) -> Option<AnnotatedBorrowFnSignature> {
        debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
        let is_closure = self.infcx.tcx.is_closure(did);
        let fn_node_id = self.infcx.tcx.hir.as_local_node_id(did)?;
        let fn_decl = self.infcx.tcx.hir.fn_decl(fn_node_id)?;

        // We need to work out which arguments to highlight. We do this by looking
        // at the return type, where there are three cases:
        //
        // 1. If there are named arguments, then we should highlight the return type and
        //    highlight any of the arguments that are also references with that lifetime.
        //    If there are no arguments that have the same lifetime as the return type,
        //    then don't highlight anything.
        // 2. The return type is a reference with an anonymous lifetime. If this is
        //    the case, then we can take advantage of (and teach) the lifetime elision
        //    rules.
        //
        //    We know that an error is being reported. So the arguments and return type
        //    must satisfy the elision rules. Therefore, if there is a single argument
        //    then that means the return type and first (and only) argument have the same
        //    lifetime and the borrow isn't meeting that, we can highlight the argument
        //    and return type.
        //
        //    If there are multiple arguments then the first argument must be self (else
        //    it would not satisfy the elision rules), so we can highlight self and the
        //    return type.
        // 3. The return type is not a reference. In this case, we don't highlight
        //    anything.
        let return_ty = sig.output();
        match return_ty.skip_binder().sty {
            ty::TyKind::Ref(return_region, _, _) if return_region.has_name() && !is_closure => {
                // This is case 1 from above, return type is a named reference so we need to
                // search for relevant arguments.
                let mut arguments = Vec::new();
                for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
                    if let ty::TyKind::Ref(argument_region, _, _) = argument.sty {
                        if argument_region == return_region {
                            // Need to use the `rustc::ty` types to compare against the
                            // `return_region`. Then use the `rustc::hir` type to get only
                            // the lifetime span.
                            if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].node {
                                // With access to the lifetime, we can get
                                // the span of it.
                                arguments.push((*argument, lifetime.span));
                            } else {
                                bug!("ty type is a ref but hir type is not");
                            }
                        }
                    }
                }

                // We need to have arguments. This shouldn't happen, but it's worth checking.
                if arguments.is_empty() {
                    return None;
                }

                // We use a mix of the HIR and the Ty types to get information
                // as the HIR doesn't have full types for closure arguments.
                let return_ty = *sig.output().skip_binder();
                let mut return_span = fn_decl.output.span();
                if let hir::FunctionRetTy::Return(ty) = fn_decl.output {
                    if let hir::TyKind::Rptr(lifetime, _) = ty.into_inner().node {
                        return_span = lifetime.span;
                    }
                }

                Some(AnnotatedBorrowFnSignature::NamedFunction {
                    arguments,
                    return_ty,
                    return_span,
                })
            }
            ty::TyKind::Ref(_, _, _) if is_closure => {
                // This is case 2 from above but only for closures, return type is anonymous
                // reference so we select
                // the first argument.
                let argument_span = fn_decl.inputs.first()?.span;
                let argument_ty = sig.inputs().skip_binder().first()?;

                // Closure arguments are wrapped in a tuple, so we need to get the first
                // from that.
                if let ty::TyKind::Tuple(elems) = argument_ty.sty {
                    let argument_ty = elems.first()?;
                    if let ty::TyKind::Ref(_, _, _) = argument_ty.sty {
                        return Some(AnnotatedBorrowFnSignature::Closure {
                            argument_ty,
                            argument_span,
                        });
                    }
                }

                None
            }
            ty::TyKind::Ref(_, _, _) => {
                // This is also case 2 from above but for functions, return type is still an
                // anonymous reference so we select the first argument.
                let argument_span = fn_decl.inputs.first()?.span;
                let argument_ty = sig.inputs().skip_binder().first()?;

                let return_span = fn_decl.output.span();
                let return_ty = *sig.output().skip_binder();

                // We expect the first argument to be a reference.
                match argument_ty.sty {
                    ty::TyKind::Ref(_, _, _) => {}
                    _ => return None,
                }

                Some(AnnotatedBorrowFnSignature::AnonymousFunction {
                    argument_ty,
                    argument_span,
                    return_ty,
                    return_span,
                })
            }
            _ => {
                // This is case 3 from above, return type is not a reference so don't highlight
                // anything.
                None
            }
        }
    }
}

#[derive(Debug)]
enum AnnotatedBorrowFnSignature<'tcx> {
    NamedFunction {
        arguments: Vec<(ty::Ty<'tcx>, Span)>,
        return_ty: ty::Ty<'tcx>,
        return_span: Span,
    },
    AnonymousFunction {
        argument_ty: ty::Ty<'tcx>,
        argument_span: Span,
        return_ty: ty::Ty<'tcx>,
        return_span: Span,
    },
    Closure {
        argument_ty: ty::Ty<'tcx>,
        argument_span: Span,
    },
}

impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
    /// Annotate the provided diagnostic with information about borrow from the fn signature that
    /// helps explain.
    fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
        match self {
            AnnotatedBorrowFnSignature::Closure {
                argument_ty,
                argument_span,
            } => {
                diag.span_label(
                    *argument_span,
                    format!("has type `{}`", self.get_name_for_ty(argument_ty, 0)),
                );

                self.get_region_name_for_ty(argument_ty, 0)
            }
            AnnotatedBorrowFnSignature::AnonymousFunction {
                argument_ty,
                argument_span,
                return_ty,
                return_span,
            } => {
                let argument_ty_name = self.get_name_for_ty(argument_ty, 0);
                diag.span_label(*argument_span, format!("has type `{}`", argument_ty_name));

                let return_ty_name = self.get_name_for_ty(return_ty, 0);
                let types_equal = return_ty_name == argument_ty_name;
                diag.span_label(
                    *return_span,
                    format!(
                        "{}has type `{}`",
                        if types_equal { "also " } else { "" },
                        return_ty_name,
                    ),
                );

                diag.note(
                    "argument and return type have the same lifetime due to lifetime elision rules",
                );
                diag.note(
                    "to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch10-03-\
                     lifetime-syntax.html#lifetime-elision>",
                );

                self.get_region_name_for_ty(return_ty, 0)
            }
            AnnotatedBorrowFnSignature::NamedFunction {
                arguments,
                return_ty,
                return_span,
            } => {
                // Region of return type and arguments checked to be the same earlier.
                let region_name = self.get_region_name_for_ty(return_ty, 0);
                for (_, argument_span) in arguments {
                    diag.span_label(*argument_span, format!("has lifetime `{}`", region_name));
                }

                diag.span_label(
                    *return_span,
                    format!("also has lifetime `{}`", region_name,),
                );

                diag.help(&format!(
                    "use data from the highlighted arguments which match the `{}` lifetime of \
                     the return type",
                    region_name,
                ));

                region_name
            }
        }
    }

    /// Return the name of the provided `Ty` (that must be a reference) with a synthesized lifetime
    /// name where required.
    fn get_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
        // 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.sty {
            ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _)
            | ty::TyKind::Ref(
                ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }),
                _,
                _,
            ) => with_highlight_region_for_bound_region(*br, counter, || ty.to_string()),
            _ => ty.to_string(),
        }
    }

    /// Return the name of the provided `Ty` (that must be a reference)'s region with a
    /// synthesized lifetime name where required.
    fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
        match ty.sty {
            ty::TyKind::Ref(region, _, _) => match region {
                ty::RegionKind::ReLateBound(_, br)
                | ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }) => {
                    with_highlight_region_for_bound_region(*br, counter, || region.to_string())
                }
                _ => region.to_string(),
            },
            _ => bug!("ty for annotation of borrow region is not a reference"),
        }
    }
}

// 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.
        is_generator: bool,
        // 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,
        }
    }

    // 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);
        }
    }

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

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

    /// Describe the span associated with a use of a place.
    fn describe(&self) -> String {
        match *self {
            UseSpans::ClosureUse { is_generator, .. } => if is_generator {
                " 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(),
        }
    }
}

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

        let stmt = match self.mir[location.block].statements.get(location.statement_index) {
            Some(stmt) => stmt,
            None => return OtherUse(self.mir.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, is_generator) = match kind {
                box AggregateKind::Closure(def_id, _) => (def_id, false),
                box AggregateKind::Generator(def_id, _, _) => (def_id, true),
                _ => return OtherUse(stmt.source_info.span),
            };

            debug!(
                "move_spans: def_id={:?} is_generator={:?} places={:?}",
                def_id, is_generator, places
            );
            if let Some((args_span, var_span)) = self.closure_span(*def_id, moved_place, places) {
                return ClosureUse {
                    is_generator,
                    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.mir[location.block]
            .statements
            .get(location.statement_index)
        {
            Some(&Statement {
                kind: StatementKind::Assign(Place::Local(local), _),
                ..
            }) => local,
            _ => return OtherUse(use_span),
        };

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

        for stmt in &self.mir[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, var_span)) = self.closure_span(
                    *def_id, &Place::Local(target), places
                ) {
                    return ClosureUse {
                        is_generator,
                        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: &Place<'tcx>,
        places: &Vec<Operand<'tcx>>,
    ) -> Option<(Span, Span)> {
        debug!(
            "closure_span: def_id={:?} target_place={:?} places={:?}",
            def_id, target_place, places
        );
        let node_id = self.infcx.tcx.hir.as_local_node_id(def_id)?;
        let expr = &self.infcx.tcx.hir.expect_expr(node_id).node;
        debug!("closure_span: node_id={:?} expr={:?}", node_id, expr);
        if let hir::ExprKind::Closure(
            .., args_span, _
        ) = expr {
            let var_span = self.infcx.tcx.with_freevars(
                node_id,
                |freevars| {
                    for (v, place) in freevars.iter().zip(places) {
                        match place {
                            Operand::Copy(place) |
                            Operand::Move(place) if target_place == place => {
                                debug!("closure_span: found captured local {:?}", place);
                                return Some(v.span);
                            },
                            _ => {}
                        }
                    }

                    None
                },
            )?;

            Some((*args_span, var_span))
        } else {
            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.mir.source_info(borrow.reserve_location).span;
        self.borrow_spans(span, borrow.reserve_location)
    }
}
