17
17
18
18
use fnv:: { FnvHashMap , FnvHashSet } ;
19
19
20
+ use std:: cell:: Cell ;
20
21
use std:: collections:: hash_map:: Entry ;
21
22
use std:: fmt:: Debug ;
22
23
use std:: hash;
@@ -41,7 +42,9 @@ pub trait ObligationProcessor {
41
42
obligation : & mut Self :: Obligation )
42
43
-> Result < Option < Vec < Self :: Obligation > > , Self :: Error > ;
43
44
44
- fn process_backedge ( & mut self , cycle : & [ Self :: Obligation ] ) ;
45
+ // FIXME: crazy lifetime troubles
46
+ fn process_backedge < I > ( & mut self , cycle : I )
47
+ where I : Clone + Iterator < Item =* const Self :: Obligation > ;
45
48
}
46
49
47
50
struct SnapshotData {
@@ -77,7 +80,7 @@ pub struct Snapshot {
77
80
#[ derive( Debug ) ]
78
81
struct Node < O > {
79
82
obligation : O ,
80
- state : NodeState ,
83
+ state : Cell < NodeState > ,
81
84
82
85
// these both go *in the same direction*.
83
86
parent : Option < NodeIndex > ,
@@ -87,14 +90,17 @@ struct Node<O> {
87
90
/// The state of one node in some tree within the forest. This
88
91
/// represents the current state of processing for the obligation (of
89
92
/// type `O`) associated with this node.
90
- #[ derive( Debug , PartialEq , Eq ) ]
93
+ #[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
91
94
enum NodeState {
92
95
/// Obligation not yet resolved to success or error.
93
96
Pending ,
94
97
95
98
/// Used before garbage collection
96
99
Success ,
97
100
101
+ /// Used in DFS loops
102
+ InLoop ,
103
+
98
104
/// Obligation resolved to success; `num_incomplete_children`
99
105
/// indicates the number of children still in an "incomplete"
100
106
/// state. Incomplete means that either the child is still
@@ -225,7 +231,7 @@ impl<O: Debug + ForestObligation> ObligationForest<O> {
225
231
let mut errors = vec ! [ ] ;
226
232
for index in 0 ..self . nodes . len ( ) {
227
233
debug_assert ! ( !self . nodes[ index] . is_popped( ) ) ;
228
- if let NodeState :: Pending = self . nodes [ index] . state {
234
+ if let NodeState :: Pending = self . nodes [ index] . state . get ( ) {
229
235
let backtrace = self . error_at ( index) ;
230
236
errors. push ( Error {
231
237
error : error. clone ( ) ,
@@ -244,7 +250,7 @@ impl<O: Debug + ForestObligation> ObligationForest<O> {
244
250
{
245
251
self . nodes
246
252
. iter ( )
247
- . filter ( |n| n. state == NodeState :: Pending )
253
+ . filter ( |n| n. state . get ( ) == NodeState :: Pending )
248
254
. map ( |n| n. obligation . clone ( ) )
249
255
. collect ( )
250
256
}
@@ -270,7 +276,9 @@ impl<O: Debug + ForestObligation> ObligationForest<O> {
270
276
self . nodes[ index] ) ;
271
277
272
278
let result = match self . nodes [ index] {
273
- Node { state : NodeState :: Pending , ref mut obligation, .. } => {
279
+ Node { state : ref _state, ref mut obligation, .. }
280
+ if _state. get ( ) == NodeState :: Pending =>
281
+ {
274
282
processor. process_obligation ( obligation)
275
283
}
276
284
_ => continue
@@ -292,7 +300,7 @@ impl<O: Debug + ForestObligation> ObligationForest<O> {
292
300
Some ( NodeIndex :: new ( index) ) ) ;
293
301
}
294
302
295
- self . nodes [ index] . state = NodeState :: Success ;
303
+ self . nodes [ index] . state . set ( NodeState :: Success ) ;
296
304
}
297
305
Err ( err) => {
298
306
let backtrace = self . error_at ( index) ;
@@ -319,29 +327,69 @@ impl<O: Debug + ForestObligation> ObligationForest<O> {
319
327
}
320
328
}
321
329
322
- pub fn process_cycles < P > ( & mut self , _processor : & mut P )
330
+ pub fn process_cycles < P > ( & mut self , processor : & mut P )
323
331
where P : ObligationProcessor < Obligation =O >
324
332
{
325
- // TODO: implement
326
- for node in & mut self . nodes {
327
- if node. state == NodeState :: Success {
328
- node. state = NodeState :: Done ;
329
- }
333
+ let mut stack = self . scratch . take ( ) . unwrap ( ) ;
334
+
335
+ for node in 0 ..self . nodes . len ( ) {
336
+ self . visit_node ( & mut stack, processor, node) ;
330
337
}
338
+
339
+ self . scratch = Some ( stack) ;
340
+ }
341
+
342
+ fn visit_node < P > ( & self , stack : & mut Vec < usize > , processor : & mut P , index : usize )
343
+ where P : ObligationProcessor < Obligation =O >
344
+ {
345
+ let node = & self . nodes [ index] ;
346
+ let state = node. state . get ( ) ;
347
+ match state {
348
+ NodeState :: InLoop => {
349
+ let index =
350
+ stack. iter ( ) . rposition ( |n| * n == index) . unwrap ( ) ;
351
+ // I need a Clone closure
352
+ #[ derive( Clone ) ]
353
+ struct GetObligation < ' a , O : ' a > ( & ' a [ Node < O > ] ) ;
354
+ impl < ' a , ' b , O > FnOnce < ( & ' b usize , ) > for GetObligation < ' a , O > {
355
+ type Output = * const O ;
356
+ extern "rust-call" fn call_once ( self , args : ( & ' b usize , ) ) -> * const O {
357
+ & self . 0 [ * args. 0 ] . obligation
358
+ }
359
+ }
360
+ impl < ' a , ' b , O > FnMut < ( & ' b usize , ) > for GetObligation < ' a , O > {
361
+ extern "rust-call" fn call_mut ( & mut self , args : ( & ' b usize , ) ) -> * const O {
362
+ & self . 0 [ * args. 0 ] . obligation
363
+ }
364
+ }
365
+
366
+ processor. process_backedge ( stack[ index..] . iter ( ) . map ( GetObligation ( & self . nodes ) ) ) ;
367
+ }
368
+ NodeState :: Success => {
369
+ node. state . set ( NodeState :: InLoop ) ;
370
+ stack. push ( index) ;
371
+ if let Some ( parent) = node. parent {
372
+ self . visit_node ( stack, processor, parent. get ( ) ) ;
373
+ }
374
+ for dependant in & node. dependants {
375
+ self . visit_node ( stack, processor, dependant. get ( ) ) ;
376
+ }
377
+ stack. pop ( ) ;
378
+ node. state . set ( NodeState :: Done ) ;
379
+ } ,
380
+ _ => return
381
+ } ;
331
382
}
332
383
333
384
/// Returns a vector of obligations for `p` and all of its
334
385
/// ancestors, putting them into the error state in the process.
335
- /// The fact that the root is now marked as an error is used by
336
- /// `inherit_error` above to propagate the error state to the
337
- /// remainder of the tree.
338
386
fn error_at ( & mut self , p : usize ) -> Vec < O > {
339
387
let mut error_stack = self . scratch . take ( ) . unwrap ( ) ;
340
388
let mut trace = vec ! [ ] ;
341
389
342
390
let mut n = p;
343
391
loop {
344
- self . nodes [ n] . state = NodeState :: Error ;
392
+ self . nodes [ n] . state . set ( NodeState :: Error ) ;
345
393
trace. push ( self . nodes [ n] . obligation . clone ( ) ) ;
346
394
error_stack. extend ( self . nodes [ n] . dependants . iter ( ) . map ( |x| x. get ( ) ) ) ;
347
395
@@ -359,12 +407,13 @@ impl<O: Debug + ForestObligation> ObligationForest<O> {
359
407
None => break
360
408
} ;
361
409
362
- match self . nodes [ i] . state {
410
+ let node = & self . nodes [ i] ;
411
+
412
+ match node. state . get ( ) {
363
413
NodeState :: Error => continue ,
364
- ref mut s => * s = NodeState :: Error
414
+ _ => node . state . set ( NodeState :: Error )
365
415
}
366
416
367
- let node = & self . nodes [ i] ;
368
417
error_stack. extend (
369
418
node. dependants . iter ( ) . cloned ( ) . chain ( node. parent ) . map ( |x| x. get ( ) )
370
419
) ;
@@ -374,41 +423,37 @@ impl<O: Debug + ForestObligation> ObligationForest<O> {
374
423
trace
375
424
}
376
425
377
- fn mark_as_waiting ( & mut self ) {
378
- for node in & mut self . nodes {
379
- if node. state == NodeState :: Waiting {
380
- node. state = NodeState :: Success ;
426
+ /// Marks all nodes that depend on a pending node as "waiting".
427
+ fn mark_as_waiting ( & self ) {
428
+ for node in & self . nodes {
429
+ if node. state . get ( ) == NodeState :: Waiting {
430
+ node. state . set ( NodeState :: Success ) ;
381
431
}
382
432
}
383
433
384
- let mut undone_stack = self . scratch . take ( ) . unwrap ( ) ;
385
- undone_stack. extend (
386
- self . nodes . iter ( ) . enumerate ( )
387
- . filter ( |& ( _i, n) | n. state == NodeState :: Pending )
388
- . map ( |( i, _n) | i) ) ;
389
-
390
- loop {
391
- // non-standard `while let` to bypass #6393
392
- let i = match undone_stack. pop ( ) {
393
- Some ( i) => i,
394
- None => break
395
- } ;
434
+ for node in & self . nodes {
435
+ if node. state . get ( ) == NodeState :: Pending {
436
+ self . mark_as_waiting_from ( node)
437
+ }
438
+ }
439
+ }
396
440
397
- match self . nodes [ i ] . state {
398
- NodeState :: Pending | NodeState :: Done => { } ,
399
- NodeState :: Waiting | NodeState :: Error => continue ,
400
- ref mut s @ NodeState :: Success => {
401
- * s = NodeState :: Waiting ;
402
- }
441
+ fn mark_as_waiting_from ( & self , node : & Node < O > ) {
442
+ match node . state . get ( ) {
443
+ NodeState :: Pending | NodeState :: Done => { } ,
444
+ NodeState :: Waiting | NodeState :: Error | NodeState :: InLoop => return ,
445
+ NodeState :: Success => {
446
+ node . state . set ( NodeState :: Waiting ) ;
403
447
}
448
+ }
404
449
405
- let node = & self . nodes [ i] ;
406
- undone_stack. extend (
407
- node. dependants . iter ( ) . cloned ( ) . chain ( node. parent ) . map ( |x| x. get ( ) )
408
- ) ;
450
+ if let Some ( parent) = node. parent {
451
+ self . mark_as_waiting_from ( & self . nodes [ parent. get ( ) ] ) ;
409
452
}
410
453
411
- self . scratch = Some ( undone_stack) ;
454
+ for dependant in & node. dependants {
455
+ self . mark_as_waiting_from ( & self . nodes [ dependant. get ( ) ] ) ;
456
+ }
412
457
}
413
458
414
459
/// Compresses the vector, removing all popped nodes. This adjusts
@@ -433,12 +478,22 @@ impl<O: Debug + ForestObligation> ObligationForest<O> {
433
478
// self.nodes[i - dead_nodes..i] are all dead
434
479
// self.nodes[i..] are unchanged
435
480
for i in 0 ..self . nodes . len ( ) {
436
- if let NodeState :: Done = self . nodes [ i] . state {
437
- self . done_cache . insert ( self . nodes [ i] . obligation . as_predicate ( ) . clone ( ) ) ;
481
+ match self . nodes [ i] . state . get ( ) {
482
+ NodeState :: Done => {
483
+ self . waiting_cache . remove ( self . nodes [ i] . obligation . as_predicate ( ) ) ;
484
+ // FIXME(HashMap): why can't I get my key back?
485
+ self . done_cache . insert ( self . nodes [ i] . obligation . as_predicate ( ) . clone ( ) ) ;
486
+ }
487
+ NodeState :: Error => {
488
+ // We *intentionally* remove the node from the cache at this point. Otherwise
489
+ // tests must come up with a different type on every type error they
490
+ // check against.
491
+ self . waiting_cache . remove ( self . nodes [ i] . obligation . as_predicate ( ) ) ;
492
+ }
493
+ _ => { }
438
494
}
439
495
440
496
if self . nodes [ i] . is_popped ( ) {
441
- self . waiting_cache . remove ( self . nodes [ i] . obligation . as_predicate ( ) ) ;
442
497
node_rewrites[ i] = nodes_len;
443
498
dead_nodes += 1 ;
444
499
} else {
@@ -461,7 +516,7 @@ impl<O: Debug + ForestObligation> ObligationForest<O> {
461
516
let successful = ( 0 ..dead_nodes)
462
517
. map ( |_| self . nodes . pop ( ) . unwrap ( ) )
463
518
. flat_map ( |node| {
464
- match node. state {
519
+ match node. state . get ( ) {
465
520
NodeState :: Error => None ,
466
521
NodeState :: Done => Some ( node. obligation ) ,
467
522
_ => unreachable ! ( )
@@ -521,15 +576,15 @@ impl<O> Node<O> {
521
576
Node {
522
577
obligation : obligation,
523
578
parent : parent,
524
- state : NodeState :: Pending ,
579
+ state : Cell :: new ( NodeState :: Pending ) ,
525
580
dependants : vec ! [ ] ,
526
581
}
527
582
}
528
583
529
584
fn is_popped ( & self ) -> bool {
530
- match self . state {
585
+ match self . state . get ( ) {
531
586
NodeState :: Pending | NodeState :: Success | NodeState :: Waiting => false ,
532
- NodeState :: Error | NodeState :: Done => true ,
587
+ NodeState :: Error | NodeState :: Done | NodeState :: InLoop => true ,
533
588
}
534
589
}
535
590
}
0 commit comments