Rollup merge of #137102 - compiler-errors:name_regions2, r=oli-obk
Rework `name_regions` to not rely on reverse scc graph for non-member-constrain usages Fixes https://github.com/rust-lang/rust/issues/137015 Splits the `name_regions` into two versions: One meant for member region constraint error reporting (which I've renamed to `name_regions_for_member_constraint`), and one meant *just* to replace region vids with an external region. Use the latter in the usage sites I added in #136559, since the regions returned by `name_regions_for_member_constraint` are also not *totally* accurate (which is fine for how they're used for member region constraint error reporting -- they're intentionally returning overapproximated universal regions so that we have something to name in `+ use<'a>` suggestions, because opaques can only capture universal regions and since member region constraints don't insert any edges into the region graph, the error region is probably gonna be shorter than a universal region) and because that function requires the reverse scc graph to have been computed which isn't done for our usages in #136559.
This commit is contained in:
commit
ea9c8d9c17
4 changed files with 58 additions and 7 deletions
|
@ -14,7 +14,10 @@ use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::hir::place::PlaceBase;
|
use rustc_middle::hir::place::PlaceBase;
|
||||||
use rustc_middle::mir::{AnnotationSource, ConstraintCategory, ReturnConstraint};
|
use rustc_middle::mir::{AnnotationSource, ConstraintCategory, ReturnConstraint};
|
||||||
use rustc_middle::ty::{self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeVisitor};
|
use rustc_middle::ty::fold::fold_regions;
|
||||||
|
use rustc_middle::ty::{
|
||||||
|
self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor,
|
||||||
|
};
|
||||||
use rustc_span::{Ident, Span, kw};
|
use rustc_span::{Ident, Span, kw};
|
||||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||||
use rustc_trait_selection::error_reporting::infer::nice_region_error::{
|
use rustc_trait_selection::error_reporting::infer::nice_region_error::{
|
||||||
|
@ -183,6 +186,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Map the regions in the type to named regions, where possible.
|
||||||
|
fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
|
||||||
|
where
|
||||||
|
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||||
|
{
|
||||||
|
fold_regions(tcx, ty, |region, _| match *region {
|
||||||
|
ty::ReVar(vid) => self.to_error_region(vid).unwrap_or(region),
|
||||||
|
_ => region,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if a closure is inferred to be an `FnMut` closure.
|
/// Returns `true` if a closure is inferred to be an `FnMut` closure.
|
||||||
fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
|
fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
|
||||||
if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).as_deref()
|
if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).as_deref()
|
||||||
|
@ -314,7 +328,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
let type_test_span = type_test.span;
|
let type_test_span = type_test.span;
|
||||||
|
|
||||||
if let Some(lower_bound_region) = lower_bound_region {
|
if let Some(lower_bound_region) = lower_bound_region {
|
||||||
let generic_ty = self.regioncx.name_regions(
|
let generic_ty = self.name_regions(
|
||||||
self.infcx.tcx,
|
self.infcx.tcx,
|
||||||
type_test.generic_kind.to_ty(self.infcx.tcx),
|
type_test.generic_kind.to_ty(self.infcx.tcx),
|
||||||
);
|
);
|
||||||
|
@ -323,7 +337,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
self.body.source.def_id().expect_local(),
|
self.body.source.def_id().expect_local(),
|
||||||
type_test_span,
|
type_test_span,
|
||||||
Some(origin),
|
Some(origin),
|
||||||
self.regioncx.name_regions(self.infcx.tcx, type_test.generic_kind),
|
self.name_regions(self.infcx.tcx, type_test.generic_kind),
|
||||||
lower_bound_region,
|
lower_bound_region,
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
|
@ -354,9 +368,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, key, member_region } => {
|
RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, key, member_region } => {
|
||||||
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
|
let named_ty =
|
||||||
let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
|
self.regioncx.name_regions_for_member_constraint(self.infcx.tcx, hidden_ty);
|
||||||
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
let named_key =
|
||||||
|
self.regioncx.name_regions_for_member_constraint(self.infcx.tcx, key);
|
||||||
|
let named_region = self
|
||||||
|
.regioncx
|
||||||
|
.name_regions_for_member_constraint(self.infcx.tcx, member_region);
|
||||||
let diag = unexpected_hidden_region_diagnostic(
|
let diag = unexpected_hidden_region_diagnostic(
|
||||||
self.infcx,
|
self.infcx,
|
||||||
self.mir_def_id(),
|
self.mir_def_id(),
|
||||||
|
|
|
@ -204,7 +204,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
/// that the regions produced are in fact equal to the named region they are
|
/// that the regions produced are in fact equal to the named region they are
|
||||||
/// replaced with. This is fine because this function is only to improve the
|
/// replaced with. This is fine because this function is only to improve the
|
||||||
/// region names in error messages.
|
/// region names in error messages.
|
||||||
pub(crate) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
|
///
|
||||||
|
/// This differs from `MirBorrowckCtxt::name_regions` since it is particularly
|
||||||
|
/// lax with mapping region vids that are *shorter* than a universal region to
|
||||||
|
/// that universal region. This is useful for member region constraints since
|
||||||
|
/// we want to suggest a universal region name to capture even if it's technically
|
||||||
|
/// not equal to the error region.
|
||||||
|
pub(crate) fn name_regions_for_member_constraint<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
|
||||||
where
|
where
|
||||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||||
{
|
{
|
||||||
|
|
13
tests/ui/borrowck/alias-liveness/name-region.rs
Normal file
13
tests/ui/borrowck/alias-liveness/name-region.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Make sure we don't ICE when trying to name the regions that appear in the alias
|
||||||
|
// of the type test error.
|
||||||
|
|
||||||
|
trait AnotherTrait {
|
||||||
|
type Ty2<'a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_alias<T: AnotherTrait>(_: &'static T::Ty2<'_>) {
|
||||||
|
let _: &'static T::Ty2<'_>;
|
||||||
|
//~^ ERROR the associated type `<T as AnotherTrait>::Ty2<'_>` may not live long enough
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
14
tests/ui/borrowck/alias-liveness/name-region.stderr
Normal file
14
tests/ui/borrowck/alias-liveness/name-region.stderr
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
error[E0310]: the associated type `<T as AnotherTrait>::Ty2<'_>` may not live long enough
|
||||||
|
--> $DIR/name-region.rs:9:12
|
||||||
|
|
|
||||||
|
LL | let _: &'static T::Ty2<'_>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| the associated type `<T as AnotherTrait>::Ty2<'_>` must be valid for the static lifetime...
|
||||||
|
| ...so that the type `<T as AnotherTrait>::Ty2<'_>` will meet its required lifetime bounds
|
||||||
|
|
|
||||||
|
= help: consider adding an explicit lifetime bound `<T as AnotherTrait>::Ty2<'_>: 'static`...
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0310`.
|
Loading…
Add table
Add a link
Reference in a new issue