Skip to content

Commit 81d403e

Browse files
committed
rarw
1 parent c051f69 commit 81d403e

File tree

9 files changed

+291
-169
lines changed

9 files changed

+291
-169
lines changed

compiler/rustc_borrowck/src/dataflow.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::fmt;
22

33
use rustc_data_structures::fx::FxIndexMap;
4-
use rustc_data_structures::graph;
54
use rustc_index::bit_set::DenseBitSet;
65
use rustc_middle::mir::{
76
self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges,

compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ pub(crate) use bound_region_errors::{ToUniverseInfo, UniverseInfo};
5858
pub(crate) use move_errors::{IllegalMoveOriginKind, MoveError};
5959
pub(crate) use mutability_errors::AccessKind;
6060
pub(crate) use outlives_suggestion::OutlivesSuggestionBuilder;
61-
pub(crate) use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
61+
pub(crate) use region_errors::{
62+
ErrorConstraintInfo, RegionErrorKind, RegionErrors, approx_universal_upper_bound,
63+
};
6264
pub(crate) use region_name::{RegionName, RegionNameSource};
6365
pub(crate) use rustc_trait_selection::error_reporting::traits::call_kind::CallKind;
6466

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

Lines changed: 64 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Error reporting machinery for lifetime errors.
22
3+
use rustc_data_structures::frozen::Frozen;
34
use rustc_data_structures::fx::FxIndexSet;
45
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan};
56
use rustc_hir as hir;
@@ -10,6 +11,7 @@ use rustc_hir::def::Res::Def;
1011
use rustc_hir::def_id::DefId;
1112
use rustc_hir::intravisit::VisitorExt;
1213
use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate};
14+
use rustc_index::IndexVec;
1315
use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound};
1416
use rustc_middle::bug;
1517
use rustc_middle::hir::place::PlaceBase;
@@ -23,19 +25,20 @@ use rustc_trait_selection::error_reporting::infer::nice_region_error::{
2325
self, HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor, find_anon_type,
2426
find_param_with_region, suggest_adding_lifetime_params,
2527
};
26-
use rustc_trait_selection::error_reporting::infer::region::unexpected_hidden_region_diagnostic;
2728
use rustc_trait_selection::infer::InferCtxtExt;
2829
use rustc_trait_selection::traits::{Obligation, ObligationCtxt};
2930
use tracing::{debug, instrument, trace};
3031

3132
use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
33+
use crate::constraints::ConstraintSccIndex;
3234
use crate::nll::ConstraintDescription;
33-
use crate::region_infer::values::RegionElement;
34-
use crate::region_infer::{BlameConstraint, TypeTest};
35+
use crate::region_infer::values::{RegionElement, RegionValues};
36+
use crate::region_infer::{BlameConstraint, ConstraintSccs, RegionDefinition, TypeTest};
3537
use crate::session_diagnostics::{
3638
FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr,
3739
LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote,
3840
};
41+
use crate::type_check::free_region_relations::UniversalRegionRelations;
3942
use crate::universal_regions::DefiningTy;
4043
use crate::{MirBorrowckCtxt, borrowck_errors, fluent_generated as fluent};
4144

@@ -108,18 +111,6 @@ pub(crate) enum RegionErrorKind<'tcx> {
108111
/// A generic bound failure for a type test (`T: 'a`).
109112
TypeTestError { type_test: TypeTest<'tcx> },
110113

111-
/// An unexpected hidden region for an opaque type.
112-
UnexpectedHiddenRegion {
113-
/// The span for the member constraint.
114-
span: Span,
115-
/// The hidden type.
116-
hidden_ty: Ty<'tcx>,
117-
/// The opaque type.
118-
key: ty::OpaqueTypeKey<'tcx>,
119-
/// The unexpected region.
120-
member_region: ty::Region<'tcx>,
121-
},
122-
123114
/// Higher-ranked subtyping error.
124115
BoundUniversalRegionError {
125116
/// The placeholder free region.
@@ -156,6 +147,64 @@ pub(crate) struct ErrorConstraintInfo<'tcx> {
156147
pub(super) span: Span,
157148
}
158149

150+
/// Like `universal_upper_bound`, but returns an approximation more suitable
151+
/// for diagnostics. If `r` contains multiple disjoint universal regions
152+
/// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region.
153+
/// This corresponds to picking named regions over unnamed regions
154+
/// (e.g. picking early-bound regions over a closure late-bound region).
155+
///
156+
/// This means that the returned value may not be a true upper bound, since
157+
/// only 'static is known to outlive disjoint universal regions.
158+
/// Therefore, this method should only be used in diagnostic code,
159+
/// where displaying *some* named universal region is better than
160+
/// falling back to 'static.
161+
#[instrument(
162+
level = "debug",
163+
skip(universal_region_relations, constraint_sccs, scc_values, definitions)
164+
)]
165+
pub(crate) fn approx_universal_upper_bound<'tcx>(
166+
universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
167+
constraint_sccs: &ConstraintSccs,
168+
scc_values: &RegionValues<ConstraintSccIndex>,
169+
definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
170+
r: RegionVid,
171+
) -> RegionVid {
172+
// Find the smallest universal region that contains all other
173+
// universal regions within `region`.
174+
let mut lub = universal_region_relations.universal_regions.fr_fn_body;
175+
let r_scc = constraint_sccs.scc(r);
176+
let static_r = universal_region_relations.universal_regions.fr_static;
177+
for ur in scc_values.universal_regions_outlived_by(r_scc) {
178+
let new_lub = universal_region_relations.postdom_upper_bound(lub, ur);
179+
debug!(?ur, ?lub, ?new_lub);
180+
// The upper bound of two non-static regions is static: this
181+
// means we know nothing about the relationship between these
182+
// two regions. Pick a 'better' one to use when constructing
183+
// a diagnostic
184+
if ur != static_r && lub != static_r && new_lub == static_r {
185+
// Prefer the region with an `external_name` - this
186+
// indicates that the region is early-bound, so working with
187+
// it can produce a nicer error.
188+
if definitions[ur].external_name.is_some() {
189+
lub = ur;
190+
} else if definitions[lub].external_name.is_some() {
191+
// Leave lub unchanged
192+
} else {
193+
// If we get here, we don't have any reason to prefer
194+
// one region over the other. Just pick the
195+
// one with the lower index for now.
196+
lub = std::cmp::min(ur, lub);
197+
}
198+
} else {
199+
lub = new_lub;
200+
}
201+
}
202+
203+
debug!(?r, ?lub);
204+
205+
lub
206+
}
207+
159208
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
160209
/// Converts a region inference variable into a `ty::Region` that
161210
/// we can use for error reporting. If `r` is universally bound,
@@ -311,9 +360,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
311360
// buffered in the `MirBorrowckCtxt`.
312361

313362
let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
314-
let mut last_unexpected_hidden_region: Option<(Span, Ty<'_>, ty::OpaqueTypeKey<'tcx>)> =
315-
None;
316-
317363
for (nll_error, _) in nll_errors.into_iter() {
318364
match nll_error {
319365
RegionErrorKind::TypeTestError { type_test } => {
@@ -363,30 +409,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
363409
}
364410
}
365411

366-
RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, key, member_region } => {
367-
let named_ty =
368-
self.regioncx.name_regions_for_member_constraint(self.infcx.tcx, hidden_ty);
369-
let named_key =
370-
self.regioncx.name_regions_for_member_constraint(self.infcx.tcx, key);
371-
let named_region = self
372-
.regioncx
373-
.name_regions_for_member_constraint(self.infcx.tcx, member_region);
374-
let diag = unexpected_hidden_region_diagnostic(
375-
self.infcx,
376-
self.mir_def_id(),
377-
span,
378-
named_ty,
379-
named_region,
380-
named_key,
381-
);
382-
if last_unexpected_hidden_region != Some((span, named_ty, named_key)) {
383-
self.buffer_error(diag);
384-
last_unexpected_hidden_region = Some((span, named_ty, named_key));
385-
} else {
386-
diag.delay_as_bug();
387-
}
388-
}
389-
390412
RegionErrorKind::BoundUniversalRegionError {
391413
longer_fr,
392414
placeholder,

compiler/rustc_borrowck/src/nll.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::rc::Rc;
66
use std::str::FromStr;
77

88
use polonius_engine::{Algorithm, Output};
9-
use rustc_index::{IndexSlice, IndexVec};
9+
use rustc_index::IndexSlice;
1010
use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
1111
use rustc_middle::mir::{Body, PassWhere, Promoted, create_dump_file, dump_enabled, dump_mir};
1212
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -26,8 +26,8 @@ use crate::polonius::PoloniusDiagnosticsContext;
2626
use crate::polonius::legacy::{
2727
PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
2828
};
29+
use crate::region_infer::RegionInferenceContext;
2930
use crate::region_infer::opaque_types::handle_opaque_type_uses;
30-
use crate::region_infer::{RegionDefinition, RegionInferenceContext};
3131
use crate::type_check::{self, MirTypeckResults};
3232
use crate::universal_regions::UniversalRegions;
3333
use crate::{

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_errors::Diag;
88
use rustc_hir::def_id::CRATE_DEF_ID;
99
use rustc_index::IndexVec;
1010
use rustc_infer::infer::outlives::test_type_match;
11-
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
11+
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound, VerifyIfEq};
1212
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
1313
use rustc_middle::bug;
1414
use rustc_middle::mir::{
@@ -28,7 +28,6 @@ use crate::dataflow::BorrowIndex;
2828
use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo};
2929
use crate::polonius::LiveLoans;
3030
use crate::polonius::legacy::PoloniusOutput;
31-
use crate::region_infer::reverse_sccs::ReverseSccGraph;
3231
use crate::region_infer::values::{LivenessValues, RegionElement, RegionValues, ToElementIndex};
3332
use crate::type_check::free_region_relations::UniversalRegionRelations;
3433
use crate::type_check::{Locations, MirTypeckRegionConstraints};
@@ -870,41 +869,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
870869
#[instrument(level = "debug", skip(self))]
871870
pub(crate) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
872871
debug!("{}", self.region_value_str(r));
873-
874-
// Find the smallest universal region that contains all other
875-
// universal regions within `region`.
876-
let mut lub = self.universal_regions().fr_fn_body;
877-
let r_scc = self.constraint_sccs.scc(r);
878-
let static_r = self.universal_regions().fr_static;
879-
for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
880-
let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
881-
debug!(?ur, ?lub, ?new_lub);
882-
// The upper bound of two non-static regions is static: this
883-
// means we know nothing about the relationship between these
884-
// two regions. Pick a 'better' one to use when constructing
885-
// a diagnostic
886-
if ur != static_r && lub != static_r && new_lub == static_r {
887-
// Prefer the region with an `external_name` - this
888-
// indicates that the region is early-bound, so working with
889-
// it can produce a nicer error.
890-
if self.region_definition(ur).external_name.is_some() {
891-
lub = ur;
892-
} else if self.region_definition(lub).external_name.is_some() {
893-
// Leave lub unchanged
894-
} else {
895-
// If we get here, we don't have any reason to prefer
896-
// one region over the other. Just pick the
897-
// one with the lower index for now.
898-
lub = std::cmp::min(ur, lub);
899-
}
900-
} else {
901-
lub = new_lub;
902-
}
903-
}
904-
905-
debug!(?r, ?lub);
906-
907-
lub
872+
crate::diagnostics::approx_universal_upper_bound(
873+
&self.universal_region_relations,
874+
&self.constraint_sccs,
875+
&self.scc_values,
876+
&self.definitions,
877+
r,
878+
)
908879
}
909880

910881
/// Tests if `test` is true when applied to `lower_bound` at

0 commit comments

Comments
 (0)