Skip to content

Get rid of ErrorReportingCtx [5/N] #67474

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 30, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 3 additions & 10 deletions src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
Original file line number Diff line number Diff line change
@@ -289,16 +289,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {

None => {
if let Some(region) = regioncx.to_error_region_vid(borrow_region_vid) {
let (category, from_closure, span, region_name) =
self.nonlexical_regioncx.free_region_constraint_info(
&self.body,
&self.local_names,
&self.upvars,
self.mir_def_id,
self.infcx,
borrow_region_vid,
region,
);
let (category, from_closure, span, region_name) = self
.nonlexical_regioncx
.free_region_constraint_info(self, borrow_region_vid, region);
if let Some(region_name) = region_name {
let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref());
BorrowExplanation::MustBeValidFor {
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/diagnostics/mod.rs
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ mod region_errors;

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

pub(super) struct IncludingDowncast(pub(super) bool);
85 changes: 25 additions & 60 deletions src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
Original file line number Diff line number Diff line change
@@ -4,20 +4,15 @@
use std::collections::BTreeMap;

use log::debug;
use rustc::mir::{Body, Local};
use rustc::{hir::def_id::DefId, infer::InferCtxt, ty::RegionVid};
use rustc::ty::RegionVid;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Diagnostic, DiagnosticBuilder};
use rustc_index::vec::IndexVec;
use syntax_pos::symbol::Symbol;
use rustc_errors::DiagnosticBuilder;

use smallvec::SmallVec;

use crate::borrow_check::region_infer::RegionInferenceContext;
use crate::borrow_check::MirBorrowckCtxt;

use super::{
ErrorConstraintInfo, ErrorReportingCtx, RegionErrorNamingCtx, RegionName, RegionNameSource,
};
use super::{ErrorConstraintInfo, RegionErrorNamingCtx, RegionName, RegionNameSource};

/// The different things we could suggest.
enum SuggestedConstraint {
@@ -35,12 +30,8 @@ enum SuggestedConstraint {
/// corresponding to a function definition.
///
/// Adds a help note suggesting adding a where clause with the needed constraints.
pub struct OutlivesSuggestionBuilder<'a> {
/// The MIR DefId of the fn with the lifetime error.
mir_def_id: DefId,

local_names: &'a IndexVec<Local, Option<Symbol>>,

#[derive(Default)]
pub struct OutlivesSuggestionBuilder {
/// The list of outlives constraints that need to be added. Specifically, we map each free
/// region to all other regions that it must outlive. I will use the shorthand `fr:
/// outlived_frs`. Not all of these regions will already have names necessarily. Some could be
@@ -49,16 +40,7 @@ pub struct OutlivesSuggestionBuilder<'a> {
constraints_to_add: BTreeMap<RegionVid, Vec<RegionVid>>,
}

impl OutlivesSuggestionBuilder<'a> {
/// Create a new builder for the given MIR node representing a fn definition.
crate fn new(mir_def_id: DefId, local_names: &'a IndexVec<Local, Option<Symbol>>) -> Self {
OutlivesSuggestionBuilder {
mir_def_id,
local_names,
constraints_to_add: BTreeMap::default(),
}
}

impl OutlivesSuggestionBuilder {
/// Returns `true` iff the `RegionNameSource` is a valid source for an outlives
/// suggestion.
//
@@ -94,22 +76,19 @@ impl OutlivesSuggestionBuilder<'a> {
/// Returns a name for the region if it is suggestable. See `region_name_is_suggestable`.
fn region_vid_to_name(
&self,
errctx: &ErrorReportingCtx<'_, '_, '_>,
mbcx: &MirBorrowckCtxt<'_, '_>,
renctx: &mut RegionErrorNamingCtx,
region: RegionVid,
) -> Option<RegionName> {
errctx
.region_infcx
.give_region_a_name(errctx, renctx, region)
mbcx.nonlexical_regioncx
.give_region_a_name(mbcx, renctx, region)
.filter(Self::region_name_is_suggestable)
}

/// Compiles a list of all suggestions to be printed in the final big suggestion.
fn compile_all_suggestions<'tcx>(
fn compile_all_suggestions(
&self,
body: &Body<'tcx>,
region_infcx: &RegionInferenceContext<'tcx>,
infcx: &InferCtxt<'_, 'tcx>,
mbcx: &MirBorrowckCtxt<'_, '_>,
renctx: &mut RegionErrorNamingCtx,
) -> SmallVec<[SuggestedConstraint; 2]> {
let mut suggested = SmallVec::new();
@@ -118,20 +97,8 @@ impl OutlivesSuggestionBuilder<'a> {
// out silly duplicate messages.
let mut unified_already = FxHashSet::default();

let errctx = ErrorReportingCtx {
region_infcx,
infcx,
body,
mir_def_id: self.mir_def_id,
local_names: self.local_names,

// We should not be suggesting naming upvars, so we pass in a dummy set of upvars that
// should never be used.
upvars: &[],
};

for (fr, outlived) in &self.constraints_to_add {
let fr_name = if let Some(fr_name) = self.region_vid_to_name(&errctx, renctx, *fr) {
let fr_name = if let Some(fr_name) = self.region_vid_to_name(mbcx, renctx, *fr) {
fr_name
} else {
continue;
@@ -141,7 +108,7 @@ impl OutlivesSuggestionBuilder<'a> {
.iter()
// if there is a `None`, we will just omit that constraint
.filter_map(|fr| {
self.region_vid_to_name(&errctx, renctx, *fr).map(|rname| (fr, rname))
self.region_vid_to_name(mbcx, renctx, *fr).map(|rname| (fr, rname))
})
.collect::<Vec<_>>();

@@ -204,14 +171,14 @@ impl OutlivesSuggestionBuilder<'a> {
/// suggestable.
crate fn intermediate_suggestion(
&mut self,
errctx: &ErrorReportingCtx<'_, '_, '_>,
mbcx: &MirBorrowckCtxt<'_, '_>,
errci: &ErrorConstraintInfo,
renctx: &mut RegionErrorNamingCtx,
diag: &mut DiagnosticBuilder<'_>,
) {
// Emit an intermediate note.
let fr_name = self.region_vid_to_name(errctx, renctx, errci.fr);
let outlived_fr_name = self.region_vid_to_name(errctx, renctx, errci.outlived_fr);
let fr_name = self.region_vid_to_name(mbcx, renctx, errci.fr);
let outlived_fr_name = self.region_vid_to_name(mbcx, renctx, errci.outlived_fr);

if let (Some(fr_name), Some(outlived_fr_name)) = (fr_name, outlived_fr_name) {
if let RegionNameSource::Static = outlived_fr_name.source {
@@ -227,12 +194,9 @@ impl OutlivesSuggestionBuilder<'a> {

/// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final
/// suggestion including all collected constraints.
crate fn add_suggestion<'tcx>(
crate fn add_suggestion(
&self,
body: &Body<'tcx>,
region_infcx: &RegionInferenceContext<'tcx>,
infcx: &InferCtxt<'_, 'tcx>,
errors_buffer: &mut Vec<Diagnostic>,
mbcx: &mut MirBorrowckCtxt<'_, '_>,
renctx: &mut RegionErrorNamingCtx,
) {
// No constraints to add? Done.
@@ -251,7 +215,7 @@ impl OutlivesSuggestionBuilder<'a> {
}

// Get all suggestable constraints.
let suggested = self.compile_all_suggestions(body, region_infcx, infcx, renctx);
let suggested = self.compile_all_suggestions(mbcx, renctx);

// If there are no suggestable constraints...
if suggested.is_empty() {
@@ -262,7 +226,7 @@ impl OutlivesSuggestionBuilder<'a> {
// If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a
// list of diagnostics.
let mut diag = if suggested.len() == 1 {
infcx.tcx.sess.diagnostic().struct_help(&match suggested.last().unwrap() {
mbcx.infcx.tcx.sess.diagnostic().struct_help(&match suggested.last().unwrap() {
SuggestedConstraint::Outlives(a, bs) => {
let bs: SmallVec<[String; 2]> = bs.iter().map(|r| format!("{}", r)).collect();
format!("add bound `{}: {}`", a, bs.join(" + "))
@@ -275,7 +239,8 @@ impl OutlivesSuggestionBuilder<'a> {
})
} else {
// Create a new diagnostic.
let mut diag = infcx
let mut diag = mbcx
.infcx
.tcx
.sess
.diagnostic()
@@ -305,10 +270,10 @@ impl OutlivesSuggestionBuilder<'a> {
};

// We want this message to appear after other messages on the mir def.
let mir_span = infcx.tcx.def_span(self.mir_def_id);
let mir_span = mbcx.infcx.tcx.def_span(mbcx.mir_def_id);
diag.sort_span = mir_span.shrink_to_hi();

// Buffer the diagnostic
diag.buffer(errors_buffer);
diag.buffer(&mut mbcx.errors_buffer);
}
}
113 changes: 41 additions & 72 deletions src/librustc_mir/borrow_check/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
@@ -5,22 +5,21 @@ use rustc::infer::{
error_reporting::nice_region_error::NiceRegionError, region_constraints::GenericKind,
InferCtxt, NLLRegionVariableOrigin,
};
use rustc::mir::{Body, ConstraintCategory, Local, Location};
use rustc::mir::{Body, ConstraintCategory, Location};
use rustc::ty::{self, RegionVid, Ty};
use rustc_errors::DiagnosticBuilder;
use rustc_index::vec::IndexVec;
use std::collections::VecDeque;
use syntax::errors::Applicability;
use syntax::symbol::kw;
use syntax_pos::symbol::Symbol;
use syntax_pos::Span;

use crate::util::borrowck_errors;

use crate::borrow_check::{
constraints::OutlivesConstraint, nll::ConstraintDescription,
region_infer::RegionInferenceContext, type_check::Locations, universal_regions::DefiningTy,
Upvar,
MirBorrowckCtxt,
};

use super::{OutlivesSuggestionBuilder, RegionErrorNamingCtx, RegionName, RegionNameSource};
@@ -116,27 +115,6 @@ crate enum RegionErrorKind<'tcx> {
},
}

/// Various pieces of state used when reporting borrow checker errors.
pub struct ErrorReportingCtx<'a, 'b, 'tcx> {
/// The region inference context used for borrow chekcing this MIR body.
pub(super) region_infcx: &'b RegionInferenceContext<'tcx>,

/// The inference context used for type checking.
pub(super) infcx: &'b InferCtxt<'a, 'tcx>,

/// The MIR def we are reporting errors on.
pub(super) mir_def_id: DefId,

/// The MIR body we are reporting errors on (for convenience).
pub(super) body: &'b Body<'tcx>,

/// User variable names for MIR locals (where applicable).
pub(super) local_names: &'b IndexVec<Local, Option<Symbol>>,

/// Any upvars for the MIR body we have kept track of during borrow checking.
pub(super) upvars: &'b [Upvar],
}

/// Information about the various region constraints involved in a borrow checker error.
#[derive(Clone, Debug)]
pub struct ErrorConstraintInfo {
@@ -454,28 +432,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
pub(in crate::borrow_check) fn report_error<'a>(
&'a self,
body: &Body<'tcx>,
local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
infcx: &'a InferCtxt<'a, 'tcx>,
mir_def_id: DefId,
mbcx: &MirBorrowckCtxt<'a, 'tcx>,
fr: RegionVid,
fr_origin: NLLRegionVariableOrigin,
outlived_fr: RegionVid,
outlives_suggestion: &mut OutlivesSuggestionBuilder<'_>,
outlives_suggestion: &mut OutlivesSuggestionBuilder,
renctx: &mut RegionErrorNamingCtx,
) -> DiagnosticBuilder<'a> {
debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);

let (category, _, span) = self.best_blame_constraint(body, fr, fr_origin, |r| {
let (category, _, span) = self.best_blame_constraint(&mbcx.body, fr, fr_origin, |r| {
self.provides_universal_region(r, fr, outlived_fr)
});

debug!("report_error: category={:?} {:?}", category, span);
// Check if we can use one of the "nice region errors".
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
let tables = infcx.tcx.typeck_tables_of(mir_def_id);
let nice = NiceRegionError::new_from_span(infcx, span, o, f, Some(tables));
let tables = mbcx.infcx.tcx.typeck_tables_of(mbcx.mir_def_id);
let nice = NiceRegionError::new_from_span(mbcx.infcx, span, o, f, Some(tables));
if let Some(diag) = nice.try_report_from_nll() {
return diag;
}
@@ -491,9 +465,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fr_is_local, outlived_fr_is_local, category
);

let errctx =
ErrorReportingCtx { region_infcx: self, infcx, mir_def_id, body, local_names, upvars };

let errci = ErrorConstraintInfo {
fr,
outlived_fr,
@@ -504,22 +475,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
};

match (category, fr_is_local, outlived_fr_is_local) {
(ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) => {
self.report_fnmut_error(&errctx, &errci, renctx)
(ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(mbcx.infcx, fr) => {
self.report_fnmut_error(mbcx, &errci, renctx)
}
(ConstraintCategory::Assignment, true, false)
| (ConstraintCategory::CallArgument, true, false) => {
let mut db = self.report_escaping_data_error(&errctx, &errci, renctx);
let mut db = self.report_escaping_data_error(mbcx, &errci, renctx);

outlives_suggestion.intermediate_suggestion(&errctx, &errci, renctx, &mut db);
outlives_suggestion.intermediate_suggestion(mbcx, &errci, renctx, &mut db);
outlives_suggestion.collect_constraint(fr, outlived_fr);

db
}
_ => {
let mut db = self.report_general_error(&errctx, &errci, renctx);
let mut db = self.report_general_error(mbcx, &errci, renctx);

outlives_suggestion.intermediate_suggestion(&errctx, &errci, renctx, &mut db);
outlives_suggestion.intermediate_suggestion(mbcx, &errci, renctx, &mut db);
outlives_suggestion.collect_constraint(fr, outlived_fr);

db
@@ -569,13 +540,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// ```
fn report_fnmut_error(
&self,
errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
errci: &ErrorConstraintInfo,
renctx: &mut RegionErrorNamingCtx,
) -> DiagnosticBuilder<'_> {
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;

let mut diag = errctx
let mut diag = mbcx
.infcx
.tcx
.sess
@@ -593,7 +564,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {

diag.span_label(*span, message);

match self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap().source {
match self.give_region_a_name(mbcx, renctx, *outlived_fr).unwrap().source {
RegionNameSource::NamedEarlyBoundRegion(fr_span)
| RegionNameSource::NamedFreeRegion(fr_span)
| RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
@@ -630,21 +601,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// ```
fn report_escaping_data_error(
&self,
errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
errci: &ErrorConstraintInfo,
renctx: &mut RegionErrorNamingCtx,
) -> DiagnosticBuilder<'_> {
let ErrorReportingCtx { infcx, body, upvars, local_names, .. } = errctx;

let ErrorConstraintInfo { span, category, .. } = errci;

let fr_name_and_span =
self.get_var_name_and_span_for_region(infcx.tcx, body, local_names, upvars, errci.fr);
let fr_name_and_span = self.get_var_name_and_span_for_region(
mbcx.infcx.tcx,
&mbcx.body,
&mbcx.local_names,
&mbcx.upvars,
errci.fr,
);
let outlived_fr_name_and_span = self.get_var_name_and_span_for_region(
infcx.tcx,
body,
local_names,
upvars,
mbcx.infcx.tcx,
&mbcx.body,
&mbcx.local_names,
&mbcx.upvars,
errci.outlived_fr,
);

@@ -662,14 +636,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|| escapes_from == "const"
{
return self.report_general_error(
errctx,
mbcx,
&ErrorConstraintInfo { fr_is_local: true, outlived_fr_is_local: false, ..*errci },
renctx,
);
}

let mut diag =
borrowck_errors::borrowed_data_escapes_closure(infcx.tcx, *span, escapes_from);
borrowck_errors::borrowed_data_escapes_closure(mbcx.infcx.tcx, *span, escapes_from);

if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span {
diag.span_label(
@@ -713,11 +687,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// ```
fn report_general_error(
&self,
errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
errci: &ErrorConstraintInfo,
renctx: &mut RegionErrorNamingCtx,
) -> DiagnosticBuilder<'_> {
let ErrorReportingCtx { infcx, mir_def_id, .. } = errctx;
let ErrorConstraintInfo {
fr,
fr_is_local,
@@ -728,13 +701,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
..
} = errci;

let mut diag = infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");
let mut diag =
mbcx.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");

let mir_def_name = if infcx.tcx.is_closure(*mir_def_id) { "closure" } else { "function" };
let mir_def_name =
if mbcx.infcx.tcx.is_closure(mbcx.mir_def_id) { "closure" } else { "function" };

let fr_name = self.give_region_a_name(errctx, renctx, *fr).unwrap();
let fr_name = self.give_region_a_name(mbcx, renctx, *fr).unwrap();
fr_name.highlight_region_name(&mut diag);
let outlived_fr_name = self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap();
let outlived_fr_name = self.give_region_a_name(mbcx, renctx, *outlived_fr).unwrap();
outlived_fr_name.highlight_region_name(&mut diag);

match (category, outlived_fr_is_local, fr_is_local) {
@@ -761,7 +736,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}

self.add_static_impl_trait_suggestion(infcx, &mut diag, *fr, fr_name, *outlived_fr);
self.add_static_impl_trait_suggestion(mbcx.infcx, &mut diag, *fr, fr_name, *outlived_fr);

diag
}
@@ -854,25 +829,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {

crate fn free_region_constraint_info(
&self,
body: &Body<'tcx>,
local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
mir_def_id: DefId,
infcx: &InferCtxt<'_, 'tcx>,
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
borrow_region: RegionVid,
outlived_region: RegionVid,
) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
let (category, from_closure, span) = self.best_blame_constraint(
body,
&mbcx.body,
borrow_region,
NLLRegionVariableOrigin::FreeRegion,
|r| self.provides_universal_region(r, borrow_region, outlived_region),
);

let mut renctx = RegionErrorNamingCtx::new();
let errctx =
ErrorReportingCtx { infcx, body, local_names, upvars, mir_def_id, region_infcx: self };
let outlived_fr_name = self.give_region_a_name(&errctx, &mut renctx, outlived_region);
let outlived_fr_name = self.give_region_a_name(mbcx, &mut renctx, outlived_region);

(category, from_closure, span, outlived_fr_name)
}
128 changes: 46 additions & 82 deletions src/librustc_mir/borrow_check/diagnostics/region_name.rs
Original file line number Diff line number Diff line change
@@ -2,21 +2,17 @@ use std::fmt::{self, Display};

use rustc::hir;
use rustc::hir::def::{DefKind, Res};
use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
use rustc::mir::{Body, Local};
use rustc::ty::print::RegionHighlightMode;
use rustc::ty::subst::{GenericArgKind, SubstsRef};
use rustc::ty::{self, RegionVid, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::DiagnosticBuilder;
use rustc_index::vec::IndexVec;
use syntax::symbol::kw;
use syntax_pos::{symbol::Symbol, Span, DUMMY_SP};

use crate::borrow_check::{
diagnostics::region_errors::ErrorReportingCtx, nll::ToRegionVid,
region_infer::RegionInferenceContext, universal_regions::DefiningTy, Upvar,
nll::ToRegionVid, region_infer::RegionInferenceContext, universal_regions::DefiningTy,
MirBorrowckCtxt,
};

/// A name for a particular region used in emitting diagnostics. This name could be a generated
@@ -193,12 +189,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// and then return the name `'1` for us to use.
crate fn give_region_a_name(
&self,
errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
renctx: &mut RegionErrorNamingCtx,
fr: RegionVid,
) -> Option<RegionName> {
let ErrorReportingCtx { infcx, body, mir_def_id, local_names, upvars, .. } = errctx;

debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter);

assert!(self.universal_regions.is_universal_region(fr));
@@ -208,38 +202,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}

let value = self
.give_name_from_error_region(infcx.tcx, *mir_def_id, fr, renctx)
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_arguments(
infcx,
body,
local_names,
*mir_def_id,
fr,
renctx,
)
})
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_upvars(infcx.tcx, upvars, fr, renctx)
})
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_output(
infcx,
body,
*mir_def_id,
fr,
renctx,
)
})
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_yield_ty(
infcx,
body,
*mir_def_id,
fr,
renctx,
)
});
.give_name_from_error_region(mbcx, fr, renctx)
.or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(mbcx, fr, renctx))
.or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(mbcx, fr, renctx))
.or_else(|| self.give_name_if_anonymous_region_appears_in_output(mbcx, fr, renctx))
.or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(mbcx, fr, renctx));

if let Some(ref value) = value {
renctx.insert(fr, value.clone());
@@ -255,13 +222,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// named variants.
fn give_name_from_error_region(
&self,
tcx: TyCtxt<'tcx>,
mir_def_id: DefId,
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
fr: RegionVid,
renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let error_region = self.to_error_region(fr)?;

let tcx = mbcx.infcx.tcx;

debug!("give_region_a_name: error_region = {:?}", error_region);
match error_region {
ty::ReEarlyBound(ebr) => {
@@ -308,7 +276,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}

ty::BoundRegion::BrEnv => {
let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
let mir_hir_id = mbcx
.infcx
.tcx
.hir()
.as_local_hir_id(mbcx.mir_def_id)
.expect("non-local mir");
let def_ty = self.universal_regions.defining_ty;

if let DefiningTy::Closure(def_id, substs) = def_ty {
@@ -373,21 +346,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// ```
fn give_name_if_anonymous_region_appears_in_arguments(
&self,
infcx: &InferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
local_names: &IndexVec<Local, Option<Symbol>>,
mir_def_id: DefId,
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
fr: RegionVid,
renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
let argument_index = self.get_argument_index_for_region(infcx.tcx, fr)?;
let argument_index = self.get_argument_index_for_region(mbcx.infcx.tcx, fr)?;

let arg_ty =
self.universal_regions.unnormalized_input_tys[implicit_inputs + argument_index];
if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument(
infcx,
mir_def_id,
mbcx,
fr,
arg_ty,
argument_index,
@@ -396,20 +365,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
return Some(region_name);
}

self.give_name_if_we_cannot_match_hir_ty(infcx, body, local_names, fr, arg_ty, renctx)
self.give_name_if_we_cannot_match_hir_ty(mbcx, fr, arg_ty, renctx)
}

fn give_name_if_we_can_match_hir_ty_from_argument(
&self,
infcx: &InferCtxt<'_, 'tcx>,
mir_def_id: DefId,
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
needle_fr: RegionVid,
argument_ty: Ty<'tcx>,
argument_index: usize,
renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let mir_hir_id = infcx.tcx.hir().as_local_hir_id(mir_def_id)?;
let fn_decl = infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
let mir_hir_id = mbcx.infcx.tcx.hir().as_local_hir_id(mbcx.mir_def_id)?;
let fn_decl = mbcx.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?;
match argument_hir_ty.kind {
// This indicates a variable with no type annotation, like
@@ -420,7 +388,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
hir::TyKind::Infer => None,

_ => self.give_name_if_we_can_match_hir_ty(
infcx.tcx,
mbcx.infcx.tcx,
needle_fr,
argument_ty,
argument_hir_ty,
@@ -442,27 +410,28 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// ```
fn give_name_if_we_cannot_match_hir_ty(
&self,
infcx: &InferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
local_names: &IndexVec<Local, Option<Symbol>>,
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
needle_fr: RegionVid,
argument_ty: Ty<'tcx>,
renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let counter = renctx.counter;
let mut highlight = RegionHighlightMode::default();
highlight.highlighting_region_vid(needle_fr, counter);
let type_name = infcx.extract_type_name(&argument_ty, Some(highlight)).0;
let type_name = mbcx.infcx.extract_type_name(&argument_ty, Some(highlight)).0;

debug!(
"give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
type_name, needle_fr
);
let assigned_region_name = if type_name.find(&format!("'{}", counter)).is_some() {
// Only add a label if we can confirm that a region was labelled.
let argument_index = self.get_argument_index_for_region(infcx.tcx, needle_fr)?;
let (_, span) =
self.get_argument_name_and_span_for_region(body, local_names, argument_index);
let argument_index = self.get_argument_index_for_region(mbcx.infcx.tcx, needle_fr)?;
let (_, span) = self.get_argument_name_and_span_for_region(
&mbcx.body,
&mbcx.local_names,
argument_index,
);

Some(RegionName {
// This counter value will already have been used, so this function will increment
@@ -696,14 +665,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// ```
fn give_name_if_anonymous_region_appears_in_upvars(
&self,
tcx: TyCtxt<'tcx>,
upvars: &[Upvar],
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
fr: RegionVid,
renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let upvar_index = self.get_upvar_index_for_region(tcx, fr)?;
let upvar_index = self.get_upvar_index_for_region(mbcx.infcx.tcx, fr)?;
let (upvar_name, upvar_span) =
self.get_upvar_name_and_span_for_region(tcx, upvars, upvar_index);
self.get_upvar_name_and_span_for_region(mbcx.infcx.tcx, &mbcx.upvars, upvar_index);
let region_name = renctx.synthesize_region_name();

Some(RegionName {
@@ -718,13 +686,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// or be early bound (named, not in argument).
fn give_name_if_anonymous_region_appears_in_output(
&self,
infcx: &InferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
mir_def_id: DefId,
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
fr: RegionVid,
renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let tcx = infcx.tcx;
let tcx = mbcx.infcx.tcx;

let return_ty = self.universal_regions.unnormalized_output_ty;
debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
@@ -734,9 +700,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {

let mut highlight = RegionHighlightMode::default();
highlight.highlighting_region_vid(fr, renctx.counter);
let type_name = infcx.extract_type_name(&return_ty, Some(highlight)).0;
let type_name = mbcx.infcx.extract_type_name(&return_ty, Some(highlight)).0;

let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
let mir_hir_id = tcx.hir().as_local_hir_id(mbcx.mir_def_id).expect("non-local mir");

let (return_span, mir_description) = match tcx.hir().get(mir_hir_id) {
hir::Node::Expr(hir::Expr {
@@ -753,7 +719,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
kind: hir::ImplItemKind::Method(method_sig, _),
..
}) => (method_sig.decl.output.span(), ""),
_ => (body.span, ""),
_ => (mbcx.body.span, ""),
};

Some(RegionName {
@@ -771,9 +737,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {

fn give_name_if_anonymous_region_appears_in_yield_ty(
&self,
infcx: &InferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
mir_def_id: DefId,
mbcx: &MirBorrowckCtxt<'_, 'tcx>,
fr: RegionVid,
renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
@@ -782,23 +746,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let yield_ty = self.universal_regions.yield_ty?;
debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty,);

let tcx = infcx.tcx;
let tcx = mbcx.infcx.tcx;

if !tcx.any_free_region_meets(&yield_ty, |r| r.to_region_vid() == fr) {
return None;
}

let mut highlight = RegionHighlightMode::default();
highlight.highlighting_region_vid(fr, renctx.counter);
let type_name = infcx.extract_type_name(&yield_ty, Some(highlight)).0;
let type_name = mbcx.infcx.extract_type_name(&yield_ty, Some(highlight)).0;

let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
let mir_hir_id = tcx.hir().as_local_hir_id(mbcx.mir_def_id).expect("non-local mir");

let yield_span = match tcx.hir().get(mir_hir_id) {
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(_, _, _, span, _), ..
}) => (tcx.sess.source_map().end_point(*span)),
_ => body.span,
_ => mbcx.body.span,
};

debug!(
17 changes: 3 additions & 14 deletions src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
@@ -1482,8 +1482,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {

// FIXME(mark-i-m): Would be great to get rid of the naming context.
let mut region_naming = RegionErrorNamingCtx::new();
let mut outlives_suggestion =
OutlivesSuggestionBuilder::new(self.mir_def_id, &self.local_names);
let mut outlives_suggestion = OutlivesSuggestionBuilder::default();

for nll_error in nll_errors.into_iter() {
match nll_error {
@@ -1561,11 +1560,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
if is_reported {
let db = self.nonlexical_regioncx.report_error(
&self.body,
&self.local_names,
&self.upvars,
self.infcx,
self.mir_def_id,
self,
longer_fr,
fr_origin,
shorter_fr,
@@ -1591,13 +1586,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}

// Emit one outlives suggestions for each MIR def we borrowck
outlives_suggestion.add_suggestion(
&self.body,
&self.nonlexical_regioncx,
self.infcx,
&mut self.errors_buffer,
&mut region_naming,
);
outlives_suggestion.add_suggestion(self, &mut region_naming);
}
}