Skip to content

Commit 7291153

Browse files
committed
Use associated types for SCC annotations, per code review suggestion
1 parent f294181 commit 7291153

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
@@ -108,9 +108,7 @@ impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> {
108108
}
109109
}
110110

111-
impl scc::Annotations<RegionVid, ConstraintSccIndex, RegionTracker>
112-
for SccAnnotations<'_, '_, RegionTracker>
113-
{
111+
impl scc::Annotations<RegionVid> for SccAnnotations<'_, '_, RegionTracker> {
114112
fn new(&self, element: RegionVid) -> RegionTracker {
115113
RegionTracker::new(element, &self.definitions[element])
116114
}
@@ -119,6 +117,9 @@ impl scc::Annotations<RegionVid, ConstraintSccIndex, RegionTracker>
119117
let idx = self.scc_to_annotation.push(annotation);
120118
assert!(idx == scc);
121119
}
120+
121+
type Ann = RegionTracker;
122+
type SccIdx = ConstraintSccIndex;
122123
}
123124

124125
impl RegionTracker {
@@ -781,10 +782,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
781782
debug!(value = ?self.scc_values.region_value_str(scc_a));
782783
}
783784

784-
fn scc_annotations(&self) -> &IndexVec<ConstraintSccIndex, RegionTracker> {
785-
&self.scc_annotations
786-
}
787-
788785
/// Invoked for each `R0 member of [R1..Rn]` constraint.
789786
///
790787
/// `scc` is the SCC containing R0, and `choice_regions` are the
@@ -826,7 +823,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
826823

827824
// If the member region lives in a higher universe, we currently choose
828825
// the most conservative option by leaving it unchanged.
829-
if !self.scc_annotations()[scc].min_universe().is_root() {
826+
if !self.scc_universe(scc).is_root() {
830827
return;
831828
}
832829

@@ -902,8 +899,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
902899
/// in `scc_a`. Used during constraint propagation, and only once
903900
/// the value of `scc_b` has been computed.
904901
fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccIndex) -> bool {
905-
let a_annotation = self.scc_annotations()[scc_a];
906-
let b_annotation = self.scc_annotations()[scc_b];
902+
let a_annotation = self.scc_annotations[scc_a];
903+
let b_annotation = self.scc_annotations[scc_b];
907904
let a_universe = a_annotation.min_universe();
908905

909906
// If scc_b's declared universe is a subset of
@@ -1019,7 +1016,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
10191016
"lower_bound = {:?} r_scc={:?} universe={:?}",
10201017
lower_bound,
10211018
r_scc,
1022-
self.scc_annotations()[r_scc].min_universe()
1019+
self.scc_universe(r_scc)
10231020
);
10241021
// If the type test requires that `T: 'a` where `'a` is a
10251022
// placeholder from another universe, that effectively requires
@@ -1500,7 +1497,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
15001497
/// The minimum universe of any variable reachable from this
15011498
/// SCC, inside or outside of it.
15021499
fn scc_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
1503-
self.scc_annotations()[scc].min_universe()
1500+
self.scc_annotations[scc].min_universe()
15041501
}
15051502

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

22532250
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)