1
Fork 0

Auto merge of #98559 - jackh726:remove-reempty, r=oli-obk

Remove ReEmpty

r? rust-lang/types
This commit is contained in:
bors 2022-09-10 20:54:01 +00:00
commit 2287107588
32 changed files with 336 additions and 298 deletions

View file

@ -27,13 +27,6 @@ impl<'a> DescriptionCtx<'a> {
me.kind = "restatic";
}
ty::ReEmpty(ty::UniverseIndex::ROOT) => me.kind = "reempty",
ty::ReEmpty(ui) => {
me.kind = "reemptyuni";
me.arg = format!("{:?}", ui);
}
ty::RePlaceholder(_) => return None,
// FIXME(#13998) RePlaceholder should probably print like

View file

@ -180,11 +180,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
match *r {
ty::ReFree(_)
| ty::ReErased
| ty::ReStatic
| ty::ReEmpty(ty::UniverseIndex::ROOT)
| ty::ReEarlyBound(..) => r,
ty::ReFree(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyBound(..) => r,
ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region(
CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderRegion(placeholder) },
@ -199,10 +195,6 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
)
}
ty::ReEmpty(ui) => {
bug!("canonicalizing 'empty in universe {:?}", ui) // FIXME
}
_ => {
// Other than `'static` or `'empty`, the query
// response should be executing in a fully
@ -381,7 +373,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
ty::ReStatic
| ty::ReEarlyBound(..)
| ty::ReFree(_)
| ty::ReEmpty(_)
| ty::RePlaceholder(..)
| ty::ReErased => self.canonicalize_mode.canonicalize_free_region(self, r),
}

View file

@ -688,7 +688,6 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
ty::RePlaceholder(..)
| ty::ReVar(..)
| ty::ReEmpty(_)
| ty::ReStatic
| ty::ReEarlyBound(..)
| ty::ReFree(..) => {
@ -900,7 +899,6 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
ty::RePlaceholder(..)
| ty::ReVar(..)
| ty::ReEmpty(_)
| ty::ReStatic
| ty::ReEarlyBound(..)
| ty::ReFree(..) => {

View file

@ -97,11 +97,6 @@ pub(super) fn note_and_explain_region<'tcx>(
msg_span_from_free_region(tcx, region, alt_span)
}
ty::ReEmpty(ty::UniverseIndex::ROOT) => ("the empty lifetime".to_owned(), alt_span),
// uh oh, hope no user ever sees THIS
ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), alt_span),
ty::RePlaceholder(_) => return,
// FIXME(#13998) RePlaceholder should probably print like
@ -140,8 +135,6 @@ fn msg_span_from_free_region<'tcx>(
(msg, Some(span))
}
ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
ty::ReEmpty(ty::UniverseIndex::ROOT) => ("an empty lifetime".to_owned(), alt_span),
ty::ReEmpty(ui) => (format!("an empty lifetime in universe {:?}", ui), alt_span),
_ => bug!("{:?}", region),
}
}
@ -251,17 +244,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
// Explain the region we are capturing.
match *hidden_region {
ty::ReEmpty(ty::UniverseIndex::ROOT) => {
// All lifetimes shorter than the function body are `empty` in
// lexical region resolution. The default explanation of "an empty
// lifetime" isn't really accurate here.
let message = format!(
"hidden type `{}` captures lifetime smaller than the function body",
hidden_ty
);
err.span_note(span, &message);
}
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) => {
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
// Assuming regionck succeeded (*), we ought to always be
// capturing *some* region from the fn header, and hence it
// ought to be free. So under normal circumstances, we will go
@ -387,7 +370,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
RegionResolutionError::UpperBoundUniverseConflict(
_,
_,
var_universe,
_,
sup_origin,
sup_r,
) => {
@ -398,7 +381,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// placeholder. In practice, we expect more
// tailored errors that don't really use this
// value.
let sub_r = self.tcx.mk_region(ty::ReEmpty(var_universe));
let sub_r = self.tcx.lifetimes.re_erased;
self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
}

View file

@ -126,7 +126,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
| ty::ReFree(_)
| ty::ReVar(_)
| ty::RePlaceholder(..)
| ty::ReEmpty(_)
| ty::ReErased => {
// replace all free regions with 'erased
self.tcx().lifetimes.re_erased

View file

@ -15,8 +15,9 @@ use rustc_data_structures::graph::implementation::{
use rustc_data_structures::intern::Interned;
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::PlaceholderRegion;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
use rustc_middle::ty::{ReEarlyBound, ReErased, ReFree, ReStatic};
use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
use rustc_middle::ty::{Region, RegionVid};
use rustc_span::Span;
@ -51,6 +52,13 @@ pub struct LexicalRegionResolutions<'tcx> {
#[derive(Copy, Clone, Debug)]
pub(crate) enum VarValue<'tcx> {
/// Empty lifetime is for data that is never accessed. We tag the
/// empty lifetime with a universe -- the idea is that we don't
/// want `exists<'a> { forall<'b> { 'b: 'a } }` to be satisfiable.
/// Therefore, the `'empty` in a universe `U` is less than all
/// regions visible from `U`, but not less than regions not visible
/// from `U`.
Empty(ty::UniverseIndex),
Value(Region<'tcx>),
ErrorValue,
}
@ -117,7 +125,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
&mut self,
errors: &mut Vec<RegionResolutionError<'tcx>>,
) -> LexicalRegionResolutions<'tcx> {
let mut var_data = self.construct_var_data(self.tcx());
let mut var_data = self.construct_var_data();
if cfg!(debug_assertions) {
self.dump_constraints();
@ -137,13 +145,12 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
/// Initially, the value for all variables is set to `'empty`, the
/// empty region. The `expansion` phase will grow this larger.
fn construct_var_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> {
fn construct_var_data(&self) -> LexicalRegionResolutions<'tcx> {
LexicalRegionResolutions {
values: IndexVec::from_fn_n(
|vid| {
let vid_universe = self.var_infos[vid].universe;
let re_empty = tcx.mk_region(ty::ReEmpty(vid_universe));
VarValue::Value(re_empty)
VarValue::Empty(vid_universe)
},
self.num_vars(),
),
@ -189,20 +196,131 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
}
}
/// Gets the LUb of a given region and the empty region
fn lub_empty(&self, a_region: Region<'tcx>) -> Result<Region<'tcx>, PlaceholderRegion> {
match *a_region {
ReLateBound(..) | ReErased => {
bug!("cannot relate region: {:?}", a_region);
}
ReVar(v_id) => {
span_bug!(
self.var_infos[v_id].origin.span(),
"lub invoked with non-concrete regions: {:?}",
a_region,
);
}
ReStatic => {
// nothing lives longer than `'static`
Ok(self.tcx().lifetimes.re_static)
}
ReEarlyBound(_) | ReFree(_) => {
// All empty regions are less than early-bound, free,
// and scope regions.
Ok(a_region)
}
RePlaceholder(placeholder) => Err(placeholder),
}
}
fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
// In the first pass, we expand region vids according to constraints we
// have previously found. In the second pass, we loop through the region
// vids we expanded and expand *across* region vids (effectively
// "expanding" new `RegSubVar` constraints).
// Tracks the `VarSubVar` constraints generated for each region vid. We
// later use this to expand across vids.
let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len());
// Tracks the changed region vids.
let mut changes = Vec::new();
for constraint in self.data.constraints.keys() {
let (a_vid, a_region, b_vid, b_data) = match *constraint {
match *constraint {
Constraint::RegSubVar(a_region, b_vid) => {
let b_data = var_values.value_mut(b_vid);
(None, a_region, b_vid, b_data)
if self.expand_node(a_region, b_vid, b_data) {
changes.push(b_vid);
}
}
Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
VarValue::ErrorValue => continue,
VarValue::Empty(a_universe) => {
let b_data = var_values.value_mut(b_vid);
let changed = (|| match *b_data {
VarValue::Empty(b_universe) => {
// Empty regions are ordered according to the universe
// they are associated with.
let ui = a_universe.min(b_universe);
debug!(
"Expanding value of {:?} \
from empty lifetime with universe {:?} \
to empty lifetime with universe {:?}",
b_vid, b_universe, ui
);
*b_data = VarValue::Empty(ui);
true
}
VarValue::Value(cur_region) => {
let lub = match self.lub_empty(cur_region) {
Ok(r) => r,
// If the empty and placeholder regions are in the same universe,
// then the LUB is the Placeholder region (which is the cur_region).
// If they are not in the same universe, the LUB is the Static lifetime.
Err(placeholder) if a_universe == placeholder.universe => {
cur_region
}
Err(_) => self.tcx().lifetimes.re_static,
};
if lub == cur_region {
return false;
}
debug!(
"Expanding value of {:?} from {:?} to {:?}",
b_vid, cur_region, lub
);
*b_data = VarValue::Value(lub);
true
}
VarValue::ErrorValue => false,
})();
if changed {
changes.push(b_vid);
}
match b_data {
VarValue::Value(Region(Interned(ReStatic, _)))
| VarValue::ErrorValue => (),
_ => {
constraints[a_vid].push((a_vid, b_vid));
constraints[b_vid].push((a_vid, b_vid));
}
}
}
VarValue::Value(a_region) => {
let b_data = var_values.value_mut(b_vid);
(Some(a_vid), a_region, b_vid, b_data)
if self.expand_node(a_region, b_vid, b_data) {
changes.push(b_vid);
}
match b_data {
VarValue::Value(Region(Interned(ReStatic, _)))
| VarValue::ErrorValue => (),
_ => {
constraints[a_vid].push((a_vid, b_vid));
constraints[b_vid].push((a_vid, b_vid));
}
}
}
},
Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
@ -210,18 +328,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// is done, in `collect_errors`.
continue;
}
};
if self.expand_node(a_region, b_vid, b_data) {
changes.push(b_vid);
}
if let Some(a_vid) = a_vid {
match b_data {
VarValue::Value(Region(Interned(ReStatic, _))) | VarValue::ErrorValue => (),
_ => {
constraints[a_vid].push((a_vid, b_vid));
constraints[b_vid].push((a_vid, b_vid));
}
}
}
}
@ -242,6 +348,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
}
}
/// Expands the value of the region represented with `b_vid` with current
/// value `b_data` to the lub of `b_data` and `a_region`. The corresponds
/// with the constraint `'?b: 'a` (`'a <: '?b`), where `'a` is some known
/// region and `'?b` is some region variable.
fn expand_node(
&self,
a_region: Region<'tcx>,
@ -263,14 +373,28 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
}
match *b_data {
VarValue::Empty(empty_ui) => {
let lub = match self.lub_empty(a_region) {
Ok(r) => r,
// If this empty region is from a universe that can
// name the placeholder, then the placeholder is
// larger; otherwise, the only ancestor is `'static`.
Err(placeholder) if empty_ui.can_name(placeholder.universe) => {
self.tcx().mk_region(RePlaceholder(placeholder))
}
Err(_) => self.tcx().lifetimes.re_static,
};
debug!("Expanding value of {:?} from empty lifetime to {:?}", b_vid, lub);
*b_data = VarValue::Value(lub);
true
}
VarValue::Value(cur_region) => {
// This is a specialized version of the `lub_concrete_regions`
// check below for a common case, here purely as an
// optimization.
let b_universe = self.var_infos[b_vid].universe;
if let ReEmpty(a_universe) = *a_region && a_universe == b_universe {
return false;
}
let mut lub = self.lub_concrete_regions(a_region, cur_region);
if lub == cur_region {
@ -300,6 +424,78 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
}
}
/// True if `a <= b`.
fn sub_region_values(&self, a: VarValue<'tcx>, b: VarValue<'tcx>) -> bool {
match (a, b) {
// Error region is `'static`
(VarValue::ErrorValue, _) | (_, VarValue::ErrorValue) => return true,
(VarValue::Empty(a_ui), VarValue::Empty(b_ui)) => {
// Empty regions are ordered according to the universe
// they are associated with.
a_ui.min(b_ui) == b_ui
}
(VarValue::Value(a), VarValue::Empty(_)) => {
match *a {
ReLateBound(..) | ReErased => {
bug!("cannot relate region: {:?}", a);
}
ReVar(v_id) => {
span_bug!(
self.var_infos[v_id].origin.span(),
"lub_concrete_regions invoked with non-concrete region: {:?}",
a
);
}
ReStatic | ReEarlyBound(_) | ReFree(_) => {
// nothing lives longer than `'static`
// All empty regions are less than early-bound, free,
// and scope regions.
false
}
RePlaceholder(_) => {
// The LUB is either `a` or `'static`
false
}
}
}
(VarValue::Empty(a_ui), VarValue::Value(b)) => {
match *b {
ReLateBound(..) | ReErased => {
bug!("cannot relate region: {:?}", b);
}
ReVar(v_id) => {
span_bug!(
self.var_infos[v_id].origin.span(),
"lub_concrete_regions invoked with non-concrete regions: {:?}",
b
);
}
ReStatic | ReEarlyBound(_) | ReFree(_) => {
// nothing lives longer than `'static`
// All empty regions are less than early-bound, free,
// and scope regions.
true
}
RePlaceholder(placeholder) => {
// If this empty region is from a universe that can
// name the placeholder, then the placeholder is
// larger; otherwise, the only ancestor is `'static`.
if a_ui.can_name(placeholder.universe) { true } else { false }
}
}
}
(VarValue::Value(a), VarValue::Value(b)) => self.sub_concrete_regions(a, b),
}
}
/// True if `a <= b`, but not defined over inference variables.
#[instrument(level = "trace", skip(self))]
fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool {
@ -355,37 +551,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
self.tcx().lifetimes.re_static
}
(ReEmpty(_), ReEarlyBound(_) | ReFree(_)) => {
// All empty regions are less than early-bound, free,
// and scope regions.
b
}
(ReEarlyBound(_) | ReFree(_), ReEmpty(_)) => {
// All empty regions are less than early-bound, free,
// and scope regions.
a
}
(ReEmpty(a_ui), ReEmpty(b_ui)) => {
// Empty regions are ordered according to the universe
// they are associated with.
let ui = a_ui.min(b_ui);
self.tcx().mk_region(ReEmpty(ui))
}
(ReEmpty(empty_ui), RePlaceholder(placeholder))
| (RePlaceholder(placeholder), ReEmpty(empty_ui)) => {
// If this empty region is from a universe that can
// name the placeholder, then the placeholder is
// larger; otherwise, the only ancestor is `'static`.
if empty_ui.can_name(placeholder.universe) {
self.tcx().mk_region(RePlaceholder(placeholder))
} else {
self.tcx().lifetimes.re_static
}
}
(ReEarlyBound(_) | ReFree(_), ReEarlyBound(_) | ReFree(_)) => {
self.region_rels.lub_free_regions(a, b)
}
@ -508,7 +673,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
for (node_vid, value) in var_data.values.iter_enumerated() {
match *value {
VarValue::Value(_) => { /* Inference successful */ }
VarValue::Empty(_) | VarValue::Value(_) => { /* Inference successful */ }
VarValue::ErrorValue => {
// Inference impossible: this value contains
// inconsistent constraints.
@ -829,12 +994,25 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
}
VerifyBound::OutlivedBy(r) => {
self.sub_concrete_regions(min, var_values.normalize(self.tcx(), *r))
let a = match *min {
ty::ReVar(rid) => var_values.values[rid],
_ => VarValue::Value(min),
};
let b = match **r {
ty::ReVar(rid) => var_values.values[rid],
_ => VarValue::Value(*r),
};
self.sub_region_values(a, b)
}
VerifyBound::IsEmpty => {
matches!(*min, ty::ReEmpty(_))
}
VerifyBound::IsEmpty => match *min {
ty::ReVar(rid) => match var_values.values[rid] {
VarValue::ErrorValue => false,
VarValue::Empty(_) => true,
VarValue::Value(_) => false,
},
_ => false,
},
VerifyBound::AnyBound(bs) => {
bs.iter().any(|b| self.bound_is_met(b, var_values, generic_ty, min))
@ -876,6 +1054,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> {
) -> ty::Region<'tcx> {
let result = match *r {
ty::ReVar(rid) => match self.values[rid] {
VarValue::Empty(_) => r,
VarValue::Value(r) => r,
VarValue::ErrorValue => tcx.lifetimes.re_static,
},

View file

@ -426,21 +426,21 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
data
}
pub fn data(&self) -> &RegionConstraintData<'tcx> {
pub(super) fn data(&self) -> &RegionConstraintData<'tcx> {
&self.data
}
pub fn start_snapshot(&mut self) -> RegionSnapshot {
pub(super) fn start_snapshot(&mut self) -> RegionSnapshot {
debug!("RegionConstraintCollector: start_snapshot");
RegionSnapshot { any_unifications: self.any_unifications }
}
pub fn rollback_to(&mut self, snapshot: RegionSnapshot) {
pub(super) fn rollback_to(&mut self, snapshot: RegionSnapshot) {
debug!("RegionConstraintCollector: rollback_to({:?})", snapshot);
self.any_unifications = snapshot.any_unifications;
}
pub fn new_region_var(
pub(super) fn new_region_var(
&mut self,
universe: ty::UniverseIndex,
origin: RegionVariableOrigin,
@ -455,12 +455,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
}
/// Returns the universe for the given variable.
pub fn var_universe(&self, vid: RegionVid) -> ty::UniverseIndex {
pub(super) fn var_universe(&self, vid: RegionVid) -> ty::UniverseIndex {
self.var_infos[vid].universe
}
/// Returns the origin for the given variable.
pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
pub(super) fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
self.var_infos[vid].origin
}
@ -492,7 +492,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
self.undo_log.push(AddVerify(index));
}
pub fn add_given(&mut self, sub: Region<'tcx>, sup: ty::RegionVid) {
pub(super) fn add_given(&mut self, sub: Region<'tcx>, sup: ty::RegionVid) {
// cannot add givens once regions are resolved
if self.data.givens.insert((sub, sup)) {
debug!("add_given({:?} <= {:?})", sub, sup);
@ -501,7 +501,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
}
}
pub fn make_eqregion(
pub(super) fn make_eqregion(
&mut self,
origin: SubregionOrigin<'tcx>,
sub: Region<'tcx>,
@ -530,7 +530,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
}
}
pub fn member_constraint(
pub(super) fn member_constraint(
&mut self,
key: ty::OpaqueTypeKey<'tcx>,
definition_span: Span,
@ -554,7 +554,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
}
#[instrument(skip(self, origin), level = "debug")]
pub fn make_subregion(
pub(super) fn make_subregion(
&mut self,
origin: SubregionOrigin<'tcx>,
sub: Region<'tcx>,
@ -585,7 +585,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
}
}
pub fn verify_generic_bound(
pub(super) fn verify_generic_bound(
&mut self,
origin: SubregionOrigin<'tcx>,
kind: GenericKind<'tcx>,
@ -595,7 +595,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
self.add_verify(Verify { kind, origin, region: sub, bound });
}
pub fn lub_regions(
pub(super) fn lub_regions(
&mut self,
tcx: TyCtxt<'tcx>,
origin: SubregionOrigin<'tcx>,
@ -613,7 +613,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
}
}
pub fn glb_regions(
pub(super) fn glb_regions(
&mut self,
tcx: TyCtxt<'tcx>,
origin: SubregionOrigin<'tcx>,
@ -634,7 +634,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
}
/// Resolves the passed RegionVid to the root RegionVid in the unification table
pub fn opportunistic_resolve_var(&mut self, rid: ty::RegionVid) -> ty::RegionVid {
pub(super) fn opportunistic_resolve_var(&mut self, rid: ty::RegionVid) -> ty::RegionVid {
self.unification_table().find(rid).vid
}
@ -699,7 +699,6 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
ty::ReStatic | ty::ReErased | ty::ReFree(..) | ty::ReEarlyBound(..) => {
ty::UniverseIndex::ROOT
}
ty::ReEmpty(ui) => ui,
ty::RePlaceholder(placeholder) => placeholder.universe,
ty::ReVar(vid) => self.var_universe(vid),
ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region),