Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 57a593f

Browse files
nikomatsakissgrif
authored andcommittedMar 1, 2018
store type values in the unification table directly
1 parent c7953bb commit 57a593f

File tree

5 files changed

+176
-98
lines changed

5 files changed

+176
-98
lines changed
 

‎src/librustc/infer/combine.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
402402
// `vid` are related via subtyping.
403403
return Err(TypeError::CyclicTy(self.root_ty));
404404
} else {
405-
match variables.probe_root(vid) {
405+
match variables.probe(vid) {
406406
Some(u) => {
407407
drop(variables);
408408
self.relate(&u, &u)
@@ -423,7 +423,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
423423
ty::Covariant | ty::Contravariant => (),
424424
}
425425

426-
let origin = variables.origin(vid);
426+
let origin = *variables.var_origin(vid);
427427
let new_var_id = variables.new_var(false, origin);
428428
let u = self.tcx().mk_var(new_var_id);
429429
debug!("generalize: replacing original vid={:?} with new={:?}",

‎src/librustc/infer/higher_ranked/mod.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
244244

245245
fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
246246
span: Span,
247-
snapshot: &CombinedSnapshot,
247+
snapshot: &CombinedSnapshot<'a, 'tcx>,
248248
debruijn: ty::DebruijnIndex,
249249
new_vars: &[ty::RegionVid],
250250
a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
@@ -340,7 +340,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
340340

341341
fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
342342
span: Span,
343-
snapshot: &CombinedSnapshot,
343+
snapshot: &CombinedSnapshot<'a, 'tcx>,
344344
debruijn: ty::DebruijnIndex,
345345
new_vars: &[ty::RegionVid],
346346
a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
@@ -479,7 +479,7 @@ fn fold_regions_in<'a, 'gcx, 'tcx, T, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
479479

480480
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
481481
fn tainted_regions(&self,
482-
snapshot: &CombinedSnapshot,
482+
snapshot: &CombinedSnapshot<'a, 'tcx>,
483483
r: ty::Region<'tcx>,
484484
directions: TaintDirections)
485485
-> FxHashSet<ty::Region<'tcx>> {
@@ -491,7 +491,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
491491
}
492492

493493
fn region_vars_confined_to_snapshot(&self,
494-
snapshot: &CombinedSnapshot)
494+
snapshot: &CombinedSnapshot<'a, 'tcx>)
495495
-> Vec<ty::RegionVid>
496496
{
497497
/*!
@@ -583,7 +583,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
583583
/// See `README.md` for more details.
584584
pub fn skolemize_late_bound_regions<T>(&self,
585585
binder: &ty::Binder<T>,
586-
snapshot: &CombinedSnapshot)
586+
snapshot: &CombinedSnapshot<'a, 'tcx>)
587587
-> (T, SkolemizationMap<'tcx>)
588588
where T : TypeFoldable<'tcx>
589589
{
@@ -609,7 +609,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
609609
overly_polymorphic: bool,
610610
_span: Span,
611611
skol_map: &SkolemizationMap<'tcx>,
612-
snapshot: &CombinedSnapshot)
612+
snapshot: &CombinedSnapshot<'a, 'tcx>)
613613
-> RelateResult<'tcx, ()>
614614
{
615615
debug!("leak_check: skol_map={:?}",
@@ -684,7 +684,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
684684
/// predicate is `for<'a> &'a int : Clone`.
685685
pub fn plug_leaks<T>(&self,
686686
skol_map: SkolemizationMap<'tcx>,
687-
snapshot: &CombinedSnapshot,
687+
snapshot: &CombinedSnapshot<'a, 'tcx>,
688688
value: T) -> T
689689
where T : TypeFoldable<'tcx>
690690
{
@@ -770,8 +770,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
770770
/// Note: popping also occurs implicitly as part of `leak_check`.
771771
pub fn pop_skolemized(&self,
772772
skol_map: SkolemizationMap<'tcx>,
773-
snapshot: &CombinedSnapshot)
774-
{
773+
snapshot: &CombinedSnapshot<'a, 'tcx>) {
775774
debug!("pop_skolemized({:?})", skol_map);
776775
let skol_regions: FxHashSet<_> = skol_map.values().cloned().collect();
777776
self.borrow_region_constraints()

‎src/librustc/infer/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ impl<'tcx, T> InferOk<'tcx, T> {
475475
#[must_use = "once you start a snapshot, you should always consume it"]
476476
pub struct CombinedSnapshot<'a, 'tcx:'a> {
477477
projection_cache_snapshot: traits::ProjectionCacheSnapshot,
478-
type_snapshot: type_variable::Snapshot,
478+
type_snapshot: type_variable::Snapshot<'tcx>,
479479
int_snapshot: ut::Snapshot<ut::InPlace<ty::IntVid>>,
480480
float_snapshot: ut::Snapshot<ut::InPlace<ty::FloatVid>>,
481481
region_constraints_snapshot: RegionSnapshot,
@@ -765,7 +765,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
765765
result
766766
}
767767

768-
fn start_snapshot<'b>(&'b self) -> CombinedSnapshot<'b, 'tcx> {
768+
fn start_snapshot(&self) -> CombinedSnapshot<'a, 'tcx> {
769769
debug!("start_snapshot()");
770770

771771
let in_snapshot = self.in_snapshot.get();
@@ -787,7 +787,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
787787
}
788788
}
789789

790-
fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot) {
790+
fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'a, 'tcx>) {
791791
debug!("rollback_to(cause={})", cause);
792792
let CombinedSnapshot { projection_cache_snapshot,
793793
type_snapshot,
@@ -819,7 +819,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
819819
.rollback_to(region_constraints_snapshot);
820820
}
821821

822-
fn commit_from(&self, snapshot: CombinedSnapshot) {
822+
fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) {
823823
debug!("commit_from()");
824824
let CombinedSnapshot { projection_cache_snapshot,
825825
type_snapshot,
@@ -861,7 +861,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
861861

862862
/// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`
863863
pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
864-
F: FnOnce(&CombinedSnapshot) -> Result<T, E>
864+
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result<T, E>
865865
{
866866
debug!("commit_if_ok()");
867867
let snapshot = self.start_snapshot();
@@ -876,7 +876,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
876876

877877
// Execute `f` in a snapshot, and commit the bindings it creates
878878
pub fn in_snapshot<T, F>(&self, f: F) -> T where
879-
F: FnOnce(&CombinedSnapshot) -> T
879+
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> T
880880
{
881881
debug!("in_snapshot()");
882882
let snapshot = self.start_snapshot();
@@ -887,7 +887,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
887887

888888
/// Execute `f` then unroll any bindings it creates
889889
pub fn probe<R, F>(&self, f: F) -> R where
890-
F: FnOnce(&CombinedSnapshot) -> R,
890+
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
891891
{
892892
debug!("probe()");
893893
let snapshot = self.start_snapshot();

‎src/librustc/infer/type_variable.rs

Lines changed: 151 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,24 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use self::TypeVariableValue::*;
1211
use syntax::ast;
1312
use syntax_pos::Span;
1413
use ty::{self, Ty};
1514

1615
use std::cmp::min;
1716
use std::marker::PhantomData;
18-
use std::mem;
1917
use std::u32;
2018
use rustc_data_structures::fx::FxHashMap;
2119
use rustc_data_structures::snapshot_vec as sv;
2220
use rustc_data_structures::unify as ut;
2321

2422
pub struct TypeVariableTable<'tcx> {
25-
values: sv::SnapshotVec<Delegate<'tcx>>,
23+
values: sv::SnapshotVec<Delegate>,
2624

2725
/// Two variables are unified in `eq_relations` when we have a
28-
/// constraint `?X == ?Y`.
29-
eq_relations: ut::UnificationTable<ut::InPlace<ty::TyVid>>,
26+
/// constraint `?X == ?Y`. This table also stores, for each key,
27+
/// the known value.
28+
eq_relations: ut::UnificationTable<ut::InPlace<TyVidEqKey<'tcx>>>,
3029

3130
/// Two variables are unified in `eq_relations` when we have a
3231
/// constraint `?X <: ?Y` *or* a constraint `?Y <: ?X`. This second
@@ -71,30 +70,28 @@ pub enum TypeVariableOrigin {
7170

7271
pub type TypeVariableMap = FxHashMap<ty::TyVid, TypeVariableOrigin>;
7372

74-
struct TypeVariableData<'tcx> {
75-
value: TypeVariableValue<'tcx>,
73+
struct TypeVariableData {
7674
origin: TypeVariableOrigin,
7775
diverging: bool
7876
}
7977

78+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
8079
enum TypeVariableValue<'tcx> {
81-
Known {
82-
value: Ty<'tcx>
83-
},
80+
Known { value: Ty<'tcx> },
8481
Unknown,
8582
}
8683

87-
pub struct Snapshot {
84+
pub struct Snapshot<'tcx> {
8885
snapshot: sv::Snapshot,
89-
eq_snapshot: ut::Snapshot<ut::InPlace<ty::TyVid>>,
86+
eq_snapshot: ut::Snapshot<ut::InPlace<TyVidEqKey<'tcx>>>,
9087
sub_snapshot: ut::Snapshot<ut::InPlace<ty::TyVid>>,
9188
}
9289

9390
struct Instantiate {
9491
vid: ty::TyVid,
9592
}
9693

97-
struct Delegate<'tcx>(PhantomData<&'tcx ()>);
94+
struct Delegate;
9895

9996
impl<'tcx> TypeVariableTable<'tcx> {
10097
pub fn new() -> TypeVariableTable<'tcx> {
@@ -105,10 +102,18 @@ impl<'tcx> TypeVariableTable<'tcx> {
105102
}
106103
}
107104

105+
/// Returns the diverges flag given when `vid` was created.
106+
///
107+
/// Note that this function does not return care whether
108+
/// `vid` has been unified with something else or not.
108109
pub fn var_diverges<'a>(&'a self, vid: ty::TyVid) -> bool {
109110
self.values.get(vid.index as usize).diverging
110111
}
111112

113+
/// Returns the origin that was given when `vid` was created.
114+
///
115+
/// Note that this function does not return care whether
116+
/// `vid` has been unified with something else or not.
112117
pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin {
113118
&self.values.get(vid.index as usize).origin
114119
}
@@ -137,41 +142,49 @@ impl<'tcx> TypeVariableTable<'tcx> {
137142
/// Precondition: `vid` must not have been previously instantiated.
138143
pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) {
139144
let vid = self.root_var(vid);
140-
debug_assert!(self.probe_root(vid).is_none());
141-
142-
let old_value = {
143-
let vid_data = &mut self.values[vid.index as usize];
144-
mem::replace(&mut vid_data.value, TypeVariableValue::Known { value: ty })
145-
};
146-
147-
match old_value {
148-
TypeVariableValue::Unknown => {
149-
self.values.record(Instantiate { vid: vid });
150-
}
151-
TypeVariableValue::Known { value: old_ty } => {
152-
bug!("instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}",
153-
vid, ty, old_ty)
154-
}
155-
}
145+
debug_assert!(self.probe(vid).is_none());
146+
debug_assert!(self.eq_relations.probe_value(vid) == TypeVariableValue::Unknown,
147+
"instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}",
148+
vid, ty, self.eq_relations.probe_value(vid));
149+
self.eq_relations.union_value(vid, TypeVariableValue::Known { value: ty });
150+
151+
// Hack: we only need this so that `types_escaping_snapshot`
152+
// can see what has been unified; see the Delegate impl for
153+
// more details.
154+
self.values.record(Instantiate { vid: vid });
156155
}
157156

157+
/// Creates a new type variable.
158+
///
159+
/// - `diverging`: indicates if this is a "diverging" type
160+
/// variable, e.g. one created as the type of a `return`
161+
/// expression. The code in this module doesn't care if a
162+
/// variable is diverging, but the main Rust type-checker will
163+
/// sometimes "unify" such variables with the `!` or `()` types.
164+
/// - `origin`: indicates *why* the type variable was created.
165+
/// The code in this module doesn't care, but it can be useful
166+
/// for improving error messages.
158167
pub fn new_var(&mut self,
159168
diverging: bool,
160169
origin: TypeVariableOrigin)
161170
-> ty::TyVid {
162-
debug!("new_var(diverging={:?}, origin={:?})", diverging, origin);
163-
self.eq_relations.new_key(());
164-
self.sub_relations.new_key(());
171+
let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown);
172+
173+
let sub_key = self.sub_relations.new_key(());
174+
assert_eq!(eq_key.vid, sub_key);
175+
165176
let index = self.values.push(TypeVariableData {
166-
value: Unknown,
167177
origin,
168178
diverging,
169179
});
170-
let v = ty::TyVid { index: index as u32 };
171-
debug!("new_var: diverging={:?} index={:?}", diverging, v);
172-
v
180+
assert_eq!(eq_key.vid.index, index as u32);
181+
182+
debug!("new_var(index={:?}, diverging={:?}, origin={:?}", eq_key.vid, diverging, origin);
183+
184+
eq_key.vid
173185
}
174186

187+
/// Returns the number of type variables created thus far.
175188
pub fn num_vars(&self) -> usize {
176189
self.values.len()
177190
}
@@ -182,7 +195,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
182195
/// algorithm), so `root_var(a) == root_var(b)` implies that `a ==
183196
/// b` (transitively).
184197
pub fn root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
185-
self.eq_relations.find(vid)
198+
self.eq_relations.find(vid).vid
186199
}
187200

188201
/// Returns the "root" variable of `vid` in the `sub_relations`
@@ -202,24 +215,19 @@ impl<'tcx> TypeVariableTable<'tcx> {
202215
self.sub_root_var(a) == self.sub_root_var(b)
203216
}
204217

218+
/// Retrieves the type to which `vid` has been instantiated, if
219+
/// any.
205220
pub fn probe(&mut self, vid: ty::TyVid) -> Option<Ty<'tcx>> {
206221
let vid = self.root_var(vid);
207-
self.probe_root(vid)
208-
}
209-
210-
pub fn origin(&self, vid: ty::TyVid) -> TypeVariableOrigin {
211-
self.values.get(vid.index as usize).origin.clone()
212-
}
213-
214-
/// Retrieves the type of `vid` given that it is currently a root in the unification table
215-
pub fn probe_root(&mut self, vid: ty::TyVid) -> Option<Ty<'tcx>> {
216-
debug_assert!(self.root_var(vid) == vid);
217-
match self.values.get(vid.index as usize).value {
218-
Unknown => None,
219-
Known { value } => Some(value)
222+
match self.eq_relations.probe_value(vid) {
223+
TypeVariableValue::Unknown => None,
224+
TypeVariableValue::Known { value } => Some(value)
220225
}
221226
}
222227

228+
/// If `t` is a type-inference variable, and it has been
229+
/// instantiated, then return the with which it was
230+
/// instantiated. Otherwise, returns `t`.
223231
pub fn replace_if_possible(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
224232
match t.sty {
225233
ty::TyInfer(ty::TyVar(v)) => {
@@ -232,15 +240,22 @@ impl<'tcx> TypeVariableTable<'tcx> {
232240
}
233241
}
234242

235-
pub fn snapshot(&mut self) -> Snapshot {
243+
/// Creates a snapshot of the type variable state. This snapshot
244+
/// must later be committed (`commit()`) or rolled back
245+
/// (`rollback_to()`). Nested snapshots are permitted, but must
246+
/// be processed in a stack-like fashion.
247+
pub fn snapshot(&mut self) -> Snapshot<'tcx> {
236248
Snapshot {
237249
snapshot: self.values.start_snapshot(),
238250
eq_snapshot: self.eq_relations.snapshot(),
239251
sub_snapshot: self.sub_relations.snapshot(),
240252
}
241253
}
242254

243-
pub fn rollback_to(&mut self, s: Snapshot) {
255+
/// Undoes all changes since the snapshot was created. Any
256+
/// snapshots created since that point must already have been
257+
/// committed or rolled back.
258+
pub fn rollback_to(&mut self, s: Snapshot<'tcx>) {
244259
debug!("rollback_to{:?}", {
245260
for action in self.values.actions_since_snapshot(&s.snapshot) {
246261
match *action {
@@ -258,7 +273,11 @@ impl<'tcx> TypeVariableTable<'tcx> {
258273
self.sub_relations.rollback_to(sub_snapshot);
259274
}
260275

261-
pub fn commit(&mut self, s: Snapshot) {
276+
/// Commits all changes since the snapshot was created, making
277+
/// them permanent (unless this snapshot was created within
278+
/// another snapshot). Any snapshots created since that point
279+
/// must already have been committed or rolled back.
280+
pub fn commit(&mut self, s: Snapshot<'tcx>) {
262281
let Snapshot { snapshot, eq_snapshot, sub_snapshot } = s;
263282
self.values.commit(snapshot);
264283
self.eq_relations.commit(eq_snapshot);
@@ -269,7 +288,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
269288
/// ty-variables created during the snapshot, and the values
270289
/// `{V2}` are the root variables that they were unified with,
271290
/// along with their origin.
272-
pub fn types_created_since_snapshot(&mut self, s: &Snapshot) -> TypeVariableMap {
291+
pub fn types_created_since_snapshot(&mut self, s: &Snapshot<'tcx>) -> TypeVariableMap {
273292
let actions_since_snapshot = self.values.actions_since_snapshot(&s.snapshot);
274293

275294
actions_since_snapshot
@@ -285,16 +304,13 @@ impl<'tcx> TypeVariableTable<'tcx> {
285304
.collect()
286305
}
287306

288-
pub fn types_escaping_snapshot(&mut self, s: &Snapshot) -> Vec<Ty<'tcx>> {
289-
/*!
290-
* Find the set of type variables that existed *before* `s`
291-
* but which have only been unified since `s` started, and
292-
* return the types with which they were unified. So if we had
293-
* a type variable `V0`, then we started the snapshot, then we
294-
* created a type variable `V1`, unifed `V0` with `T0`, and
295-
* unified `V1` with `T1`, this function would return `{T0}`.
296-
*/
297-
307+
/// Find the set of type variables that existed *before* `s`
308+
/// but which have only been unified since `s` started, and
309+
/// return the types with which they were unified. So if we had
310+
/// a type variable `V0`, then we started the snapshot, then we
311+
/// created a type variable `V1`, unifed `V0` with `T0`, and
312+
/// unified `V1` with `T1`, this function would return `{T0}`.
313+
pub fn types_escaping_snapshot(&mut self, s: &Snapshot<'tcx>) -> Vec<Ty<'tcx>> {
298314
let mut new_elem_threshold = u32::MAX;
299315
let mut escaping_types = Vec::new();
300316
let actions_since_snapshot = self.values.actions_since_snapshot(&s.snapshot);
@@ -315,9 +331,9 @@ impl<'tcx> TypeVariableTable<'tcx> {
315331
if vid.index < new_elem_threshold {
316332
// quick check to see if this variable was
317333
// created since the snapshot started or not.
318-
let escaping_type = match self.values.get(vid.index as usize).value {
319-
Unknown => bug!(),
320-
Known { value } => value,
334+
let escaping_type = match self.eq_relations.probe_value(vid) {
335+
TypeVariableValue::Unknown => bug!(),
336+
TypeVariableValue::Known { value } => value,
321337
};
322338
escaping_types.push(escaping_type);
323339
}
@@ -331,6 +347,8 @@ impl<'tcx> TypeVariableTable<'tcx> {
331347
escaping_types
332348
}
333349

350+
/// Returns indices of all variables that are not yet
351+
/// instantiated.
334352
pub fn unsolved_variables(&mut self) -> Vec<ty::TyVid> {
335353
(0..self.values.len())
336354
.filter_map(|i| {
@@ -345,19 +363,80 @@ impl<'tcx> TypeVariableTable<'tcx> {
345363
}
346364
}
347365

348-
impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
349-
type Value = TypeVariableData<'tcx>;
366+
impl sv::SnapshotVecDelegate for Delegate {
367+
type Value = TypeVariableData;
350368
type Undo = Instantiate;
351369

352-
fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: Instantiate) {
353-
let Instantiate { vid } = action;
354-
values[vid.index as usize].value = Unknown;
370+
fn reverse(_values: &mut Vec<TypeVariableData>, _action: Instantiate) {
371+
// We don't actually have to *do* anything to reverse an
372+
// instanation; the value for a variable is stored in the
373+
// `eq_relations` and hence its rollback code will handle
374+
// it. In fact, we could *almost* just remove the
375+
// `SnapshotVec` entirely, except that we would have to
376+
// reproduce *some* of its logic, since we want to know which
377+
// type variables have been instantiated since the snapshot
378+
// was started, so we can implement `types_escaping_snapshot`.
379+
//
380+
// (If we extended the `UnificationTable` to let us see which
381+
// values have been unified and so forth, that might also
382+
// suffice.)
383+
}
384+
}
385+
386+
///////////////////////////////////////////////////////////////////////////
387+
388+
/// These structs (a newtyped TyVid) are used as the unification key
389+
/// for the `eq_relations`; they carry a `TypeVariableValue` along
390+
/// with them.
391+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
392+
struct TyVidEqKey<'tcx> {
393+
vid: ty::TyVid,
394+
395+
// in the table, we map each ty-vid to one of these:
396+
phantom: PhantomData<TypeVariableValue<'tcx>>,
397+
}
398+
399+
impl<'tcx> From<ty::TyVid> for TyVidEqKey<'tcx> {
400+
fn from(vid: ty::TyVid) -> Self {
401+
TyVidEqKey { vid, phantom: PhantomData }
402+
}
403+
}
404+
405+
impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> {
406+
type Value = TypeVariableValue<'tcx>;
407+
fn index(&self) -> u32 { self.vid.index }
408+
fn from_index(i: u32) -> Self { TyVidEqKey::from(ty::TyVid { index: i }) }
409+
fn tag() -> &'static str { "TyVidEqKey" }
410+
}
411+
412+
impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
413+
type Error = ut::NoError;
414+
415+
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, ut::NoError> {
416+
match (value1, value2) {
417+
// We never equate two type variables, both of which
418+
// have known types. Instead, we recursively equate
419+
// those types.
420+
(&TypeVariableValue::Known { .. }, &TypeVariableValue::Known { .. }) => {
421+
bug!("equating two type variables, both of which have known types")
422+
}
423+
424+
// If one side is known, prefer that one.
425+
(&TypeVariableValue::Known { .. }, &TypeVariableValue::Unknown { .. }) => Ok(*value1),
426+
(&TypeVariableValue::Unknown { .. }, &TypeVariableValue::Known { .. }) => Ok(*value2),
427+
428+
// If both sides are *unknown*, it hardly matters, does it?
429+
(&TypeVariableValue::Unknown, &TypeVariableValue::Unknown) => Ok(*value1),
430+
}
355431
}
356432
}
357433

434+
/// Raw `TyVid` are used as the unification key for `sub_relations`;
435+
/// they carry no values.
358436
impl ut::UnifyKey for ty::TyVid {
359437
type Value = ();
360438
fn index(&self) -> u32 { self.index }
361439
fn from_index(i: u32) -> ty::TyVid { ty::TyVid { index: i } }
362440
fn tag() -> &'static str { "TyVid" }
363441
}
442+

‎src/librustc/traits/select.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
496496
/// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection
497497
/// context's self.
498498
fn in_snapshot<R, F>(&mut self, f: F) -> R
499-
where F: FnOnce(&mut Self, &infer::CombinedSnapshot) -> R
499+
where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R
500500
{
501501
// The irrefutable nature of the operation means we don't need to snapshot the
502502
// inferred_obligations vector.
@@ -506,7 +506,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
506506
/// Wraps a probe s.t. obligations collected during it are ignored and old obligations are
507507
/// retained.
508508
fn probe<R, F>(&mut self, f: F) -> R
509-
where F: FnOnce(&mut Self, &infer::CombinedSnapshot) -> R
509+
where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R
510510
{
511511
let inferred_obligations_snapshot = self.inferred_obligations.start_snapshot();
512512
let result = self.infcx.probe(|snapshot| f(self, snapshot));
@@ -1478,7 +1478,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
14781478
fn match_projection_obligation_against_definition_bounds(
14791479
&mut self,
14801480
obligation: &TraitObligation<'tcx>,
1481-
snapshot: &infer::CombinedSnapshot)
1481+
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
14821482
-> bool
14831483
{
14841484
let poly_trait_predicate =
@@ -1549,7 +1549,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
15491549
trait_bound: ty::PolyTraitRef<'tcx>,
15501550
skol_trait_ref: ty::TraitRef<'tcx>,
15511551
skol_map: &infer::SkolemizationMap<'tcx>,
1552-
snapshot: &infer::CombinedSnapshot)
1552+
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
15531553
-> bool
15541554
{
15551555
assert!(!skol_trait_ref.has_escaping_regions());
@@ -2587,7 +2587,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
25872587
recursion_depth: usize,
25882588
param_env: ty::ParamEnv<'tcx>,
25892589
skol_map: infer::SkolemizationMap<'tcx>,
2590-
snapshot: &infer::CombinedSnapshot)
2590+
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
25912591
-> VtableImplData<'tcx, PredicateObligation<'tcx>>
25922592
{
25932593
debug!("vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={}, skol_map={:?})",
@@ -3076,7 +3076,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
30763076
fn rematch_impl(&mut self,
30773077
impl_def_id: DefId,
30783078
obligation: &TraitObligation<'tcx>,
3079-
snapshot: &infer::CombinedSnapshot)
3079+
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
30803080
-> (Normalized<'tcx, &'tcx Substs<'tcx>>,
30813081
infer::SkolemizationMap<'tcx>)
30823082
{
@@ -3093,7 +3093,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
30933093
fn match_impl(&mut self,
30943094
impl_def_id: DefId,
30953095
obligation: &TraitObligation<'tcx>,
3096-
snapshot: &infer::CombinedSnapshot)
3096+
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
30973097
-> Result<(Normalized<'tcx, &'tcx Substs<'tcx>>,
30983098
infer::SkolemizationMap<'tcx>), ()>
30993099
{
@@ -3288,7 +3288,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
32883288
def_id: DefId, // of impl or trait
32893289
substs: &Substs<'tcx>, // for impl or trait
32903290
skol_map: infer::SkolemizationMap<'tcx>,
3291-
snapshot: &infer::CombinedSnapshot)
3291+
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
32923292
-> Vec<PredicateObligation<'tcx>>
32933293
{
32943294
debug!("impl_or_trait_obligations(def_id={:?})", def_id);

0 commit comments

Comments
 (0)
Please sign in to comment.