From a804868bbf578dada5249ac3c79b7b524684c78e Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 28 Dec 2019 20:36:42 -0600 Subject: [PATCH] Get rid of RegionErrorNamingContext --- .../diagnostics/explain_borrow.rs | 7 +- .../borrow_check/diagnostics/mod.rs | 2 +- .../diagnostics/outlives_suggestion.rs | 25 +--- .../borrow_check/diagnostics/region_errors.rs | 51 +++---- .../borrow_check/diagnostics/region_name.rs | 138 ++++++------------ src/librustc_mir/borrow_check/mod.rs | 15 +- .../borrow_check/region_infer/mod.rs | 17 --- .../ui/c-variadic/variadic-ffi-4.nll.stderr | 4 +- 8 files changed, 88 insertions(+), 171 deletions(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs index ca5cf5bc741a..01b7c5645fe8 100644 --- a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs +++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs @@ -16,8 +16,8 @@ use rustc_span::symbol::Symbol; 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 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { |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) } diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 3f3bdb9d36c7..0fc73d33f900 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -32,7 +32,7 @@ mod region_errors; 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); diff --git a/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs index be067fcf4f26..ee9489078bdb 100644 --- a/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs +++ b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs @@ -12,7 +12,7 @@ use smallvec::SmallVec; 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 @@ impl OutlivesSuggestionBuilder { fn region_vid_to_name( &self, mbcx: &MirBorrowckCtxt<'_, '_>, - renctx: &mut RegionErrorNamingCtx, region: RegionVid, ) -> Option { - 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 @@ impl OutlivesSuggestionBuilder { 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 @@ impl OutlivesSuggestionBuilder { 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::>(); // No suggestable outlived lifetimes. @@ -171,12 +167,11 @@ impl OutlivesSuggestionBuilder { &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 @@ impl OutlivesSuggestionBuilder { /// 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 @@ impl OutlivesSuggestionBuilder { } // 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() { diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index f3dc8e72e301..729a679e92a3 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -19,7 +19,7 @@ use crate::borrow_check::{ 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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // 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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { 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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } // 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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { 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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { 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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// 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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { 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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// 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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { || (*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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// | ^^^^^^^^^^^^^^ 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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { 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) { diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs index 7ce29713240c..f7aeec5e76ee 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs @@ -3,7 +3,6 @@ use std::fmt::{self, Display}; 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 @@ crate enum RegionNameSource { 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, - - /// 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 @@ impl Display for RegionName { } 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 { - debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter); + crate fn give_region_a_name(&self, fr: RegionVid) -> Option { + 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 { + fn give_name_from_error_region(&self, fr: RegionVid) -> Option { let error_region = self.to_error_region(fr)?; let tcx = self.infcx.tcx; @@ -262,7 +230,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { } 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { fn give_name_if_anonymous_region_appears_in_arguments( &self, fr: RegionVid, - renctx: &mut RegionErrorNamingCtx, ) -> Option { 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { needle_fr: RegionVid, argument_ty: Ty<'tcx>, argument_index: usize, - renctx: &mut RegionErrorNamingCtx, ) -> Option { 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // (`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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { &self, needle_fr: RegionVid, argument_ty: Ty<'tcx>, - renctx: &mut RegionErrorNamingCtx, ) -> Option { - 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { needle_fr: RegionVid, argument_ty: Ty<'tcx>, argument_hir_ty: &hir::Ty<'_>, - renctx: &mut RegionErrorNamingCtx, ) -> Option { let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> = &mut vec![(argument_ty, argument_hir_ty)]; @@ -479,7 +438,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { substs, needle_fr, last_segment, - renctx, search_stack, ) { return Some(name); @@ -557,7 +515,6 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { 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 { // Did the user give explicit arguments? (e.g., `Foo<..>`) @@ -569,7 +526,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { | 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { /// | 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 { + fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option { 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { /// 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 { + fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option { let tcx = self.infcx.tcx; let return_ty = self.regioncx.universal_regions().unnormalized_output_ty; @@ -687,7 +636,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { } 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { fn give_name_if_anonymous_region_appears_in_yield_ty( &self, fr: RegionVid, - renctx: &mut RegionErrorNamingCtx, ) -> Option { // Note: generators from `async fn` yield `()`, so we don't have to // worry about them here. @@ -740,7 +688,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { } 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 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ); Some(RegionName { - name: renctx.synthesize_region_name(), + name: self.synthesize_region_name(), source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name), }) } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 0ad9d4492b20..90927069242b 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -11,7 +11,8 @@ use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; 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::bit_set::BitSet; 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::{do_dataflow, DebugFormatted}; 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 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { /// Names of local (user) variables (extracted from `var_debug_info`). local_names: IndexVec>, + + /// 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>, + + /// The counter for generating new region names. + next_region_name: RefCell, } // Check that: diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index 359f75cac837..180bb95cab9f 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -1603,23 +1603,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - /// 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 diff --git a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr index 8b70b15fa6e5..89107e799bd2 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr @@ -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