Get rid of RegionErrorNamingContext
This commit is contained in:
parent
234b930108
commit
a804868bbf
@ -16,8 +16,8 @@
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::borrow_check::{
|
||||
borrow_set::BorrowData, diagnostics::RegionErrorNamingCtx, nll::ConstraintDescription,
|
||||
region_infer::Cause, MirBorrowckCtxt, WriteKind,
|
||||
borrow_set::BorrowData, nll::ConstraintDescription, region_infer::Cause, MirBorrowckCtxt,
|
||||
WriteKind,
|
||||
};
|
||||
|
||||
use super::{find_use, RegionName, UseSpans};
|
||||
@ -267,8 +267,7 @@ fn free_region_constraint_info(
|
||||
|r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
|
||||
);
|
||||
|
||||
let mut renctx = RegionErrorNamingCtx::new();
|
||||
let outlived_fr_name = self.give_region_a_name(&mut renctx, outlived_region);
|
||||
let outlived_fr_name = self.give_region_a_name(outlived_region);
|
||||
|
||||
(category, from_closure, span, outlived_fr_name)
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
crate use mutability_errors::AccessKind;
|
||||
crate use outlives_suggestion::OutlivesSuggestionBuilder;
|
||||
crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
|
||||
crate use region_name::{RegionErrorNamingCtx, RegionName, RegionNameSource};
|
||||
crate use region_name::{RegionName, RegionNameSource};
|
||||
|
||||
pub(super) struct IncludingDowncast(pub(super) bool);
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
use crate::borrow_check::MirBorrowckCtxt;
|
||||
|
||||
use super::{ErrorConstraintInfo, RegionErrorNamingCtx, RegionName, RegionNameSource};
|
||||
use super::{ErrorConstraintInfo, RegionName, RegionNameSource};
|
||||
|
||||
/// The different things we could suggest.
|
||||
enum SuggestedConstraint {
|
||||
@ -77,17 +77,15 @@ fn region_name_is_suggestable(name: &RegionName) -> bool {
|
||||
fn region_vid_to_name(
|
||||
&self,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_>,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
region: RegionVid,
|
||||
) -> Option<RegionName> {
|
||||
mbcx.give_region_a_name(renctx, region).filter(Self::region_name_is_suggestable)
|
||||
mbcx.give_region_a_name(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(
|
||||
&self,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_>,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> SmallVec<[SuggestedConstraint; 2]> {
|
||||
let mut suggested = SmallVec::new();
|
||||
|
||||
@ -96,7 +94,7 @@ fn compile_all_suggestions(
|
||||
let mut unified_already = FxHashSet::default();
|
||||
|
||||
for (fr, outlived) in &self.constraints_to_add {
|
||||
let fr_name = if let Some(fr_name) = self.region_vid_to_name(mbcx, renctx, *fr) {
|
||||
let fr_name = if let Some(fr_name) = self.region_vid_to_name(mbcx, *fr) {
|
||||
fr_name
|
||||
} else {
|
||||
continue;
|
||||
@ -105,9 +103,7 @@ fn compile_all_suggestions(
|
||||
let outlived = outlived
|
||||
.iter()
|
||||
// if there is a `None`, we will just omit that constraint
|
||||
.filter_map(|fr| {
|
||||
self.region_vid_to_name(mbcx, renctx, *fr).map(|rname| (fr, rname))
|
||||
})
|
||||
.filter_map(|fr| self.region_vid_to_name(mbcx, *fr).map(|rname| (fr, rname)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// No suggestable outlived lifetimes.
|
||||
@ -171,12 +167,11 @@ fn compile_all_suggestions(
|
||||
&mut self,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_>,
|
||||
errci: &ErrorConstraintInfo,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
diag: &mut DiagnosticBuilder<'_>,
|
||||
) {
|
||||
// Emit an intermediate note.
|
||||
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);
|
||||
let fr_name = self.region_vid_to_name(mbcx, errci.fr);
|
||||
let outlived_fr_name = self.region_vid_to_name(mbcx, 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 {
|
||||
@ -192,11 +187,7 @@ fn compile_all_suggestions(
|
||||
|
||||
/// 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(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_>,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) {
|
||||
crate fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_>) {
|
||||
// No constraints to add? Done.
|
||||
if self.constraints_to_add.is_empty() {
|
||||
debug!("No constraints to suggest.");
|
||||
@ -213,7 +204,7 @@ fn compile_all_suggestions(
|
||||
}
|
||||
|
||||
// Get all suggestable constraints.
|
||||
let suggested = self.compile_all_suggestions(mbcx, renctx);
|
||||
let suggested = self.compile_all_suggestions(mbcx);
|
||||
|
||||
// If there are no suggestable constraints...
|
||||
if suggested.is_empty() {
|
||||
|
@ -19,7 +19,7 @@
|
||||
MirBorrowckCtxt,
|
||||
};
|
||||
|
||||
use super::{OutlivesSuggestionBuilder, RegionErrorNamingCtx, RegionName, RegionNameSource};
|
||||
use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
|
||||
|
||||
impl ConstraintDescription for ConstraintCategory {
|
||||
fn description(&self) -> &'static str {
|
||||
@ -152,8 +152,6 @@ pub(in crate::borrow_check) fn report_region_errors(&mut self, nll_errors: Regio
|
||||
// Iterate through all the errors, producing a diagnostic for each one. The diagnostics are
|
||||
// buffered in the `MirBorrowckCtxt`.
|
||||
|
||||
// TODO(mark-i-m): Would be great to get rid of the naming context.
|
||||
let mut region_naming = RegionErrorNamingCtx::new();
|
||||
let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
|
||||
|
||||
for nll_error in nll_errors.into_iter() {
|
||||
@ -243,7 +241,6 @@ pub(in crate::borrow_check) fn report_region_errors(&mut self, nll_errors: Regio
|
||||
fr_origin,
|
||||
shorter_fr,
|
||||
&mut outlives_suggestion,
|
||||
&mut region_naming,
|
||||
);
|
||||
} else {
|
||||
// We only report the first error, so as not to overwhelm the user. See
|
||||
@ -262,7 +259,7 @@ pub(in crate::borrow_check) fn report_region_errors(&mut self, nll_errors: Regio
|
||||
}
|
||||
|
||||
// Emit one outlives suggestions for each MIR def we borrowck
|
||||
outlives_suggestion.add_suggestion(self, &mut region_naming);
|
||||
outlives_suggestion.add_suggestion(self);
|
||||
}
|
||||
|
||||
/// Report an error because the universal region `fr` was required to outlive
|
||||
@ -279,7 +276,6 @@ pub(in crate::borrow_check) fn report_error(
|
||||
fr_origin: NLLRegionVariableOrigin,
|
||||
outlived_fr: RegionVid,
|
||||
outlives_suggestion: &mut OutlivesSuggestionBuilder,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) {
|
||||
debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
|
||||
|
||||
@ -320,21 +316,21 @@ pub(in crate::borrow_check) fn report_error(
|
||||
|
||||
let diag = match (category, fr_is_local, outlived_fr_is_local) {
|
||||
(ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(fr) => {
|
||||
self.report_fnmut_error(&errci, renctx)
|
||||
self.report_fnmut_error(&errci)
|
||||
}
|
||||
(ConstraintCategory::Assignment, true, false)
|
||||
| (ConstraintCategory::CallArgument, true, false) => {
|
||||
let mut db = self.report_escaping_data_error(&errci, renctx);
|
||||
let mut db = self.report_escaping_data_error(&errci);
|
||||
|
||||
outlives_suggestion.intermediate_suggestion(self, &errci, renctx, &mut db);
|
||||
outlives_suggestion.intermediate_suggestion(self, &errci, &mut db);
|
||||
outlives_suggestion.collect_constraint(fr, outlived_fr);
|
||||
|
||||
db
|
||||
}
|
||||
_ => {
|
||||
let mut db = self.report_general_error(&errci, renctx);
|
||||
let mut db = self.report_general_error(&errci);
|
||||
|
||||
outlives_suggestion.intermediate_suggestion(self, &errci, renctx, &mut db);
|
||||
outlives_suggestion.intermediate_suggestion(self, &errci, &mut db);
|
||||
outlives_suggestion.collect_constraint(fr, outlived_fr);
|
||||
|
||||
db
|
||||
@ -360,11 +356,7 @@ pub(in crate::borrow_check) fn report_error(
|
||||
/// executing...
|
||||
/// = note: ...therefore, returned references to captured variables will escape the closure
|
||||
/// ```
|
||||
fn report_fnmut_error(
|
||||
&self,
|
||||
errci: &ErrorConstraintInfo,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
fn report_fnmut_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> {
|
||||
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
|
||||
|
||||
let mut diag = self
|
||||
@ -386,7 +378,7 @@ fn report_fnmut_error(
|
||||
|
||||
diag.span_label(*span, message);
|
||||
|
||||
match self.give_region_a_name(renctx, *outlived_fr).unwrap().source {
|
||||
match self.give_region_a_name(*outlived_fr).unwrap().source {
|
||||
RegionNameSource::NamedEarlyBoundRegion(fr_span)
|
||||
| RegionNameSource::NamedFreeRegion(fr_span)
|
||||
| RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
|
||||
@ -421,11 +413,7 @@ fn report_fnmut_error(
|
||||
/// LL | ref_obj(x)
|
||||
/// | ^^^^^^^^^^ `x` escapes the function body here
|
||||
/// ```
|
||||
fn report_escaping_data_error(
|
||||
&self,
|
||||
errci: &ErrorConstraintInfo,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> {
|
||||
let ErrorConstraintInfo { span, category, .. } = errci;
|
||||
|
||||
let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
|
||||
@ -456,10 +444,11 @@ fn report_escaping_data_error(
|
||||
|| (*category == ConstraintCategory::Assignment && escapes_from == "function")
|
||||
|| escapes_from == "const"
|
||||
{
|
||||
return self.report_general_error(
|
||||
&ErrorConstraintInfo { fr_is_local: true, outlived_fr_is_local: false, ..*errci },
|
||||
renctx,
|
||||
);
|
||||
return self.report_general_error(&ErrorConstraintInfo {
|
||||
fr_is_local: true,
|
||||
outlived_fr_is_local: false,
|
||||
..*errci
|
||||
});
|
||||
}
|
||||
|
||||
let mut diag =
|
||||
@ -505,11 +494,7 @@ fn report_escaping_data_error(
|
||||
/// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it
|
||||
/// | is returning data with lifetime `'b`
|
||||
/// ```
|
||||
fn report_general_error(
|
||||
&self,
|
||||
errci: &ErrorConstraintInfo,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
fn report_general_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> {
|
||||
let ErrorConstraintInfo {
|
||||
fr,
|
||||
fr_is_local,
|
||||
@ -526,9 +511,9 @@ fn report_general_error(
|
||||
let mir_def_name =
|
||||
if self.infcx.tcx.is_closure(self.mir_def_id) { "closure" } else { "function" };
|
||||
|
||||
let fr_name = self.give_region_a_name(renctx, *fr).unwrap();
|
||||
let fr_name = self.give_region_a_name(*fr).unwrap();
|
||||
fr_name.highlight_region_name(&mut diag);
|
||||
let outlived_fr_name = self.give_region_a_name(renctx, *outlived_fr).unwrap();
|
||||
let outlived_fr_name = self.give_region_a_name(*outlived_fr).unwrap();
|
||||
outlived_fr_name.highlight_region_name(&mut diag);
|
||||
|
||||
match (category, outlived_fr_is_local, fr_is_local) {
|
||||
|
@ -3,7 +3,6 @@
|
||||
use rustc::ty::print::RegionHighlightMode;
|
||||
use rustc::ty::subst::{GenericArgKind, SubstsRef};
|
||||
use rustc::ty::{self, RegionVid, Ty};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
@ -52,46 +51,6 @@
|
||||
AnonRegionFromAsyncFn(Span),
|
||||
}
|
||||
|
||||
/// Records region names that have been assigned before so that we can use the same ones in later
|
||||
/// diagnostics.
|
||||
#[derive(Debug, Clone)]
|
||||
crate struct RegionErrorNamingCtx {
|
||||
/// Record the region names generated for each region in the given
|
||||
/// MIR def so that we can reuse them later in help/error messages.
|
||||
renctx: FxHashMap<RegionVid, RegionName>,
|
||||
|
||||
/// The counter for generating new region names.
|
||||
counter: usize,
|
||||
}
|
||||
|
||||
impl RegionErrorNamingCtx {
|
||||
crate fn new() -> Self {
|
||||
Self { counter: 1, renctx: FxHashMap::default() }
|
||||
}
|
||||
|
||||
/// Get the name of `region` if it has previously been named.
|
||||
crate fn get(&self, region: &RegionVid) -> Option<&RegionName> {
|
||||
self.renctx.get(region)
|
||||
}
|
||||
|
||||
/// Give `region` the name `name`.
|
||||
crate fn insert(&mut self, region: RegionVid, name: RegionName) {
|
||||
self.renctx.insert(region, name);
|
||||
}
|
||||
|
||||
/// Creates a synthetic region named `'N`, where `N` is the next value of the counter. Then,
|
||||
/// increment the counter.
|
||||
///
|
||||
/// The name is not memoized. A separate call to `insert` should be made later. (Currently,
|
||||
/// this happens at the end of `give_region_a_name`).
|
||||
crate fn synthesize_region_name(&mut self) -> Symbol {
|
||||
let c = self.counter;
|
||||
self.counter += 1;
|
||||
|
||||
Symbol::intern(&format!("'{:?}", c))
|
||||
}
|
||||
}
|
||||
|
||||
impl RegionName {
|
||||
crate fn was_named(&self) -> bool {
|
||||
match self.source {
|
||||
@ -159,6 +118,17 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
|
||||
impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
/// Generate a synthetic region named `'N`, where `N` is the next value of the counter. Then,
|
||||
/// increment the counter.
|
||||
///
|
||||
/// This is _not_ idempotent. Call `give_region_a_name` when possible.
|
||||
fn synthesize_region_name(&self) -> Symbol {
|
||||
let mut counter = self.next_region_name.try_borrow_mut().unwrap();
|
||||
let c = *counter;
|
||||
*counter += 1;
|
||||
Symbol::intern(&format!("'{:?}", c))
|
||||
}
|
||||
|
||||
/// Maps from an internal MIR region vid to something that we can
|
||||
/// report to the user. In some cases, the region vids will map
|
||||
/// directly to lifetimes that the user has a name for (e.g.,
|
||||
@ -167,6 +137,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
/// that end, this function takes a "diagnostic" so that it can
|
||||
/// create auxiliary notes as needed.
|
||||
///
|
||||
/// The names are memoized, so this is both cheap to recompute and idempotent.
|
||||
///
|
||||
/// Example (function arguments):
|
||||
///
|
||||
/// Suppose we are trying to give a name to the lifetime of the
|
||||
@ -184,28 +156,28 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
/// ```
|
||||
///
|
||||
/// and then return the name `'1` for us to use.
|
||||
crate fn give_region_a_name(
|
||||
&self,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
fr: RegionVid,
|
||||
) -> Option<RegionName> {
|
||||
debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter);
|
||||
crate fn give_region_a_name(&self, fr: RegionVid) -> Option<RegionName> {
|
||||
debug!(
|
||||
"give_region_a_name(fr={:?}, counter={:?})",
|
||||
fr,
|
||||
self.next_region_name.try_borrow().unwrap()
|
||||
);
|
||||
|
||||
assert!(self.regioncx.universal_regions().is_universal_region(fr));
|
||||
|
||||
if let Some(value) = renctx.get(&fr) {
|
||||
if let Some(value) = self.region_names.try_borrow_mut().unwrap().get(&fr) {
|
||||
return Some(value.clone());
|
||||
}
|
||||
|
||||
let value = self
|
||||
.give_name_from_error_region(fr, renctx)
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr, renctx))
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr, renctx))
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr, renctx))
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr, renctx));
|
||||
.give_name_from_error_region(fr)
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr))
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr));
|
||||
|
||||
if let Some(ref value) = value {
|
||||
renctx.insert(fr, value.clone());
|
||||
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
|
||||
}
|
||||
|
||||
debug!("give_region_a_name: gave name {:?}", value);
|
||||
@ -216,11 +188,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
/// *user* has a name for. In that case, we'll be able to map
|
||||
/// `fr` to a `Region<'tcx>`, and that region will be one of
|
||||
/// named variants.
|
||||
fn give_name_from_error_region(
|
||||
&self,
|
||||
fr: RegionVid,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> Option<RegionName> {
|
||||
fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> {
|
||||
let error_region = self.to_error_region(fr)?;
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
@ -262,7 +230,7 @@ fn give_name_from_error_region(
|
||||
// happen if we have an elided name in an async fn for example: the
|
||||
// compiler will generate a region named `'_`, but reporting such a name is
|
||||
// not actually useful, so we synthesize a name for it instead.
|
||||
let name = renctx.synthesize_region_name();
|
||||
let name = self.synthesize_region_name();
|
||||
Some(RegionName {
|
||||
name,
|
||||
source: RegionNameSource::AnonRegionFromAsyncFn(span),
|
||||
@ -287,7 +255,7 @@ fn give_name_from_error_region(
|
||||
} else {
|
||||
bug!("Closure is not defined by a closure expr");
|
||||
};
|
||||
let region_name = renctx.synthesize_region_name();
|
||||
let region_name = self.synthesize_region_name();
|
||||
|
||||
let closure_kind_ty = substs.as_closure().kind_ty(def_id, tcx);
|
||||
let note = match closure_kind_ty.to_opt_closure_kind() {
|
||||
@ -342,7 +310,6 @@ fn give_name_from_error_region(
|
||||
fn give_name_if_anonymous_region_appears_in_arguments(
|
||||
&self,
|
||||
fr: RegionVid,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> Option<RegionName> {
|
||||
let implicit_inputs = self.regioncx.universal_regions().defining_ty.implicit_inputs();
|
||||
let argument_index = self.regioncx.get_argument_index_for_region(self.infcx.tcx, fr)?;
|
||||
@ -350,12 +317,12 @@ fn give_name_if_anonymous_region_appears_in_arguments(
|
||||
let arg_ty = self.regioncx.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(fr, arg_ty, argument_index, renctx)
|
||||
self.give_name_if_we_can_match_hir_ty_from_argument(fr, arg_ty, argument_index)
|
||||
{
|
||||
return Some(region_name);
|
||||
}
|
||||
|
||||
self.give_name_if_we_cannot_match_hir_ty(fr, arg_ty, renctx)
|
||||
self.give_name_if_we_cannot_match_hir_ty(fr, arg_ty)
|
||||
}
|
||||
|
||||
fn give_name_if_we_can_match_hir_ty_from_argument(
|
||||
@ -363,7 +330,6 @@ fn give_name_if_we_can_match_hir_ty_from_argument(
|
||||
needle_fr: RegionVid,
|
||||
argument_ty: Ty<'tcx>,
|
||||
argument_index: usize,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> Option<RegionName> {
|
||||
let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id)?;
|
||||
let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
|
||||
@ -376,12 +342,7 @@ fn give_name_if_we_can_match_hir_ty_from_argument(
|
||||
// (`give_name_if_anonymous_region_appears_in_arguments`).
|
||||
hir::TyKind::Infer => None,
|
||||
|
||||
_ => self.give_name_if_we_can_match_hir_ty(
|
||||
needle_fr,
|
||||
argument_ty,
|
||||
argument_hir_ty,
|
||||
renctx,
|
||||
),
|
||||
_ => self.give_name_if_we_can_match_hir_ty(needle_fr, argument_ty, argument_hir_ty),
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,9 +361,8 @@ fn give_name_if_we_cannot_match_hir_ty(
|
||||
&self,
|
||||
needle_fr: RegionVid,
|
||||
argument_ty: Ty<'tcx>,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> Option<RegionName> {
|
||||
let counter = renctx.counter;
|
||||
let counter = *self.next_region_name.try_borrow().unwrap();
|
||||
let mut highlight = RegionHighlightMode::default();
|
||||
highlight.highlighting_region_vid(needle_fr, counter);
|
||||
let type_name = self.infcx.extract_type_name(&argument_ty, Some(highlight)).0;
|
||||
@ -425,7 +385,7 @@ fn give_name_if_we_cannot_match_hir_ty(
|
||||
// This counter value will already have been used, so this function will increment
|
||||
// it so the next value will be used next and return the region name that would
|
||||
// have been used.
|
||||
name: renctx.synthesize_region_name(),
|
||||
name: self.synthesize_region_name(),
|
||||
source: RegionNameSource::CannotMatchHirTy(span, type_name),
|
||||
})
|
||||
} else {
|
||||
@ -461,7 +421,6 @@ fn give_name_if_we_can_match_hir_ty(
|
||||
needle_fr: RegionVid,
|
||||
argument_ty: Ty<'tcx>,
|
||||
argument_hir_ty: &hir::Ty<'_>,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> Option<RegionName> {
|
||||
let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> =
|
||||
&mut vec![(argument_ty, argument_hir_ty)];
|
||||
@ -479,7 +438,7 @@ fn give_name_if_we_can_match_hir_ty(
|
||||
hir::TyKind::Rptr(_lifetime, referent_hir_ty),
|
||||
) => {
|
||||
if region.to_region_vid() == needle_fr {
|
||||
let region_name = renctx.synthesize_region_name();
|
||||
let region_name = self.synthesize_region_name();
|
||||
|
||||
// Just grab the first character, the `&`.
|
||||
let source_map = self.infcx.tcx.sess.source_map();
|
||||
@ -512,7 +471,6 @@ fn give_name_if_we_can_match_hir_ty(
|
||||
substs,
|
||||
needle_fr,
|
||||
last_segment,
|
||||
renctx,
|
||||
search_stack,
|
||||
) {
|
||||
return Some(name);
|
||||
@ -557,7 +515,6 @@ fn match_adt_and_segment<'hir>(
|
||||
substs: SubstsRef<'tcx>,
|
||||
needle_fr: RegionVid,
|
||||
last_segment: &'hir hir::PathSegment<'hir>,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
|
||||
) -> Option<RegionName> {
|
||||
// Did the user give explicit arguments? (e.g., `Foo<..>`)
|
||||
@ -569,7 +526,7 @@ fn match_adt_and_segment<'hir>(
|
||||
| hir::LifetimeName::Error
|
||||
| hir::LifetimeName::Static
|
||||
| hir::LifetimeName::Underscore => {
|
||||
let region_name = renctx.synthesize_region_name();
|
||||
let region_name = self.synthesize_region_name();
|
||||
let ampersand_span = lifetime.span;
|
||||
Some(RegionName {
|
||||
name: region_name,
|
||||
@ -650,18 +607,14 @@ fn try_match_adt_and_generic_args<'hir>(
|
||||
/// | let x = Some(&22);
|
||||
/// - fully elaborated type of `x` is `Option<&'1 u32>`
|
||||
/// ```
|
||||
fn give_name_if_anonymous_region_appears_in_upvars(
|
||||
&self,
|
||||
fr: RegionVid,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> Option<RegionName> {
|
||||
fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option<RegionName> {
|
||||
let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
|
||||
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
|
||||
self.infcx.tcx,
|
||||
&self.upvars,
|
||||
upvar_index,
|
||||
);
|
||||
let region_name = renctx.synthesize_region_name();
|
||||
let region_name = self.synthesize_region_name();
|
||||
|
||||
Some(RegionName {
|
||||
name: region_name,
|
||||
@ -673,11 +626,7 @@ fn give_name_if_anonymous_region_appears_in_upvars(
|
||||
/// must be a closure since, in a free fn, such an argument would
|
||||
/// have to either also appear in an argument (if using elision)
|
||||
/// or be early bound (named, not in argument).
|
||||
fn give_name_if_anonymous_region_appears_in_output(
|
||||
&self,
|
||||
fr: RegionVid,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> Option<RegionName> {
|
||||
fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
|
||||
@ -687,7 +636,7 @@ fn give_name_if_anonymous_region_appears_in_output(
|
||||
}
|
||||
|
||||
let mut highlight = RegionHighlightMode::default();
|
||||
highlight.highlighting_region_vid(fr, renctx.counter);
|
||||
highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
|
||||
let type_name = self.infcx.extract_type_name(&return_ty, Some(highlight)).0;
|
||||
|
||||
let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id).expect("non-local mir");
|
||||
@ -714,7 +663,7 @@ fn give_name_if_anonymous_region_appears_in_output(
|
||||
// This counter value will already have been used, so this function will increment it
|
||||
// so the next value will be used next and return the region name that would have been
|
||||
// used.
|
||||
name: renctx.synthesize_region_name(),
|
||||
name: self.synthesize_region_name(),
|
||||
source: RegionNameSource::AnonRegionFromOutput(
|
||||
return_span,
|
||||
mir_description.to_string(),
|
||||
@ -726,7 +675,6 @@ fn give_name_if_anonymous_region_appears_in_output(
|
||||
fn give_name_if_anonymous_region_appears_in_yield_ty(
|
||||
&self,
|
||||
fr: RegionVid,
|
||||
renctx: &mut RegionErrorNamingCtx,
|
||||
) -> Option<RegionName> {
|
||||
// Note: generators from `async fn` yield `()`, so we don't have to
|
||||
// worry about them here.
|
||||
@ -740,7 +688,7 @@ fn give_name_if_anonymous_region_appears_in_yield_ty(
|
||||
}
|
||||
|
||||
let mut highlight = RegionHighlightMode::default();
|
||||
highlight.highlighting_region_vid(fr, renctx.counter);
|
||||
highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
|
||||
let type_name = self.infcx.extract_type_name(&yield_ty, Some(highlight)).0;
|
||||
|
||||
let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id).expect("non-local mir");
|
||||
@ -759,7 +707,7 @@ fn give_name_if_anonymous_region_appears_in_yield_ty(
|
||||
);
|
||||
|
||||
Some(RegionName {
|
||||
name: renctx.synthesize_region_name(),
|
||||
name: self.synthesize_region_name(),
|
||||
source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name),
|
||||
})
|
||||
}
|
||||
|
@ -11,7 +11,8 @@
|
||||
use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
|
||||
use rustc::mir::{Terminator, TerminatorKind};
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::{self, RegionVid, TyCtxt};
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
|
||||
@ -21,6 +22,7 @@
|
||||
use rustc_index::vec::IndexVec;
|
||||
|
||||
use smallvec::SmallVec;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
@ -39,7 +41,7 @@
|
||||
use crate::dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
|
||||
use crate::transform::MirSource;
|
||||
|
||||
use self::diagnostics::AccessKind;
|
||||
use self::diagnostics::{AccessKind, RegionName};
|
||||
use self::flows::Flows;
|
||||
use self::location::LocationTable;
|
||||
use self::prefixes::PrefixSet;
|
||||
@ -290,6 +292,8 @@ fn do_mir_borrowck<'a, 'tcx>(
|
||||
dominators,
|
||||
upvars,
|
||||
local_names,
|
||||
region_names: RefCell::default(),
|
||||
next_region_name: RefCell::new(1),
|
||||
};
|
||||
|
||||
// Compute and report region errors, if any.
|
||||
@ -489,6 +493,13 @@ fn do_mir_borrowck<'a, 'tcx>(
|
||||
|
||||
/// Names of local (user) variables (extracted from `var_debug_info`).
|
||||
local_names: IndexVec<Local, Option<Name>>,
|
||||
|
||||
/// Record the region names generated for each region in the given
|
||||
/// MIR def so that we can reuse them later in help/error messages.
|
||||
region_names: RefCell<FxHashMap<RegionVid, RegionName>>,
|
||||
|
||||
/// The counter for generating new region names.
|
||||
next_region_name: RefCell<usize>,
|
||||
}
|
||||
|
||||
// Check that:
|
||||
|
@ -1603,23 +1603,6 @@ fn check_member_constraints(
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the region outlived by `longer_fr` and live at `element`.
|
||||
crate fn region_from_element(&self, longer_fr: RegionVid, element: RegionElement) -> RegionVid {
|
||||
match element {
|
||||
RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
|
||||
RegionElement::RootUniversalRegion(r) => r,
|
||||
RegionElement::PlaceholderRegion(error_placeholder) => self
|
||||
.definitions
|
||||
.iter_enumerated()
|
||||
.filter_map(|(r, definition)| match definition.origin {
|
||||
NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
|
||||
_ => None,
|
||||
})
|
||||
.next()
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
/// We have a constraint `fr1: fr2` that is not satisfied, where
|
||||
/// `fr2` represents some universal region. Here, `r` is some
|
||||
/// region where we know that `fr1: r` and this function has the
|
||||
|
@ -87,12 +87,12 @@ error[E0597]: `ap1` does not live long enough
|
||||
--> $DIR/variadic-ffi-4.rs:24:11
|
||||
|
|
||||
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
| - let's call the lifetime of this reference `'3`
|
||||
LL | ap0 = &mut ap1;
|
||||
| ------^^^^^^^^
|
||||
| | |
|
||||
| | borrowed value does not live long enough
|
||||
| assignment requires that `ap1` is borrowed for `'1`
|
||||
| assignment requires that `ap1` is borrowed for `'3`
|
||||
...
|
||||
LL | }
|
||||
| - `ap1` dropped here while still borrowed
|
||||
|
Loading…
Reference in New Issue
Block a user