Skip to content

Commit 70b9d1e

Browse files
committed
Auto merge of rust-lang#85313 - jackh726:region_eq, r=nikomatsakis
Unify Regions with RegionVids in UnificationTable A few test output changes; might be able to revert those but figured I would open this for perf and comments. r? `@nikomatsakis`
2 parents 25a277f + c6e4284 commit 70b9d1e

File tree

5 files changed

+83
-41
lines changed

5 files changed

+83
-41
lines changed

compiler/rustc_infer/src/infer/region_constraints/mod.rs

+42-16
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
use self::CombineMapType::*;
44
use self::UndoLog::*;
55

6-
use super::unify_key;
76
use super::{
87
InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin,
98
};
@@ -12,9 +11,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1211
use rustc_data_structures::sync::Lrc;
1312
use rustc_data_structures::undo_log::UndoLogs;
1413
use rustc_data_structures::unify as ut;
15-
use rustc_data_structures::unify::UnifyKey;
1614
use rustc_hir::def_id::DefId;
1715
use rustc_index::vec::IndexVec;
16+
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
1817
use rustc_middle::ty::ReStatic;
1918
use rustc_middle::ty::{self, Ty, TyCtxt};
2019
use rustc_middle::ty::{ReLateBound, ReVar};
@@ -54,7 +53,7 @@ pub struct RegionConstraintStorage<'tcx> {
5453
/// code is iterating to a fixed point, because otherwise we sometimes
5554
/// would wind up with a fresh stream of region variables that have been
5655
/// equated but appear distinct.
57-
pub(super) unification_table: ut::UnificationTableStorage<ty::RegionVid>,
56+
pub(super) unification_table: ut::UnificationTableStorage<RegionVidKey<'tcx>>,
5857

5958
/// a flag set to true when we perform any unifications; this is used
6059
/// to micro-optimize `take_and_reset_data`
@@ -407,8 +406,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
407406
// `RegionConstraintData` contains the relationship here.
408407
if *any_unifications {
409408
*any_unifications = false;
410-
self.unification_table()
411-
.reset_unifications(|vid| unify_key::RegionVidKey { min_vid: vid });
409+
self.unification_table().reset_unifications(|_| UnifiedRegion(None));
412410
}
413411

414412
data
@@ -435,8 +433,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
435433
) -> RegionVid {
436434
let vid = self.var_infos.push(RegionVariableInfo { origin, universe });
437435

438-
let u_vid = self.unification_table().new_key(unify_key::RegionVidKey { min_vid: vid });
439-
assert_eq!(vid, u_vid);
436+
let u_vid = self.unification_table().new_key(UnifiedRegion(None));
437+
assert_eq!(vid, u_vid.vid);
440438
self.undo_log.push(AddVar(vid));
441439
debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin);
442440
vid
@@ -498,10 +496,18 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
498496
self.make_subregion(origin.clone(), sub, sup);
499497
self.make_subregion(origin, sup, sub);
500498

501-
if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
502-
debug!("make_eqregion: uniying {:?} with {:?}", sub, sup);
503-
self.unification_table().union(sub, sup);
504-
self.any_unifications = true;
499+
match (sub, sup) {
500+
(&ty::ReVar(sub), &ty::ReVar(sup)) => {
501+
debug!("make_eqregion: unifying {:?} with {:?}", sub, sup);
502+
self.unification_table().union(sub, sup);
503+
self.any_unifications = true;
504+
}
505+
(&ty::ReVar(vid), value) | (value, &ty::ReVar(vid)) => {
506+
debug!("make_eqregion: unifying {:?} with {:?}", vid, value);
507+
self.unification_table().union_value(vid, UnifiedRegion(Some(value)));
508+
self.any_unifications = true;
509+
}
510+
(_, _) => {}
505511
}
506512
}
507513
}
@@ -617,8 +623,29 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
617623
}
618624
}
619625

620-
pub fn opportunistic_resolve_var(&mut self, rid: RegionVid) -> ty::RegionVid {
621-
self.unification_table().probe_value(rid).min_vid
626+
/// Resolves the passed RegionVid to the root RegionVid in the unification table
627+
pub fn opportunistic_resolve_var(&mut self, rid: ty::RegionVid) -> ty::RegionVid {
628+
self.unification_table().find(rid).vid
629+
}
630+
631+
/// If the Region is a `ReVar`, then resolves it either to the root value in
632+
/// the unification table, if it exists, or to the root `ReVar` in the table.
633+
/// If the Region is not a `ReVar`, just returns the Region itself.
634+
pub fn opportunistic_resolve_region(
635+
&mut self,
636+
tcx: TyCtxt<'tcx>,
637+
region: ty::Region<'tcx>,
638+
) -> ty::Region<'tcx> {
639+
match region {
640+
ty::ReVar(rid) => {
641+
let unified_region = self.unification_table().probe_value(*rid);
642+
unified_region.0.unwrap_or_else(|| {
643+
let root = self.unification_table().find(*rid).vid;
644+
tcx.reuse_or_mk_region(region, ty::ReVar(root))
645+
})
646+
}
647+
_ => region,
648+
}
622649
}
623650

624651
fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> {
@@ -673,8 +700,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
673700
&self,
674701
value_count: usize,
675702
) -> (Range<RegionVid>, Vec<RegionVariableOrigin>) {
676-
let range = RegionVid::from_index(value_count as u32)
677-
..RegionVid::from_index(self.unification_table.len() as u32);
703+
let range = RegionVid::from(value_count)..RegionVid::from(self.unification_table.len());
678704
(
679705
range.clone(),
680706
(range.start.index()..range.end.index())
@@ -696,7 +722,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
696722
}
697723

698724
#[inline]
699-
fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, ty::RegionVid> {
725+
fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, RegionVidKey<'tcx>> {
700726
ut::UnificationTable::with_log(&mut self.storage.unification_table, self.undo_log)
701727
}
702728
}

compiler/rustc_infer/src/infer/undo_log.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::marker::PhantomData;
33
use rustc_data_structures::snapshot_vec as sv;
44
use rustc_data_structures::undo_log::{Rollback, UndoLogs};
55
use rustc_data_structures::unify as ut;
6+
use rustc_middle::infer::unify_key::RegionVidKey;
67
use rustc_middle::ty;
78

89
use crate::{
@@ -22,7 +23,7 @@ pub(crate) enum UndoLog<'tcx> {
2223
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
2324
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
2425
RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
25-
RegionUnificationTable(sv::UndoLog<ut::Delegate<ty::RegionVid>>),
26+
RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
2627
ProjectionCache(traits::UndoLog<'tcx>),
2728
PushRegionObligation,
2829
}
@@ -55,7 +56,7 @@ impl_from! {
5556

5657
ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>),
5758

58-
RegionUnificationTable(sv::UndoLog<ut::Delegate<ty::RegionVid>>),
59+
RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
5960
ProjectionCache(traits::UndoLog<'tcx>),
6061
}
6162

compiler/rustc_middle/src/infer/unify_key.rs

+33-22
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,48 @@ pub trait ToType {
1616
}
1717

1818
#[derive(PartialEq, Copy, Clone, Debug)]
19-
pub struct RegionVidKey {
20-
/// The minimum region vid in the unification set. This is needed
21-
/// to have a canonical name for a type to prevent infinite
22-
/// recursion.
23-
pub min_vid: ty::RegionVid,
24-
}
25-
26-
impl UnifyValue for RegionVidKey {
27-
type Error = NoError;
19+
pub struct UnifiedRegion<'tcx>(pub Option<ty::Region<'tcx>>);
2820

29-
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
30-
let min_vid = if value1.min_vid.index() < value2.min_vid.index() {
31-
value1.min_vid
32-
} else {
33-
value2.min_vid
34-
};
21+
#[derive(PartialEq, Copy, Clone, Debug)]
22+
pub struct RegionVidKey<'tcx> {
23+
pub vid: ty::RegionVid,
24+
pub phantom: PhantomData<UnifiedRegion<'tcx>>,
25+
}
3526

36-
Ok(RegionVidKey { min_vid })
27+
impl<'tcx> From<ty::RegionVid> for RegionVidKey<'tcx> {
28+
fn from(vid: ty::RegionVid) -> Self {
29+
RegionVidKey { vid, phantom: PhantomData }
3730
}
3831
}
3932

40-
impl UnifyKey for ty::RegionVid {
41-
type Value = RegionVidKey;
33+
impl<'tcx> UnifyKey for RegionVidKey<'tcx> {
34+
type Value = UnifiedRegion<'tcx>;
4235
fn index(&self) -> u32 {
43-
u32::from(*self)
36+
self.vid.as_u32()
4437
}
45-
fn from_index(i: u32) -> ty::RegionVid {
46-
ty::RegionVid::from(i)
38+
fn from_index(i: u32) -> Self {
39+
RegionVidKey::from(ty::RegionVid::from_u32(i))
4740
}
4841
fn tag() -> &'static str {
49-
"RegionVid"
42+
"RegionVidKey"
43+
}
44+
}
45+
46+
impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
47+
type Error = NoError;
48+
49+
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
50+
Ok(match (value1.0, value2.0) {
51+
// Here we can just pick one value, because the full constraints graph
52+
// will be handled later. Ideally, we might want a `MultipleValues`
53+
// variant or something. For now though, this is fine.
54+
(Some(_), Some(_)) => *value1,
55+
56+
(Some(_), _) => *value1,
57+
(_, Some(_)) => *value2,
58+
59+
(None, None) => *value1,
60+
})
5061
}
5162
}
5263

src/test/ui/traits/inductive-overflow/lifetime.rs

+2
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@ fn main() {
2626
// Should only be a few notes.
2727
is_send::<X<C<'static>>>();
2828
//~^ ERROR overflow evaluating
29+
//~| 2 redundant requirements hidden
30+
//~| required because of
2931
}

src/test/ui/traits/inductive-overflow/lifetime.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ LL | fn is_send<S: NotAuto>() {}
77
LL | is_send::<X<C<'static>>>();
88
| ^^^^^^^^^^^^^^^^^^^^^^^^
99
|
10-
note: required because of the requirements on the impl of `NotAuto` for `X<C<'static>>`
10+
note: required because of the requirements on the impl of `NotAuto` for `X<C<'_>>`
1111
--> $DIR/lifetime.rs:19:12
1212
|
1313
LL | impl<T: Y> NotAuto for X<T> where T::P: NotAuto {}
1414
| ^^^^^^^ ^^^^
15+
= note: 2 redundant requirements hidden
16+
= note: required because of the requirements on the impl of `NotAuto` for `X<C<'static>>`
1517

1618
error: aborting due to previous error
1719

0 commit comments

Comments
 (0)