Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

always resolve to universal regions if possible #108121

Merged
merged 7 commits into from
Mar 8, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,19 +352,17 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
}

ty::ReVar(vid) => {
let resolved_vid = self
let resolved = self
.infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_var(vid);
.opportunistic_resolve_var(self.tcx, vid);
debug!(
"canonical: region var found with vid {:?}, \
opportunistically resolved to {:?}",
vid, resolved_vid
"canonical: region var found with vid {vid:?}, \
opportunistically resolved to {resolved:?}",
);
let r = self.tcx.mk_re_var(resolved_vid);
self.canonicalize_mode.canonicalize_free_region(self, r)
self.canonicalize_mode.canonicalize_free_region(self, resolved)
}

ty::ReStatic
Expand Down
42 changes: 18 additions & 24 deletions compiler/rustc_infer/src/infer/region_constraints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
// `RegionConstraintData` contains the relationship here.
if *any_unifications {
*any_unifications = false;
self.unification_table().reset_unifications(|_| UnifiedRegion(None));
self.unification_table_mut().reset_unifications(|_| UnifiedRegion(None));
}

data
Expand All @@ -447,7 +447,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
) -> RegionVid {
let vid = self.var_infos.push(RegionVariableInfo { origin, universe });

let u_vid = self.unification_table().new_key(UnifiedRegion(None));
let u_vid = self.unification_table_mut().new_key(UnifiedRegion(None));
assert_eq!(vid, u_vid.vid);
self.undo_log.push(AddVar(vid));
debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin);
Expand Down Expand Up @@ -516,13 +516,13 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
match (sub, sup) {
(Region(Interned(ReVar(sub), _)), Region(Interned(ReVar(sup), _))) => {
debug!("make_eqregion: unifying {:?} with {:?}", sub, sup);
self.unification_table().union(*sub, *sup);
self.unification_table_mut().union(*sub, *sup);
self.any_unifications = true;
}
(Region(Interned(ReVar(vid), _)), value)
| (value, Region(Interned(ReVar(vid), _))) => {
debug!("make_eqregion: unifying {:?} with {:?}", vid, value);
self.unification_table().union_value(*vid, UnifiedRegion(Some(value)));
self.unification_table_mut().union_value(*vid, UnifiedRegion(Some(value)));
self.any_unifications = true;
}
(_, _) => {}
Expand Down Expand Up @@ -633,28 +633,22 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
}
}

/// Resolves the passed RegionVid to the root RegionVid in the unification table
pub(super) fn opportunistic_resolve_var(&mut self, rid: ty::RegionVid) -> ty::RegionVid {
self.unification_table().find(rid).vid
}

/// If the Region is a `ReVar`, then resolves it either to the root value in
/// the unification table, if it exists, or to the root `ReVar` in the table.
/// If the Region is not a `ReVar`, just returns the Region itself.
pub fn opportunistic_resolve_region(
/// Resolves a region var to its value in the unification table, if it exists.
/// Otherwise, it is resolved to the root `ReVar` in the table.
pub fn opportunistic_resolve_var(
&mut self,
tcx: TyCtxt<'tcx>,
region: ty::Region<'tcx>,
vid: ty::RegionVid,
) -> ty::Region<'tcx> {
match *region {
ty::ReVar(rid) => {
let unified_region = self.unification_table().probe_value(rid);
unified_region.0.unwrap_or_else(|| {
let root = self.unification_table().find(rid).vid;
tcx.mk_re_var(root)
})
}
_ => region,
let mut ut = self.unification_table_mut(); // FIXME(rust-lang/ena#42): unnecessary mut
let root_vid = ut.find(vid).vid;
let resolved = ut.probe_value(root_vid).0.unwrap_or_else(|| tcx.mk_re_var(root_vid));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the only use of probe_value for regions 🤔 so yeah I agree that this is fine.

Can you add a comment to UnifiedRegion that the assigned value may not be nameable by the region var?

Or even better, change unified region to

pub(super?) struct UnifiedRegion {
    resolved: Option<Region<'tcx>>,
}

impl UnifiedRegion {
    /// Something something the resolved region may not be nameable by
    /// this region variable.
    pub fn get_resolved_region_ignoring_universes(self) -> Option<Region<'tcx>> {
        self.resolved
    }
}


// Don't resolve a variable to a region that it cannot name.
if self.var_universe(vid).can_name(self.universe(resolved)) {
resolved
} else {
tcx.mk_re_var(vid)
}
}

Expand Down Expand Up @@ -733,7 +727,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
}

#[inline]
fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, RegionVidKey<'tcx>> {
fn unification_table_mut(&mut self) -> super::UnificationTable<'_, 'tcx, RegionVidKey<'tcx>> {
ut::UnificationTable::with_log(&mut self.storage.unification_table, self.undo_log)
}
}
Expand Down
15 changes: 6 additions & 9 deletions compiler/rustc_infer/src/infer/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,12 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticRegionResolver<'a, 'tcx

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
ty::ReVar(rid) => {
let resolved = self
.infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_var(rid);
TypeFolder::interner(self).mk_re_var(resolved)
}
ty::ReVar(vid) => self
.infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_var(TypeFolder::interner(self), vid),
_ => r,
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -871,12 +871,12 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {

fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> {
let r1 = match *r0 {
ty::ReVar(_) => self
ty::ReVar(vid) => self
.infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_region(self.infcx.tcx, r0),
.opportunistic_resolve_var(self.infcx.tcx, vid),
_ => r0,
};

Expand Down
4 changes: 2 additions & 2 deletions tests/rustdoc/normalize-assoc-item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ impl<'a> Lifetimes<'a> for usize {
type Y = &'a isize;
}

// @has 'normalize_assoc_item/fn.g.html' '//pre[@class="rust item-decl"]' "pub fn g() -> &isize"
// @has 'normalize_assoc_item/fn.g.html' '//pre[@class="rust item-decl"]' "pub fn g() -> &'static isize"
pub fn g() -> <usize as Lifetimes<'static>>::Y {
&0
}

// @has 'normalize_assoc_item/constant.A.html' '//pre[@class="rust item-decl"]' "pub const A: &isize"
// @has 'normalize_assoc_item/constant.A.html' '//pre[@class="rust item-decl"]' "pub const A: &'static isize"
pub const A: <usize as Lifetimes<'static>>::Y = &0;

// test cross-crate re-exports
Expand Down
6 changes: 2 additions & 4 deletions tests/ui/traits/inductive-overflow/lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ impl<'a> Y for C<'a> {
struct C<'a>(&'a ());
struct X<T: Y>(T::P);

impl<T: NotAuto> NotAuto for Box<T> {} //~ NOTE: required
impl<T: NotAuto> NotAuto for Box<T> {}
impl<T: Y> NotAuto for X<T> where T::P: NotAuto {} //~ NOTE: required
//~^ NOTE unsatisfied trait bound introduced here
impl<T: Y> NotAuto for X<T> where T::P: NotAuto {}
impl<'a> NotAuto for C<'a> {}

fn is_send<S: NotAuto>() {}
Expand All @@ -28,6 +28,4 @@ fn main() {
// Should only be a few notes.
is_send::<X<C<'static>>>();
//~^ ERROR overflow evaluating
//~| 3 redundant requirements hidden
//~| required for
}
14 changes: 5 additions & 9 deletions tests/ui/traits/inductive-overflow/lifetime.stderr
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
error[E0275]: overflow evaluating the requirement `X<C<'_>>: NotAuto`
error[E0275]: overflow evaluating the requirement `Box<X<C<'static>>>: NotAuto`
--> $DIR/lifetime.rs:29:5
|
LL | is_send::<X<C<'static>>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: required for `Box<X<C<'_>>>` to implement `NotAuto`
--> $DIR/lifetime.rs:18:18
note: required for `X<C<'static>>` to implement `NotAuto`
--> $DIR/lifetime.rs:19:12
|
LL | impl<T: NotAuto> NotAuto for Box<T> {}
| ------- ^^^^^^^ ^^^^^^
| |
| unsatisfied trait bound introduced here
= note: 3 redundant requirements hidden
= note: required for `X<C<'static>>` to implement `NotAuto`
LL | impl<T: Y> NotAuto for X<T> where T::P: NotAuto {}
| ^^^^^^^ ^^^^ ------- unsatisfied trait bound introduced here
note: required by a bound in `is_send`
--> $DIR/lifetime.rs:23:15
|
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/wf/hir-wf-check-erase-regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
pub struct Table<T, const N: usize>([Option<T>; N]);

impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>; //~ ERROR `&T` is not an iterator
type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>; //~ ERROR `&'a T` is not an iterator
type Item = &'a T;

fn into_iter(self) -> Self::IntoIter { //~ ERROR `&T` is not an iterator
fn into_iter(self) -> Self::IntoIter { //~ ERROR `&'a T` is not an iterator
unimplemented!()
}
}
Expand Down
16 changes: 8 additions & 8 deletions tests/ui/wf/hir-wf-check-erase-regions.stderr
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
error[E0277]: `&T` is not an iterator
error[E0277]: `&'a T` is not an iterator
--> $DIR/hir-wf-check-erase-regions.rs:7:21
|
LL | type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'a T` is not an iterator
|
= help: the trait `Iterator` is not implemented for `&T`
= help: the trait `Iterator` is not implemented for `&'a T`
= help: the trait `Iterator` is implemented for `&mut I`
= note: required for `&T` to implement `IntoIterator`
= note: required for `&'a T` to implement `IntoIterator`
note: required by a bound in `Flatten`
--> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL

error[E0277]: `&T` is not an iterator
error[E0277]: `&'a T` is not an iterator
--> $DIR/hir-wf-check-erase-regions.rs:10:27
|
LL | fn into_iter(self) -> Self::IntoIter {
| ^^^^^^^^^^^^^^ `&T` is not an iterator
| ^^^^^^^^^^^^^^ `&'a T` is not an iterator
|
= help: the trait `Iterator` is not implemented for `&T`
= help: the trait `Iterator` is not implemented for `&'a T`
= help: the trait `Iterator` is implemented for `&mut I`
= note: required for `&T` to implement `IntoIterator`
= note: required for `&'a T` to implement `IntoIterator`
note: required by a bound in `Flatten`
--> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL

Expand Down