Skip to content

Commit e4375da

Browse files
authored
Rollup merge of #151863 - amandasystems:streamline-borrow-error-handling, r=lcnr
Borrowck: simplify diagnostics for placeholders This folds the call to `region_from_element` into `RegionInferenceContext`, and simplifies the error variant for this case to only talk about regions as opposed to elements. This is the only case where a `RegionElement` leaks out of region inference, so now they can be considered internal to region inference (though that currently isn't expressed). It also clarifies the type information on the methods called to emphasise the fact that they only ever use placeholder regions in the diagnostics completely ignore any other element. It also adds a bunch of FIXMEs to some fishy statements that conjure universes from what seems like arbitrary integers. This was lifted from #142623. r? @lcnr
2 parents 3db13e2 + f53eed5 commit e4375da

File tree

3 files changed

+62
-51
lines changed

3 files changed

+62
-51
lines changed

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_
2424
use tracing::{debug, instrument};
2525

2626
use crate::MirBorrowckCtxt;
27-
use crate::region_infer::values::RegionElement;
2827
use crate::session_diagnostics::{
2928
HigherRankedErrorCause, HigherRankedLifetimeError, HigherRankedSubtypeError,
3029
};
@@ -49,11 +48,12 @@ impl<'tcx> UniverseInfo<'tcx> {
4948
UniverseInfo::RelateTys { expected, found }
5049
}
5150

51+
/// Report an error where an element erroneously made its way into `placeholder`.
5252
pub(crate) fn report_erroneous_element(
5353
&self,
5454
mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
5555
placeholder: ty::PlaceholderRegion<'tcx>,
56-
error_element: RegionElement<'tcx>,
56+
error_element: Option<ty::PlaceholderRegion<'tcx>>,
5757
cause: ObligationCause<'tcx>,
5858
) {
5959
match *self {
@@ -146,14 +146,14 @@ pub(crate) trait TypeOpInfo<'tcx> {
146146
) -> Option<Diag<'infcx>>;
147147

148148
/// Constraints require that `error_element` appear in the
149-
/// values of `placeholder`, but this cannot be proven to
149+
/// values of `placeholder`, but this cannot be proven to
150150
/// hold. Report an error.
151151
#[instrument(level = "debug", skip(self, mbcx))]
152152
fn report_erroneous_element(
153153
&self,
154154
mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
155155
placeholder: ty::PlaceholderRegion<'tcx>,
156-
error_element: RegionElement<'tcx>,
156+
error_element: Option<ty::PlaceholderRegion<'tcx>>,
157157
cause: ObligationCause<'tcx>,
158158
) {
159159
let tcx = mbcx.infcx.tcx;
@@ -172,19 +172,17 @@ pub(crate) trait TypeOpInfo<'tcx> {
172172
ty::PlaceholderRegion::new(adjusted_universe.into(), placeholder.bound),
173173
);
174174

175-
let error_region =
176-
if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
177-
let adjusted_universe =
178-
error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
179-
adjusted_universe.map(|adjusted| {
180-
ty::Region::new_placeholder(
181-
tcx,
182-
ty::PlaceholderRegion::new(adjusted.into(), error_placeholder.bound),
183-
)
184-
})
185-
} else {
186-
None
187-
};
175+
// FIXME: one day this should just be error_element,
176+
// and this method shouldn't do anything.
177+
let error_region = error_element.and_then(|e| {
178+
let adjusted_universe = e.universe.as_u32().checked_sub(base_universe.as_u32());
179+
adjusted_universe.map(|adjusted| {
180+
ty::Region::new_placeholder(
181+
tcx,
182+
ty::PlaceholderRegion::new(adjusted.into(), e.bound),
183+
)
184+
})
185+
});
188186

189187
debug!(?placeholder_region);
190188

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use tracing::{debug, instrument, trace};
2929

3030
use super::{LIMITATION_NOTE, OutlivesSuggestionBuilder, RegionName, RegionNameSource};
3131
use crate::nll::ConstraintDescription;
32-
use crate::region_infer::values::RegionElement;
3332
use crate::region_infer::{BlameConstraint, TypeTest};
3433
use crate::session_diagnostics::{
3534
FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr,
@@ -104,15 +103,9 @@ pub(crate) enum RegionErrorKind<'tcx> {
104103
/// A generic bound failure for a type test (`T: 'a`).
105104
TypeTestError { type_test: TypeTest<'tcx> },
106105

107-
/// Higher-ranked subtyping error.
108-
BoundUniversalRegionError {
109-
/// The placeholder free region.
110-
longer_fr: RegionVid,
111-
/// The region element that erroneously must be outlived by `longer_fr`.
112-
error_element: RegionElement<'tcx>,
113-
/// The placeholder region.
114-
placeholder: ty::PlaceholderRegion<'tcx>,
115-
},
106+
/// 'p outlives 'r, which does not hold. 'p is always a placeholder
107+
/// and 'r is some other region.
108+
PlaceholderOutlivesIllegalRegion { longer_fr: RegionVid, illegally_outlived_r: RegionVid },
116109

117110
/// Any other lifetime error.
118111
RegionError {
@@ -360,28 +353,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
360353
}
361354
}
362355

363-
RegionErrorKind::BoundUniversalRegionError {
356+
RegionErrorKind::PlaceholderOutlivesIllegalRegion {
364357
longer_fr,
365-
placeholder,
366-
error_element,
358+
illegally_outlived_r,
367359
} => {
368-
let error_vid = self.regioncx.region_from_element(longer_fr, &error_element);
369-
370-
// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
371-
let cause = self
372-
.regioncx
373-
.best_blame_constraint(
374-
longer_fr,
375-
NllRegionVariableOrigin::Placeholder(placeholder),
376-
error_vid,
377-
)
378-
.0
379-
.cause;
380-
381-
let universe = placeholder.universe;
382-
let universe_info = self.regioncx.universe_info(universe);
383-
384-
universe_info.report_erroneous_element(self, placeholder, error_element, cause);
360+
self.report_erroneous_rvid_reaches_placeholder(longer_fr, illegally_outlived_r)
385361
}
386362

387363
RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
@@ -412,6 +388,43 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
412388
outlives_suggestion.add_suggestion(self);
413389
}
414390

391+
/// Report that `longer_fr: error_vid`, which doesn't hold,
392+
/// where `longer_fr` is a placeholder.
393+
fn report_erroneous_rvid_reaches_placeholder(
394+
&mut self,
395+
longer_fr: RegionVid,
396+
error_vid: RegionVid,
397+
) {
398+
use NllRegionVariableOrigin::*;
399+
400+
let origin_longer = self.regioncx.definitions[longer_fr].origin;
401+
402+
let Placeholder(placeholder) = origin_longer else {
403+
bug!("Expected {longer_fr:?} to come from placeholder!");
404+
};
405+
406+
// FIXME: Is throwing away the existential region really the best here?
407+
let error_region = match self.regioncx.definitions[error_vid].origin {
408+
FreeRegion | Existential { .. } => None,
409+
Placeholder(other_placeholder) => Some(other_placeholder),
410+
};
411+
412+
// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
413+
let cause =
414+
self.regioncx.best_blame_constraint(longer_fr, origin_longer, error_vid).0.cause;
415+
416+
// FIXME these methods should have better names, and also probably not be this generic.
417+
// FIXME note that we *throw away* the error element here! We probably want to
418+
// thread it through the computation further down and use it, but there currently isn't
419+
// anything there to receive it.
420+
self.regioncx.universe_info(placeholder.universe).report_erroneous_element(
421+
self,
422+
placeholder,
423+
error_region,
424+
cause,
425+
);
426+
}
427+
415428
/// Report an error because the universal region `fr` was required to outlive
416429
/// `outlived_fr` but it is not known to do so. For example:
417430
///

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,11 +1379,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
13791379
.elements_contained_in(longer_fr_scc)
13801380
.find(|e| *e != RegionElement::PlaceholderRegion(placeholder))
13811381
{
1382+
let illegally_outlived_r = self.region_from_element(longer_fr, &error_element);
13821383
// Stop after the first error, it gets too noisy otherwise, and does not provide more information.
1383-
errors_buffer.push(RegionErrorKind::BoundUniversalRegionError {
1384+
errors_buffer.push(RegionErrorKind::PlaceholderOutlivesIllegalRegion {
13841385
longer_fr,
1385-
error_element,
1386-
placeholder,
1386+
illegally_outlived_r,
13871387
});
13881388
} else {
13891389
debug!("check_bound_universal_region: all bounds satisfied");
@@ -1572,7 +1572,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
15721572
}
15731573

15741574
/// Get the region outlived by `longer_fr` and live at `element`.
1575-
pub(crate) fn region_from_element(
1575+
fn region_from_element(
15761576
&self,
15771577
longer_fr: RegionVid,
15781578
element: &RegionElement<'tcx>,

0 commit comments

Comments
 (0)