Skip to content

Commit a820672

Browse files
committed
Avoid the popping loop at the end of compress().
By collecting the done obligations (when necessary) in the main loop. This makes the code cleaner. The commit also changes the order in which successful obligations are returned -- they are now returned in the registered order, rather than reversed. Because this order doesn't actually matter, being only used by tests, the commit uses `sort()` to make the test agnostic w.r.t. the order.
1 parent 2883c25 commit a820672

File tree

2 files changed

+40
-34
lines changed

2 files changed

+40
-34
lines changed

src/librustc_data_structures/obligation_forest/mod.rs

+19-27
Original file line numberDiff line numberDiff line change
@@ -600,10 +600,13 @@ impl<O: ForestObligation> ObligationForest<O> {
600600
fn compress(&mut self, do_completed: DoCompleted) -> Option<Vec<O>> {
601601
let orig_nodes_len = self.nodes.len();
602602
let mut node_rewrites: Vec<_> = self.node_rewrites.replace(vec![]);
603+
debug_assert!(node_rewrites.is_empty());
603604
node_rewrites.extend(0..orig_nodes_len);
604605
let mut dead_nodes = 0;
606+
let mut removed_done_obligations: Vec<O> = vec![];
605607

606-
// Now move all popped nodes to the end. Try to keep the order.
608+
// Now move all Done/Error nodes to the end, preserving the order of
609+
// the Pending/Waiting nodes.
607610
//
608611
// LOOP INVARIANT:
609612
// self.nodes[0..index - dead_nodes] are the first remaining nodes
@@ -620,7 +623,7 @@ impl<O: ForestObligation> ObligationForest<O> {
620623
}
621624
NodeState::Done => {
622625
// This lookup can fail because the contents of
623-
// `self.active_cache` is not guaranteed to match those of
626+
// `self.active_cache` are not guaranteed to match those of
624627
// `self.nodes`. See the comment in `process_obligation`
625628
// for more details.
626629
if let Some((predicate, _)) =
@@ -630,6 +633,10 @@ impl<O: ForestObligation> ObligationForest<O> {
630633
} else {
631634
self.done_cache.insert(node.obligation.as_predicate().clone());
632635
}
636+
if do_completed == DoCompleted::Yes {
637+
// Extract the success stories.
638+
removed_done_obligations.push(node.obligation.clone());
639+
}
633640
node_rewrites[index] = orig_nodes_len;
634641
dead_nodes += 1;
635642
}
@@ -638,43 +645,28 @@ impl<O: ForestObligation> ObligationForest<O> {
638645
// tests must come up with a different type on every type error they
639646
// check against.
640647
self.active_cache.remove(node.obligation.as_predicate());
648+
self.insert_into_error_cache(index);
641649
node_rewrites[index] = orig_nodes_len;
642650
dead_nodes += 1;
643-
self.insert_into_error_cache(index);
644651
}
645652
NodeState::Success => unreachable!()
646653
}
647654
}
648655

649-
// No compression needed.
650-
if dead_nodes == 0 {
651-
node_rewrites.truncate(0);
652-
self.node_rewrites.replace(node_rewrites);
653-
return if do_completed == DoCompleted::Yes { Some(vec![]) } else { None };
654-
}
655-
656-
// Pop off all the nodes we killed and extract the success stories.
657-
let successful = if do_completed == DoCompleted::Yes {
658-
Some((0..dead_nodes)
659-
.map(|_| self.nodes.pop().unwrap())
660-
.flat_map(|node| {
661-
match node.state.get() {
662-
NodeState::Error => None,
663-
NodeState::Done => Some(node.obligation),
664-
_ => unreachable!()
665-
}
666-
})
667-
.collect())
668-
} else {
656+
if dead_nodes > 0 {
657+
// Remove the dead nodes and rewrite indices.
669658
self.nodes.truncate(orig_nodes_len - dead_nodes);
670-
None
671-
};
672-
self.apply_rewrites(&node_rewrites);
659+
self.apply_rewrites(&node_rewrites);
660+
}
673661

674662
node_rewrites.truncate(0);
675663
self.node_rewrites.replace(node_rewrites);
676664

677-
successful
665+
if do_completed == DoCompleted::Yes {
666+
Some(removed_done_obligations)
667+
} else {
668+
None
669+
}
678670
}
679671

680672
fn apply_rewrites(&mut self, node_rewrites: &[usize]) {

src/librustc_data_structures/obligation_forest/tests.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ fn push_pop() {
116116
_ => unreachable!(),
117117
}
118118
}, |_| {}), DoCompleted::Yes);
119-
assert_eq!(ok.unwrap(), vec!["A.3", "A.1", "A.3.i"]);
119+
let mut ok = ok.unwrap();
120+
ok.sort();
121+
assert_eq!(ok, vec!["A.1", "A.3", "A.3.i"]);
120122
assert_eq!(err,
121123
vec![Error {
122124
error: "A is for apple",
@@ -132,7 +134,9 @@ fn push_pop() {
132134
_ => panic!("unexpected obligation {:?}", obligation),
133135
}
134136
}, |_| {}), DoCompleted::Yes);
135-
assert_eq!(ok.unwrap(), vec!["D.2.i", "D.2"]);
137+
let mut ok = ok.unwrap();
138+
ok.sort();
139+
assert_eq!(ok, vec!["D.2", "D.2.i"]);
136140
assert_eq!(err,
137141
vec![Error {
138142
error: "D is for dumb",
@@ -172,7 +176,9 @@ fn success_in_grandchildren() {
172176
_ => unreachable!(),
173177
}
174178
}, |_| {}), DoCompleted::Yes);
175-
assert_eq!(ok.unwrap(), vec!["A.3", "A.1"]);
179+
let mut ok = ok.unwrap();
180+
ok.sort();
181+
assert_eq!(ok, vec!["A.1", "A.3"]);
176182
assert!(err.is_empty());
177183

178184
let Outcome { completed: ok, errors: err, .. } =
@@ -193,7 +199,9 @@ fn success_in_grandchildren() {
193199
_ => unreachable!(),
194200
}
195201
}, |_| {}), DoCompleted::Yes);
196-
assert_eq!(ok.unwrap(), vec!["A.2.i.a", "A.2.i", "A.2", "A"]);
202+
let mut ok = ok.unwrap();
203+
ok.sort();
204+
assert_eq!(ok, vec!["A", "A.2", "A.2.i", "A.2.i.a"]);
197205
assert!(err.is_empty());
198206

199207
let Outcome { completed: ok, errors: err, .. } =
@@ -261,7 +269,9 @@ fn diamond() {
261269
}
262270
}, |_|{}), DoCompleted::Yes);
263271
assert_eq!(d_count, 1);
264-
assert_eq!(ok.unwrap(), vec!["D", "A.2", "A.1", "A"]);
272+
let mut ok = ok.unwrap();
273+
ok.sort();
274+
assert_eq!(ok, vec!["A", "A.1", "A.2", "D"]);
265275
assert_eq!(err.len(), 0);
266276

267277
let errors = forest.to_errors(());
@@ -323,7 +333,9 @@ fn done_dependency() {
323333
_ => unreachable!(),
324334
}
325335
}, |_|{}), DoCompleted::Yes);
326-
assert_eq!(ok.unwrap(), vec!["C: Sized", "B: Sized", "A: Sized"]);
336+
let mut ok = ok.unwrap();
337+
ok.sort();
338+
assert_eq!(ok, vec!["A: Sized", "B: Sized", "C: Sized"]);
327339
assert_eq!(err.len(), 0);
328340

329341
forest.register_obligation("(A,B,C): Sized");
@@ -361,7 +373,9 @@ fn orphan() {
361373
_ => unreachable!(),
362374
}
363375
}, |_|{}), DoCompleted::Yes);
364-
assert_eq!(ok.unwrap(), vec!["C2", "C1"]);
376+
let mut ok = ok.unwrap();
377+
ok.sort();
378+
assert_eq!(ok, vec!["C1", "C2"]);
365379
assert_eq!(err.len(), 0);
366380

367381
let Outcome { completed: ok, errors: err, .. } =

0 commit comments

Comments
 (0)