Skip to content

Commit dc57c8b

Browse files
committed
make unification infallible again
1 parent 7e9b2ab commit dc57c8b

File tree

6 files changed

+32
-48
lines changed

6 files changed

+32
-48
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,13 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
9898
}
9999
}
100100

101-
struct LeakCheck<'me, 'tcx> {
101+
struct LeakCheck<'me, 'rcc, 'tcx> {
102102
tcx: TyCtxt<'tcx>,
103103
universe_at_start_of_snapshot: ty::UniverseIndex,
104104
/// Only used when reporting region errors.
105105
overly_polymorphic: bool,
106106
mini_graph: &'me MiniGraph<'tcx>,
107-
rcc: &'me RegionConstraintCollector<'me, 'tcx>,
107+
rcc: &'me mut RegionConstraintCollector<'rcc, 'tcx>,
108108

109109
// Initially, for each SCC S, stores a placeholder `P` such that `S = P`
110110
// must hold.
@@ -127,14 +127,14 @@ struct LeakCheck<'me, 'tcx> {
127127
scc_universes: IndexVec<LeakCheckScc, SccUniverse<'tcx>>,
128128
}
129129

130-
impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
130+
impl<'me, 'rcc, 'tcx> LeakCheck<'me, 'rcc, 'tcx> {
131131
fn new(
132132
tcx: TyCtxt<'tcx>,
133133
universe_at_start_of_snapshot: ty::UniverseIndex,
134134
max_universe: ty::UniverseIndex,
135135
overly_polymorphic: bool,
136136
mini_graph: &'me MiniGraph<'tcx>,
137-
rcc: &'me RegionConstraintCollector<'me, 'tcx>,
137+
rcc: &'me mut RegionConstraintCollector<'rcc, 'tcx>,
138138
) -> Self {
139139
let dummy_scc_universe = SccUniverse { universe: max_universe, region: None };
140140
Self {

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

Lines changed: 8 additions & 19 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, UniverseError};
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};
@@ -460,14 +460,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
460460
}
461461

462462
/// Returns the universe for the given variable.
463-
pub(super) fn var_universe(&self, vid: RegionVid) -> ty::UniverseIndex {
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-
}
463+
pub(super) fn var_universe(&mut self, vid: RegionVid) -> ty::UniverseIndex {
464+
self.unification_table_mut().probe_value(vid).universe
471465
}
472466

473467
/// Returns the origin for the given variable.
@@ -527,20 +521,15 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
527521
match (sub, sup) {
528522
(Region(Interned(ReVar(sub), _)), Region(Interned(ReVar(sup), _))) => {
529523
debug!("make_eqregion: unifying {:?} with {:?}", sub, sup);
530-
self.unification_table_mut()
531-
.unify_var_var(*sub, *sup)
532-
.unwrap_or_else(|UniverseError| {});
524+
self.unification_table_mut().union(*sub, *sup);
533525
self.any_unifications = true;
534526
}
535527
(Region(Interned(ReVar(vid), _)), value)
536528
| (value, Region(Interned(ReVar(vid), _))) => {
537529
debug!("make_eqregion: unifying {:?} with {:?}", vid, 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| {});
530+
let value =
531+
UnifiedRegion { universe: self.universe(value), value: Some(value) };
532+
self.unification_table_mut().union_value(*vid, value);
544533
self.any_unifications = true;
545534
}
546535
(_, _) => {}
@@ -699,7 +688,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
699688
new_r
700689
}
701690

702-
pub fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex {
691+
pub fn universe(&mut self, region: Region<'tcx>) -> ty::UniverseIndex {
703692
match *region {
704693
ty::ReStatic
705694
| ty::ReErased

compiler/rustc_middle/src/infer/unify_key.rs

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,30 +43,11 @@ impl<'tcx> UnifyKey for RegionVidKey<'tcx> {
4343
}
4444
}
4545

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-
}
53-
54-
pub struct UniverseError;
55-
5646
impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
57-
type Error = UniverseError;
47+
type Error = NoError;
5848

5949
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-
}
50+
Ok(cmp::min_by_key(*value1, *value2, |val| (val.universe, val.value.is_none())))
7051
}
7152
}
7253

tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
//
33
// In particular, we test this pattern in trait solving, where it is not connected
44
// to any part of the source code.
5-
//
6-
// check-pass
7-
// Oops!
85

96
use std::cell::Cell;
107

@@ -28,5 +25,5 @@ fn main() {
2825
// yielding `fn(&!b u32)`, in a fresh universe U1
2926
// - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`.
3027

31-
foo::<()>();
28+
foo::<()>(); //~ ERROR implementation of `Trait` is not general enough
3229
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: implementation of `Trait` is not general enough
2+
--> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5
3+
|
4+
LL | foo::<()>();
5+
| ^^^^^^^^^^^ implementation of `Trait` is not general enough
6+
|
7+
= note: `()` must implement `Trait<for<'b> fn(Cell<&'b u32>)>`
8+
= note: ...but it actually implements `Trait<fn(Cell<&'0 u32>)>`, for some specific lifetime `'0`
9+
10+
error: aborting due to previous error
11+

tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ LL | fn give_some<'a>() {
1414
| -- lifetime `'a` defined here
1515
LL | want_hrtb::<&'a u32>()
1616
| ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
17+
|
18+
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
19+
--> $DIR/hrtb-just-for-static.rs:9:15
20+
|
21+
LL | where T : for<'a> Foo<&'a isize>
22+
| ^^^^^^^^^^^^^^^^^^^^^^
1723

1824
error: implementation of `Foo` is not general enough
1925
--> $DIR/hrtb-just-for-static.rs:30:5

0 commit comments

Comments
 (0)