@@ -12,15 +12,18 @@ use syntax::ast;
1212use syntax_pos:: Span ;
1313use ty:: { self , Ty } ;
1414
15- use std:: cmp:: min;
1615use std:: marker:: PhantomData ;
1716use std:: u32;
1817use rustc_data_structures:: fx:: FxHashMap ;
19- use rustc_data_structures:: snapshot_vec as sv;
2018use rustc_data_structures:: unify as ut;
2119
2220pub struct TypeVariableTable < ' tcx > {
23- values : sv:: SnapshotVec < Delegate > ,
21+ /// Extra data for each type variable, such as the origin. This is
22+ /// not stored in the unification table since, when we inquire
23+ /// after the origin of a variable X, we want the origin of **that
24+ /// variable X**, not the origin of some other variable Y with
25+ /// which X has been unified.
26+ var_data : Vec < TypeVariableData > ,
2427
2528 /// Two variables are unified in `eq_relations` when we have a
2629 /// constraint `?X == ?Y`. This table also stores, for each key,
@@ -82,21 +85,20 @@ enum TypeVariableValue<'tcx> {
8285}
8386
8487pub struct Snapshot < ' tcx > {
85- snapshot : sv:: Snapshot ,
88+ /// number of variables at the time of the snapshot
89+ num_vars : usize ,
90+
91+ /// snapshot from the `eq_relations` table
8692 eq_snapshot : ut:: Snapshot < ut:: InPlace < TyVidEqKey < ' tcx > > > ,
87- sub_snapshot : ut:: Snapshot < ut:: InPlace < ty:: TyVid > > ,
88- }
8993
90- struct Instantiate {
91- vid : ty:: TyVid ,
94+ /// snapshot from the `sub_relations` table
95+ sub_snapshot : ut :: Snapshot < ut :: InPlace < ty:: TyVid > > ,
9296}
9397
94- struct Delegate ;
95-
9698impl < ' tcx > TypeVariableTable < ' tcx > {
9799 pub fn new ( ) -> TypeVariableTable < ' tcx > {
98100 TypeVariableTable {
99- values : sv :: SnapshotVec :: new ( ) ,
101+ var_data : Vec :: new ( ) ,
100102 eq_relations : ut:: UnificationTable :: new ( ) ,
101103 sub_relations : ut:: UnificationTable :: new ( ) ,
102104 }
@@ -107,15 +109,15 @@ impl<'tcx> TypeVariableTable<'tcx> {
107109 /// Note that this function does not return care whether
108110 /// `vid` has been unified with something else or not.
109111 pub fn var_diverges < ' a > ( & ' a self , vid : ty:: TyVid ) -> bool {
110- self . values . get ( vid. index as usize ) . diverging
112+ self . var_data [ vid. index as usize ] . diverging
111113 }
112114
113115 /// Returns the origin that was given when `vid` was created.
114116 ///
115117 /// Note that this function does not return care whether
116118 /// `vid` has been unified with something else or not.
117119 pub fn var_origin ( & self , vid : ty:: TyVid ) -> & TypeVariableOrigin {
118- & self . values . get ( vid. index as usize ) . origin
120+ & self . var_data [ vid. index as usize ] . origin
119121 }
120122
121123 /// Records that `a == b`, depending on `dir`.
@@ -147,11 +149,6 @@ impl<'tcx> TypeVariableTable<'tcx> {
147149 "instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}" ,
148150 vid, ty, self . eq_relations. probe_value( vid) ) ;
149151 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 } ) ;
155152 }
156153
157154 /// Creates a new type variable.
@@ -173,11 +170,8 @@ impl<'tcx> TypeVariableTable<'tcx> {
173170 let sub_key = self . sub_relations . new_key ( ( ) ) ;
174171 assert_eq ! ( eq_key. vid, sub_key) ;
175172
176- let index = self . values . push ( TypeVariableData {
177- origin,
178- diverging,
179- } ) ;
180- assert_eq ! ( eq_key. vid. index, index as u32 ) ;
173+ assert_eq ! ( self . var_data. len( ) , sub_key. index as usize ) ;
174+ self . var_data . push ( TypeVariableData { origin, diverging } ) ;
181175
182176 debug ! ( "new_var(index={:?}, diverging={:?}, origin={:?}" , eq_key. vid, diverging, origin) ;
183177
@@ -186,7 +180,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
186180
187181 /// Returns the number of type variables created thus far.
188182 pub fn num_vars ( & self ) -> usize {
189- self . values . len ( )
183+ self . var_data . len ( )
190184 }
191185
192186 /// Returns the "root" variable of `vid` in the `eq_relations`
@@ -246,7 +240,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
246240 /// be processed in a stack-like fashion.
247241 pub fn snapshot ( & mut self ) -> Snapshot < ' tcx > {
248242 Snapshot {
249- snapshot : self . values . start_snapshot ( ) ,
243+ num_vars : self . var_data . len ( ) ,
250244 eq_snapshot : self . eq_relations . snapshot ( ) ,
251245 sub_snapshot : self . sub_relations . snapshot ( ) ,
252246 }
@@ -256,30 +250,21 @@ impl<'tcx> TypeVariableTable<'tcx> {
256250 /// snapshots created since that point must already have been
257251 /// committed or rolled back.
258252 pub fn rollback_to ( & mut self , s : Snapshot < ' tcx > ) {
259- debug ! ( "rollback_to{:?}" , {
260- for action in self . values. actions_since_snapshot( & s. snapshot) {
261- match * action {
262- sv:: UndoLog :: NewElem ( index) => {
263- debug!( "inference variable _#{}t popped" , index)
264- }
265- _ => { }
266- }
267- }
268- } ) ;
269-
270- let Snapshot { snapshot, eq_snapshot, sub_snapshot } = s;
271- self . values . rollback_to ( snapshot) ;
253+ let Snapshot { num_vars, eq_snapshot, sub_snapshot } = s;
254+ debug ! ( "type_variables::rollback_to(num_vars = {})" , num_vars) ;
255+ assert ! ( self . var_data. len( ) >= num_vars) ;
272256 self . eq_relations . rollback_to ( eq_snapshot) ;
273257 self . sub_relations . rollback_to ( sub_snapshot) ;
258+ self . var_data . truncate ( num_vars) ;
274259 }
275260
276261 /// Commits all changes since the snapshot was created, making
277262 /// them permanent (unless this snapshot was created within
278263 /// another snapshot). Any snapshots created since that point
279264 /// must already have been committed or rolled back.
280265 pub fn commit ( & mut self , s : Snapshot < ' tcx > ) {
281- let Snapshot { snapshot , eq_snapshot, sub_snapshot } = s;
282- self . values . commit ( snapshot ) ;
266+ let Snapshot { num_vars , eq_snapshot, sub_snapshot } = s;
267+ debug ! ( "type_variables:: commit(num_vars = {})" , num_vars ) ;
283268 self . eq_relations . commit ( eq_snapshot) ;
284269 self . sub_relations . commit ( sub_snapshot) ;
285270 }
@@ -288,19 +273,12 @@ impl<'tcx> TypeVariableTable<'tcx> {
288273 /// ty-variables created during the snapshot, and the values
289274 /// `{V2}` are the root variables that they were unified with,
290275 /// along with their origin.
291- pub fn types_created_since_snapshot ( & mut self , s : & Snapshot < ' tcx > ) -> TypeVariableMap {
292- let actions_since_snapshot = self . values . actions_since_snapshot ( & s. snapshot ) ;
293-
294- actions_since_snapshot
276+ pub fn types_created_since_snapshot ( & mut self , snapshot : & Snapshot < ' tcx > ) -> TypeVariableMap {
277+ self . var_data
295278 . iter ( )
296- . filter_map ( |action| match action {
297- & sv:: UndoLog :: NewElem ( index) => Some ( ty:: TyVid { index : index as u32 } ) ,
298- _ => None ,
299- } )
300- . map ( |vid| {
301- let origin = self . values . get ( vid. index as usize ) . origin . clone ( ) ;
302- ( vid, origin)
303- } )
279+ . enumerate ( )
280+ . skip ( snapshot. num_vars ) // skip those that existed when snapshot was taken
281+ . map ( |( index, data) | ( ty:: TyVid { index : index as u32 } , data. origin ) )
304282 . collect ( )
305283 }
306284
@@ -310,47 +288,45 @@ impl<'tcx> TypeVariableTable<'tcx> {
310288 /// a type variable `V0`, then we started the snapshot, then we
311289 /// created a type variable `V1`, unifed `V0` with `T0`, and
312290 /// unified `V1` with `T1`, this function would return `{T0}`.
313- pub fn types_escaping_snapshot ( & mut self , s : & Snapshot < ' tcx > ) -> Vec < Ty < ' tcx > > {
314- let mut new_elem_threshold = u32:: MAX ;
315- let mut escaping_types = Vec :: new ( ) ;
316- let actions_since_snapshot = self . values . actions_since_snapshot ( & s. snapshot ) ;
317- debug ! ( "actions_since_snapshot.len() = {}" , actions_since_snapshot. len( ) ) ;
318- for action in actions_since_snapshot {
319- match * action {
320- sv:: UndoLog :: NewElem ( index) => {
321- // if any new variables were created during the
322- // snapshot, remember the lower index (which will
323- // always be the first one we see). Note that this
324- // action must precede those variables being
325- // specified.
326- new_elem_threshold = min ( new_elem_threshold, index as u32 ) ;
327- debug ! ( "NewElem({}) new_elem_threshold={}" , index, new_elem_threshold) ;
328- }
329-
330- sv:: UndoLog :: Other ( Instantiate { vid, .. } ) => {
331- if vid. index < new_elem_threshold {
332- // quick check to see if this variable was
333- // created since the snapshot started or not.
334- let escaping_type = match self . eq_relations . probe_value ( vid) {
335- TypeVariableValue :: Unknown => bug ! ( ) ,
336- TypeVariableValue :: Known { value } => value,
337- } ;
338- escaping_types. push ( escaping_type) ;
339- }
340- debug ! ( "SpecifyVar({:?}) new_elem_threshold={}" , vid, new_elem_threshold) ;
341- }
342-
343- _ => { }
344- }
345- }
346-
291+ pub fn types_escaping_snapshot ( & mut self , snapshot : & Snapshot < ' tcx > ) -> Vec < Ty < ' tcx > > {
292+ // We want to select only those instantiations that have
293+ // occurred since the snapshot *and* which affect some
294+ // variable that existed prior to the snapshot. This code just
295+ // affects all instantiatons that ever occurred which affect
296+ // variables prior to the snapshot.
297+ //
298+ // It's hard to do better than this, though, without changing
299+ // the unification table to prefer "lower" vids -- the problem
300+ // is that we may have a variable X (from before the snapshot)
301+ // and Y (from after the snapshot) which get unified, with Y
302+ // chosen as the new root. Now we are "instantiating" Y with a
303+ // value, but it escapes into X, but we wouldn't readily see
304+ // that. (In fact, earlier revisions of this code had this
305+ // bug; it was introduced when we added the `eq_relations`
306+ // table, but it's hard to create rust code that triggers it.)
307+ //
308+ // We could tell the table to prefer lower vids, and then we would
309+ // see the case above, but we would get less-well-balanced trees.
310+ //
311+ // Since I hope to kill the leak-check in this branch, and
312+ // that's the code which uses this logic anyway, I'm going to
313+ // use the less efficient algorithm for now.
314+ let mut escaping_types = Vec :: with_capacity ( snapshot. num_vars ) ;
315+ escaping_types. extend (
316+ ( 0 ..snapshot. num_vars ) // for all variables that pre-exist the snapshot...
317+ . map ( |i| ty:: TyVid { index : i as u32 } )
318+ . filter_map ( |vid| match self . eq_relations . probe_value ( vid) {
319+ TypeVariableValue :: Unknown => None ,
320+ TypeVariableValue :: Known { value } => Some ( value) ,
321+ } ) ) ; // ...collect what types they've been instantiated with.
322+ debug ! ( "types_escaping_snapshot = {:?}" , escaping_types) ;
347323 escaping_types
348324 }
349325
350326 /// Returns indices of all variables that are not yet
351327 /// instantiated.
352328 pub fn unsolved_variables ( & mut self ) -> Vec < ty:: TyVid > {
353- ( 0 ..self . values . len ( ) )
329+ ( 0 ..self . var_data . len ( ) )
354330 . filter_map ( |i| {
355331 let vid = ty:: TyVid { index : i as u32 } ;
356332 if self . probe ( vid) . is_some ( ) {
@@ -362,27 +338,6 @@ impl<'tcx> TypeVariableTable<'tcx> {
362338 . collect ( )
363339 }
364340}
365-
366- impl sv:: SnapshotVecDelegate for Delegate {
367- type Value = TypeVariableData ;
368- type Undo = Instantiate ;
369-
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-
386341///////////////////////////////////////////////////////////////////////////
387342
388343/// These structs (a newtyped TyVid) are used as the unification key
0 commit comments