Skip to content

Commit 61157b3

Browse files
committed
Store Option<Region> as value for RegionVid
1 parent e8c284f commit 61157b3

File tree

14 files changed

+170
-82
lines changed

14 files changed

+170
-82
lines changed

compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,15 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
304304
}
305305

306306
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
307+
let tcx = self.tcx();
308+
let r = self
309+
.infcx
310+
.unwrap()
311+
.inner
312+
.borrow_mut()
313+
.unwrap_region_constraints()
314+
.opportunistic_resolve_region(tcx, r);
315+
307316
match *r {
308317
ty::ReLateBound(index, ..) => {
309318
if index >= self.binder_index {
@@ -313,22 +322,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
313322
}
314323
}
315324

316-
ty::ReVar(vid) => {
317-
let resolved_vid = self
318-
.infcx
319-
.unwrap()
320-
.inner
321-
.borrow_mut()
322-
.unwrap_region_constraints()
323-
.opportunistic_resolve_var(vid);
324-
debug!(
325-
"canonical: region var found with vid {:?}, \
326-
opportunistically resolved to {:?}",
327-
vid, r
328-
);
329-
let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid));
330-
self.canonicalize_region_mode.canonicalize_free_region(self, r)
331-
}
325+
ty::ReVar(_) => self.canonicalize_region_mode.canonicalize_free_region(self, r),
332326

333327
ty::ReStatic
334328
| ty::ReEarlyBound(..)

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

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1111
use rustc_data_structures::sync::Lrc;
1212
use rustc_data_structures::undo_log::UndoLogs;
1313
use rustc_data_structures::unify as ut;
14-
use rustc_data_structures::unify::UnifyKey;
1514
use rustc_hir::def_id::DefId;
1615
use rustc_index::vec::IndexVec;
16+
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
1717
use rustc_middle::ty::ReStatic;
1818
use rustc_middle::ty::{self, Ty, TyCtxt};
1919
use rustc_middle::ty::{ReLateBound, ReVar};
@@ -47,13 +47,13 @@ pub struct RegionConstraintStorage<'tcx> {
4747

4848
/// When we add a R1 == R2 constriant, we currently add (a) edges
4949
/// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this
50-
/// table. You can then call `opportunistic_resolve_var` early
50+
/// table. You can then call `opportunistic_resolve_region` early
5151
/// which will map R1 and R2 to some common region (i.e., either
5252
/// R1 or R2). This is important when fulfillment, dropck and other such
5353
/// code is iterating to a fixed point, because otherwise we sometimes
5454
/// would wind up with a fresh stream of region variables that have been
5555
/// equated but appear distinct.
56-
pub(super) unification_table: ut::UnificationTableStorage<ty::RegionVid>,
56+
pub(super) unification_table: ut::UnificationTableStorage<RegionVidKey<'tcx>>,
5757

5858
/// a flag set to true when we perform any unifications; this is used
5959
/// to micro-optimize `take_and_reset_data`
@@ -406,8 +406,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
406406
// `RegionConstraintData` contains the relationship here.
407407
if *any_unifications {
408408
*any_unifications = false;
409-
self.unification_table()
410-
.reset_unifications(|_| ());
409+
self.unification_table().reset_unifications(|_| UnifiedRegion(None));
411410
}
412411

413412
data
@@ -434,8 +433,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
434433
) -> RegionVid {
435434
let vid = self.var_infos.push(RegionVariableInfo { origin, universe });
436435

437-
let u_vid = self.unification_table().new_key(());
438-
assert_eq!(vid, u_vid);
436+
let u_vid = self.unification_table().new_key(UnifiedRegion(None));
437+
assert_eq!(vid, u_vid.vid);
439438
self.undo_log.push(AddVar(vid));
440439
debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin);
441440
vid
@@ -497,10 +496,18 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
497496
self.make_subregion(origin.clone(), sub, sup);
498497
self.make_subregion(origin, sup, sub);
499498

500-
if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
501-
debug!("make_eqregion: uniying {:?} with {:?}", sub, sup);
502-
self.unification_table().union(sub, sup);
503-
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+
(_, _) => {}
504511
}
505512
}
506513
}
@@ -616,8 +623,21 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
616623
}
617624
}
618625

619-
pub fn opportunistic_resolve_var(&mut self, rid: RegionVid) -> ty::RegionVid {
620-
self.unification_table().find(rid)
626+
pub fn opportunistic_resolve_region(
627+
&mut self,
628+
tcx: TyCtxt<'tcx>,
629+
region: ty::Region<'tcx>,
630+
) -> ty::Region<'tcx> {
631+
match region {
632+
ty::ReVar(rid) => {
633+
let unified_region = self.unification_table().probe_value(*rid);
634+
unified_region.0.unwrap_or_else(|| {
635+
let root = self.unification_table().find(*rid).vid;
636+
tcx.reuse_or_mk_region(region, ty::ReVar(root))
637+
})
638+
}
639+
_ => region,
640+
}
621641
}
622642

623643
fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> {
@@ -672,8 +692,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
672692
&self,
673693
value_count: usize,
674694
) -> (Range<RegionVid>, Vec<RegionVariableOrigin>) {
675-
let range = RegionVid::from_index(value_count as u32)
676-
..RegionVid::from_index(self.unification_table.len() as u32);
695+
let range = RegionVid::from(value_count as u32)
696+
..RegionVid::from(self.unification_table.len() as u32);
677697
(
678698
range.clone(),
679699
(range.start.index()..range.end.index())
@@ -695,7 +715,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
695715
}
696716

697717
#[inline]
698-
fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, ty::RegionVid> {
718+
fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, RegionVidKey<'tcx>> {
699719
ut::UnificationTable::with_log(&mut self.storage.unification_table, self.undo_log)
700720
}
701721
}

compiler/rustc_infer/src/infer/resolve.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,18 +84,12 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
8484
}
8585

8686
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
87-
match *r {
88-
ty::ReVar(rid) => {
89-
let resolved = self
90-
.infcx
91-
.inner
92-
.borrow_mut()
93-
.unwrap_region_constraints()
94-
.opportunistic_resolve_var(rid);
95-
self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved))
96-
}
97-
_ => r,
98-
}
87+
let tcx = self.tcx();
88+
self.infcx
89+
.inner
90+
.borrow_mut()
91+
.unwrap_region_constraints()
92+
.opportunistic_resolve_region(tcx, r)
9993
}
10094

10195
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {

compiler/rustc_infer/src/infer/undo_log.rs

Lines changed: 3 additions & 2 deletions
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

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,45 @@ 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 = ();
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+
(Some(_), Some(_)) => *value1,
52+
53+
(Some(_), _) => *value1,
54+
(_, Some(_)) => *value2,
55+
56+
(None, None) => *value1,
57+
})
5058
}
5159
}
5260

src/test/ui/associated-types/associated-types-eq-hr.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ pub fn call_tuple_two() {
102102
tuple_two::<Tuple>();
103103
//~^ ERROR implementation of `TheTrait` is not general enough
104104
//~| ERROR implementation of `TheTrait` is not general enough
105+
//~| ERROR mismatched types
106+
//~| ERROR mismatched types
105107
}
106108

107109
pub fn call_tuple_three() {

src/test/ui/associated-types/associated-types-eq-hr.stderr

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,34 @@ LL | tuple_one::<Tuple>();
4646
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
4747
= note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
4848

49+
error[E0308]: mismatched types
50+
--> $DIR/associated-types-eq-hr.rs:102:5
51+
|
52+
LL | tuple_two::<Tuple>();
53+
| ^^^^^^^^^^^^^^^^^^ lifetime mismatch
54+
|
55+
= note: expected reference `&'x isize`
56+
found reference `&'y isize`
57+
note: the lifetime requirement is introduced here
58+
--> $DIR/associated-types-eq-hr.rs:66:53
59+
|
60+
LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>,
61+
| ^^^^^^^^^^^^^
62+
63+
error[E0308]: mismatched types
64+
--> $DIR/associated-types-eq-hr.rs:102:5
65+
|
66+
LL | tuple_two::<Tuple>();
67+
| ^^^^^^^^^^^^^^^^^^ lifetime mismatch
68+
|
69+
= note: expected reference `&'x isize`
70+
found reference `&'y isize`
71+
note: the lifetime requirement is introduced here
72+
--> $DIR/associated-types-eq-hr.rs:66:53
73+
|
74+
LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>,
75+
| ^^^^^^^^^^^^^
76+
4977
error: implementation of `TheTrait` is not general enough
5078
--> $DIR/associated-types-eq-hr.rs:102:5
5179
|
@@ -65,14 +93,15 @@ LL | tuple_two::<Tuple>();
6593
= note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
6694

6795
error: implementation of `TheTrait` is not general enough
68-
--> $DIR/associated-types-eq-hr.rs:112:5
96+
--> $DIR/associated-types-eq-hr.rs:114:5
6997
|
7098
LL | tuple_four::<Tuple>();
7199
| ^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough
72100
|
73101
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
74102
= note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
75103

76-
error: aborting due to 7 previous errors
104+
error: aborting due to 9 previous errors
77105

78-
For more information about this error, try `rustc --explain E0271`.
106+
Some errors have detailed explanations: E0271, E0308.
107+
For more information about an error, try `rustc --explain E0271`.

src/test/ui/hrtb/issue-62203-hrtb-ice.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | let v = Unit2.m(
99
= help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4`
1010
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
1111

12-
error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&u8,),)>>::Output == Unit3`
12+
error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&'r u8,),)>>::Output == Unit3`
1313
--> $DIR/issue-62203-hrtb-ice.rs:38:19
1414
|
1515
LL | let v = Unit2.m(

src/test/ui/rfc1623.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ static SOME_STRUCT: &SomeStruct = &SomeStruct {
2323
bar: &Bar { bools: &[true, true] },
2424
f: &id,
2525
//~^ ERROR implementation of `FnOnce` is not general enough
26+
//~^^ mismatched types
27+
//~^^^ mismatched types
28+
//~^^^^ mismatched types
29+
//~^^^^^ mismatched types
2630
};
2731

2832
// very simple test for a 'static static with default lifetime

0 commit comments

Comments
 (0)