Skip to content

Commit 7e9b2ab

Browse files
committed
account for universes in region unification
1 parent eea5604 commit 7e9b2ab

File tree

2 files changed

+53
-23
lines changed

2 files changed

+53
-23
lines changed

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

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_data_structures::sync::Lrc;
1313
use rustc_data_structures::undo_log::UndoLogs;
1414
use rustc_data_structures::unify as ut;
1515
use rustc_index::vec::IndexVec;
16-
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
16+
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion, UniverseError};
1717
use rustc_middle::ty::ReStatic;
1818
use rustc_middle::ty::{self, Ty, TyCtxt};
1919
use rustc_middle::ty::{ReLateBound, ReVar};
@@ -375,6 +375,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
375375
/// Not legal during a snapshot.
376376
pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) {
377377
assert!(!UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
378+
// TODO update universes of var_infos
378379
(mem::take(&mut self.storage.var_infos), mem::take(&mut self.storage.data))
379380
}
380381

@@ -397,11 +398,11 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
397398
// should think carefully about whether it needs to be cleared
398399
// or updated in some way.
399400
let RegionConstraintStorage {
400-
var_infos: _,
401+
var_infos,
401402
data,
402403
lubs,
403404
glbs,
404-
unification_table: _,
405+
unification_table,
405406
any_unifications,
406407
} = self.storage;
407408

@@ -420,7 +421,11 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
420421
// `RegionConstraintData` contains the relationship here.
421422
if *any_unifications {
422423
*any_unifications = false;
423-
self.unification_table_mut().reset_unifications(|_| UnifiedRegion(None));
424+
let mut ut = ut::UnificationTable::with_log(unification_table, &mut self.undo_log);
425+
ut.reset_unifications(|key| UnifiedRegion {
426+
universe: var_infos[key.vid].universe,
427+
value: None,
428+
});
424429
}
425430

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

450-
let u_vid = self.unification_table_mut().new_key(UnifiedRegion(None));
455+
let u_vid = self.unification_table_mut().new_key(UnifiedRegion { universe, value: None });
451456
assert_eq!(vid, u_vid.vid);
452457
self.undo_log.push(AddVar(vid));
453458
debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin);
@@ -456,7 +461,13 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
456461

457462
/// Returns the universe for the given variable.
458463
pub(super) fn var_universe(&self, vid: RegionVid) -> ty::UniverseIndex {
459-
self.var_infos[vid].universe
464+
// WARN UB ahead!
465+
unsafe {
466+
(&mut *(self as *const Self as *mut Self))
467+
.unification_table_mut()
468+
.probe_value(vid)
469+
.universe
470+
}
460471
}
461472

462473
/// Returns the origin for the given variable.
@@ -516,13 +527,20 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
516527
match (sub, sup) {
517528
(Region(Interned(ReVar(sub), _)), Region(Interned(ReVar(sup), _))) => {
518529
debug!("make_eqregion: unifying {:?} with {:?}", sub, sup);
519-
self.unification_table_mut().union(*sub, *sup);
530+
self.unification_table_mut()
531+
.unify_var_var(*sub, *sup)
532+
.unwrap_or_else(|UniverseError| {});
520533
self.any_unifications = true;
521534
}
522535
(Region(Interned(ReVar(vid), _)), value)
523536
| (value, Region(Interned(ReVar(vid), _))) => {
524537
debug!("make_eqregion: unifying {:?} with {:?}", vid, value);
525-
self.unification_table_mut().union_value(*vid, UnifiedRegion(Some(value)));
538+
self.unification_table_mut()
539+
.unify_var_value(
540+
*vid,
541+
UnifiedRegion { universe: ty::UniverseIndex::MAX, value: Some(value) },
542+
)
543+
.unwrap_or_else(|UniverseError| {});
526544
self.any_unifications = true;
527545
}
528546
(_, _) => {}
@@ -642,7 +660,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
642660
) -> ty::Region<'tcx> {
643661
let mut ut = self.unification_table_mut(); // FIXME(rust-lang/ena#42): unnecessary mut
644662
let root_vid = ut.find(vid).vid;
645-
ut.probe_value(root_vid).0.unwrap_or_else(|| tcx.mk_re_var(root_vid))
663+
ut.probe_value(root_vid).value.unwrap_or_else(|| tcx.mk_re_var(root_vid))
646664
}
647665

648666
fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> {

compiler/rustc_middle/src/infer/unify_key.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ pub trait ToType {
1111
}
1212

1313
#[derive(PartialEq, Copy, Clone, Debug)]
14-
pub struct UnifiedRegion<'tcx>(pub Option<ty::Region<'tcx>>);
14+
pub struct UnifiedRegion<'tcx> {
15+
pub universe: ty::UniverseIndex,
16+
pub value: Option<ty::Region<'tcx>>,
17+
}
1518

1619
#[derive(PartialEq, Copy, Clone, Debug)]
1720
pub struct RegionVidKey<'tcx> {
@@ -40,21 +43,30 @@ impl<'tcx> UnifyKey for RegionVidKey<'tcx> {
4043
}
4144
}
4245

43-
impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
44-
type Error = NoError;
45-
46-
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
47-
Ok(match (value1.0, value2.0) {
48-
// Here we can just pick one value, because the full constraints graph
49-
// will be handled later. Ideally, we might want a `MultipleValues`
50-
// variant or something. For now though, this is fine.
51-
(Some(_), Some(_)) => *value1,
46+
fn universe_of_universal_region(region: ty::Region<'_>) -> ty::UniverseIndex {
47+
match *region {
48+
ty::ReStatic | ty::ReFree(..) | ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT,
49+
ty::RePlaceholder(placeholder) => placeholder.universe,
50+
_ => bug!("universe(): encountered region {:?}", region),
51+
}
52+
}
5253

53-
(Some(_), _) => *value1,
54-
(_, Some(_)) => *value2,
54+
pub struct UniverseError;
5555

56-
(None, None) => *value1,
57-
})
56+
impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
57+
type Error = UniverseError;
58+
59+
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
60+
let universe = value1.universe.min(value2.universe);
61+
if [value1.value, value2.value]
62+
.into_iter()
63+
.flatten()
64+
.any(|val| universe.cannot_name(universe_of_universal_region(val)))
65+
{
66+
Err(UniverseError)
67+
} else {
68+
Ok(Self { value: [value1.value, value2.value].into_iter().flatten().next(), universe })
69+
}
5870
}
5971
}
6072

0 commit comments

Comments
 (0)