Skip to content

Commit b660ab9

Browse files
committed
Use associated types for SCC annotations, per code review suggestion
1 parent 6c934f6 commit b660ab9

File tree

3 files changed

+51
-52
lines changed

3 files changed

+51
-52
lines changed

compiler/rustc_borrowck/src/region_infer/mod.rs

+10-13
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,7 @@ impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> {
110110
}
111111
}
112112

113-
impl scc::Annotations<RegionVid, ConstraintSccIndex, RegionTracker>
114-
for SccAnnotations<'_, '_, RegionTracker>
115-
{
113+
impl scc::Annotations<RegionVid> for SccAnnotations<'_, '_, RegionTracker> {
116114
fn new(&self, element: RegionVid) -> RegionTracker {
117115
RegionTracker::new(element, &self.definitions[element])
118116
}
@@ -121,6 +119,9 @@ impl scc::Annotations<RegionVid, ConstraintSccIndex, RegionTracker>
121119
let idx = self.scc_to_annotation.push(annotation);
122120
assert!(idx == scc);
123121
}
122+
123+
type Ann = RegionTracker;
124+
type SccIdx = ConstraintSccIndex;
124125
}
125126

126127
impl RegionTracker {
@@ -786,10 +787,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
786787
debug!(value = ?self.scc_values.region_value_str(scc_a));
787788
}
788789

789-
fn scc_annotations(&self) -> &IndexVec<ConstraintSccIndex, RegionTracker> {
790-
&self.scc_annotations
791-
}
792-
793790
/// Invoked for each `R0 member of [R1..Rn]` constraint.
794791
///
795792
/// `scc` is the SCC containing R0, and `choice_regions` are the
@@ -831,7 +828,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
831828

832829
// If the member region lives in a higher universe, we currently choose
833830
// the most conservative option by leaving it unchanged.
834-
if !self.scc_annotations()[scc].min_universe().is_root() {
831+
if !self.scc_universe(scc).is_root() {
835832
return;
836833
}
837834

@@ -907,8 +904,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
907904
/// in `scc_a`. Used during constraint propagation, and only once
908905
/// the value of `scc_b` has been computed.
909906
fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccIndex) -> bool {
910-
let a_annotation = self.scc_annotations()[scc_a];
911-
let b_annotation = self.scc_annotations()[scc_b];
907+
let a_annotation = self.scc_annotations[scc_a];
908+
let b_annotation = self.scc_annotations[scc_b];
912909
let a_universe = a_annotation.min_universe();
913910

914911
// If scc_b's declared universe is a subset of
@@ -1024,7 +1021,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
10241021
"lower_bound = {:?} r_scc={:?} universe={:?}",
10251022
lower_bound,
10261023
r_scc,
1027-
self.scc_annotations()[r_scc].min_universe()
1024+
self.scc_universe(r_scc)
10281025
);
10291026
// If the type test requires that `T: 'a` where `'a` is a
10301027
// placeholder from another universe, that effectively requires
@@ -1505,7 +1502,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
15051502
/// The minimum universe of any variable reachable from this
15061503
/// SCC, inside or outside of it.
15071504
fn scc_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
1508-
self.scc_annotations()[scc].min_universe()
1505+
self.scc_annotations[scc].min_universe()
15091506
}
15101507

15111508
/// Checks the final value for the free region `fr` to see if it
@@ -2249,7 +2246,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
22492246
/// they *must* be equal (though not having the same repr does not
22502247
/// mean they are unequal).
22512248
fn scc_representative(&self, scc: ConstraintSccIndex) -> RegionVid {
2252-
self.scc_annotations()[scc].representative
2249+
self.scc_annotations[scc].representative
22532250
}
22542251

22552252
pub(crate) fn liveness_constraints(&self) -> &LivenessValues {

compiler/rustc_data_structures/src/graph/scc/mod.rs

+33-37
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
1111
use std::assert_matches::debug_assert_matches;
1212
use std::fmt::Debug;
13+
use std::marker::PhantomData;
1314
use std::ops::Range;
1415

1516
use rustc_index::{Idx, IndexSlice, IndexVec};
@@ -49,16 +50,21 @@ pub trait Annotation: Debug + Copy {
4950
}
5051

5152
/// An accumulator for annotations.
52-
pub trait Annotations<N: Idx, S: Idx, A: Annotation> {
53-
fn new(&self, element: N) -> A;
54-
fn annotate_scc(&mut self, scc: S, annotation: A);
53+
pub trait Annotations<N: Idx> {
54+
type Ann: Annotation;
55+
type SccIdx: Idx + Ord;
56+
57+
fn new(&self, element: N) -> Self::Ann;
58+
fn annotate_scc(&mut self, scc: Self::SccIdx, annotation: Self::Ann);
5559
}
5660

5761
/// The nil annotation accumulator, which does nothing.
58-
impl<N: Idx, S: Idx> Annotations<N, S, ()> for () {
59-
fn new(&self, _element: N) -> () {
60-
()
61-
}
62+
struct NoAnnotations<S: Idx + Ord>(PhantomData<S>);
63+
64+
impl<N: Idx, S: Idx + Ord> Annotations<N> for NoAnnotations<S> {
65+
type SccIdx = S;
66+
type Ann = ();
67+
fn new(&self, _element: N) {}
6268
fn annotate_scc(&mut self, _scc: S, _annotation: ()) {}
6369
}
6470

@@ -112,13 +118,13 @@ struct SccData<S: Idx> {
112118
impl<N: Idx, S: Idx + Ord> Sccs<N, S> {
113119
/// Compute SCCs without annotations.
114120
pub fn new(graph: &impl Successors<Node = N>) -> Self {
115-
Self::new_with_annotation(graph, &mut ())
121+
Self::new_with_annotation(graph, &mut NoAnnotations(PhantomData::<S>))
116122
}
117123

118124
/// Compute SCCs and annotate them with a user-supplied annotation
119-
pub fn new_with_annotation<A: Annotation, AA: Annotations<N, S, A>>(
125+
pub fn new_with_annotation<A: Annotations<N, SccIdx = S>>(
120126
graph: &impl Successors<Node = N>,
121-
annotations: &mut AA,
127+
annotations: &mut A,
122128
) -> Self {
123129
SccsConstruction::construct(graph, annotations)
124130
}
@@ -141,13 +147,7 @@ impl<N: Idx, S: Idx + Ord> Sccs<N, S> {
141147
pub fn all_sccs(&self) -> impl Iterator<Item = S> + 'static {
142148
(0..self.scc_data.len()).map(S::new)
143149
}
144-
/*
145-
/// Returns an iterator over the SCC annotations in the graph
146-
/// The order is the same as `all_sccs()`, dependency order.
147-
pub fn all_annotations(&self, annotations: &A) -> impl Iterator<Item = (S, A)> + use<'_, N, S, A> {
148-
self.all_sccs().map(|scc| (scc, self.annotation(scc)))
149-
}
150-
*/
150+
151151
/// Returns the SCC to which a node `r` belongs.
152152
pub fn scc(&self, r: N) -> S {
153153
self.scc_indices[r]
@@ -223,19 +223,17 @@ impl<S: Idx> SccData<S> {
223223
}
224224
}
225225

226-
struct SccsConstruction<'c, 'a, G, S, A, AA>
226+
struct SccsConstruction<'c, 'a, G, A>
227227
where
228228
G: DirectedGraph + Successors,
229-
S: Idx,
230-
A: Annotation,
231-
AA: Annotations<G::Node, S, A>,
229+
A: Annotations<G::Node>,
232230
{
233231
graph: &'c G,
234232

235233
/// The state of each node; used during walk to record the stack
236234
/// and after walk to record what cycle each node ended up being
237235
/// in.
238-
node_states: IndexVec<G::Node, NodeState<G::Node, S, A>>,
236+
node_states: IndexVec<G::Node, NodeState<G::Node, A::SccIdx, A::Ann>>,
239237

240238
/// The stack of nodes that we are visiting as part of the DFS.
241239
node_stack: Vec<G::Node>,
@@ -244,21 +242,21 @@ where
244242
/// position in this stack, and when we encounter a successor SCC,
245243
/// we push it on the stack. When we complete an SCC, we can pop
246244
/// everything off the stack that was found along the way.
247-
successors_stack: Vec<S>,
245+
successors_stack: Vec<A::SccIdx>,
248246

249247
/// A set used to strip duplicates. As we accumulate successors
250248
/// into the successors_stack, we sometimes get duplicate entries.
251249
/// We use this set to remove those -- we also keep its storage
252250
/// around between successors to amortize memory allocation costs.
253-
duplicate_set: FxHashSet<S>,
251+
duplicate_set: FxHashSet<A::SccIdx>,
254252

255-
scc_data: SccData<S>,
253+
scc_data: SccData<A::SccIdx>,
256254

257-
annotations: &'a mut AA,
255+
annotations: &'a mut A,
258256
}
259257

260258
#[derive(Copy, Clone, Debug)]
261-
enum NodeState<N, S, A> {
259+
enum NodeState<N, S, A: Annotation> {
262260
/// This node has not yet been visited as part of the DFS.
263261
///
264262
/// After SCC construction is complete, this state ought to be
@@ -289,7 +287,7 @@ enum NodeState<N, S, A> {
289287

290288
/// The state of walking a given node.
291289
#[derive(Copy, Clone, Debug)]
292-
enum WalkReturn<S, A> {
290+
enum WalkReturn<S, A: Annotation> {
293291
/// The walk found a cycle, but the entire component is not known to have
294292
/// been fully walked yet. We only know the minimum depth of this
295293
/// component in a minimum spanning tree of the graph. This component
@@ -302,12 +300,10 @@ enum WalkReturn<S, A> {
302300
Complete { scc_index: S, annotation: A },
303301
}
304302

305-
impl<'c, 'a, G, S, A, AA> SccsConstruction<'c, 'a, G, S, A, AA>
303+
impl<'c, 'a, G, A> SccsConstruction<'c, 'a, G, A>
306304
where
307305
G: DirectedGraph + Successors,
308-
S: Idx,
309-
A: Annotation,
310-
AA: Annotations<G::Node, S, A>,
306+
A: Annotations<G::Node>,
311307
{
312308
/// Identifies SCCs in the graph `G` and computes the resulting
313309
/// DAG. This uses a variant of [Tarjan's
@@ -323,7 +319,7 @@ where
323319
/// Additionally, we keep track of a current annotation of the SCC.
324320
///
325321
/// [wikipedia]: https://bit.ly/2EZIx84
326-
fn construct(graph: &'c G, annotations: &'a mut AA) -> Sccs<G::Node, S> {
322+
fn construct(graph: &'c G, annotations: &'a mut A) -> Sccs<G::Node, A::SccIdx> {
327323
let num_nodes = graph.num_nodes();
328324

329325
let mut this = Self {
@@ -349,7 +345,7 @@ where
349345
Sccs { scc_indices, scc_data: this.scc_data }
350346
}
351347

352-
fn start_walk_from(&mut self, node: G::Node) -> WalkReturn<S, A> {
348+
fn start_walk_from(&mut self, node: G::Node) -> WalkReturn<A::SccIdx, A::Ann> {
353349
self.inspect_node(node).unwrap_or_else(|| self.walk_unvisited_node(node))
354350
}
355351

@@ -365,7 +361,7 @@ where
365361
/// Otherwise, we are looking at a node that has already been
366362
/// completely visited. We therefore return `WalkReturn::Complete`
367363
/// with its associated SCC index.
368-
fn inspect_node(&mut self, node: G::Node) -> Option<WalkReturn<S, A>> {
364+
fn inspect_node(&mut self, node: G::Node) -> Option<WalkReturn<A::SccIdx, A::Ann>> {
369365
Some(match self.find_state(node) {
370366
NodeState::InCycle { scc_index, annotation } => {
371367
WalkReturn::Complete { scc_index, annotation }
@@ -388,7 +384,7 @@ where
388384
/// of `r2` (and updates `r` to reflect current result). This is
389385
/// basically the "find" part of a standard union-find algorithm
390386
/// (with path compression).
391-
fn find_state(&mut self, mut node: G::Node) -> NodeState<G::Node, S, A> {
387+
fn find_state(&mut self, mut node: G::Node) -> NodeState<G::Node, A::SccIdx, A::Ann> {
392388
// To avoid recursion we temporarily reuse the `parent` of each
393389
// InCycleWith link to encode a downwards link while compressing
394390
// the path. After we have found the root or deepest node being
@@ -511,7 +507,7 @@ where
511507
/// caller decide avoids mutual recursion between the two methods and allows
512508
/// us to maintain an allocated stack for nodes on the path between calls.
513509
#[instrument(skip(self, initial), level = "trace")]
514-
fn walk_unvisited_node(&mut self, initial: G::Node) -> WalkReturn<S, A> {
510+
fn walk_unvisited_node(&mut self, initial: G::Node) -> WalkReturn<A::SccIdx, A::Ann> {
515511
trace!("Walk unvisited node: {initial:?}");
516512
struct VisitingNodeFrame<G: DirectedGraph, Successors, A> {
517513
node: G::Node,

compiler/rustc_data_structures/src/graph/scc/tests.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ struct MaxReached(usize);
88
struct Maxes(IndexVec<usize, MaxReached>, fn(usize) -> usize);
99
type UsizeSccs = Sccs<usize, usize>;
1010

11-
impl Annotations<usize, usize, MaxReached> for Maxes {
11+
impl Annotations<usize> for Maxes {
1212
fn new(&self, element: usize) -> MaxReached {
1313
MaxReached(self.1(element))
1414
}
@@ -17,6 +17,9 @@ impl Annotations<usize, usize, MaxReached> for Maxes {
1717
let i = self.0.push(annotation);
1818
assert!(i == scc);
1919
}
20+
21+
type Ann = MaxReached;
22+
type SccIdx = usize;
2023
}
2124

2225
impl Maxes {
@@ -57,7 +60,7 @@ impl MinMaxes {
5760
}
5861
}
5962

60-
impl Annotations<usize, usize, MinMaxIn> for MinMaxes {
63+
impl Annotations<usize> for MinMaxes {
6164
fn new(&self, element: usize) -> MinMaxIn {
6265
self.1(element)
6366
}
@@ -66,6 +69,9 @@ impl Annotations<usize, usize, MinMaxIn> for MinMaxes {
6669
let i = self.0.push(annotation);
6770
assert!(i == scc);
6871
}
72+
73+
type Ann = MinMaxIn;
74+
type SccIdx = usize;
6975
}
7076

7177
impl Annotation for MinMaxIn {

0 commit comments

Comments
 (0)