Skip to content

Commit 207b712

Browse files
committed
Auto merge of rust-lang#139965 - amandasystems:marginally-improved-scc-annotations, r=<try>
Decouple SCC annotations from SCCs This rewires SCC annotations to have them be a separate, visitor-type data structure. It was broken out of rust-lang#130227, which needed them to be able to remove unused annotations after computation without recomputing the SCCs themselves. As a drive-by it also removes some redundant code from the hot loop in SCC construction for a performance improvement. r? lcnr
2 parents 15c4cce + ae763d6 commit 207b712

File tree

4 files changed

+226
-157
lines changed

4 files changed

+226
-157
lines changed

compiler/rustc_borrowck/src/constraints/mod.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_middle::ty::{RegionVid, TyCtxt, VarianceDiagInfo};
77
use rustc_span::Span;
88
use tracing::{debug, instrument};
99

10-
use crate::region_infer::{ConstraintSccs, RegionDefinition, RegionTracker};
10+
use crate::region_infer::{AnnotatedSccs, ConstraintSccs, RegionDefinition, SccAnnotations};
1111
use crate::type_check::Locations;
1212
use crate::universal_regions::UniversalRegions;
1313

@@ -61,12 +61,14 @@ impl<'tcx> OutlivesConstraintSet<'tcx> {
6161
&self,
6262
static_region: RegionVid,
6363
definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
64-
) -> ConstraintSccs {
64+
) -> AnnotatedSccs {
6565
let constraint_graph = self.graph(definitions.len());
6666
let region_graph = &constraint_graph.region_graph(self, static_region);
67-
ConstraintSccs::new_with_annotation(&region_graph, |r| {
68-
RegionTracker::new(r, &definitions[r])
69-
})
67+
let mut annotation_visitor = SccAnnotations::new(definitions);
68+
(
69+
ConstraintSccs::new_with_annotation(&region_graph, &mut annotation_visitor),
70+
annotation_visitor.scc_to_annotation,
71+
)
7072
}
7173

7274
/// This method handles Universe errors by rewriting the constraint
@@ -108,9 +110,9 @@ impl<'tcx> OutlivesConstraintSet<'tcx> {
108110
&mut self,
109111
universal_regions: &UniversalRegions<'tcx>,
110112
definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
111-
) -> ConstraintSccs {
113+
) -> AnnotatedSccs {
112114
let fr_static = universal_regions.fr_static;
113-
let sccs = self.compute_sccs(fr_static, definitions);
115+
let (sccs, annotations) = self.compute_sccs(fr_static, definitions);
114116

115117
// Changed to `true` if we added any constraints to `self` and need to
116118
// recompute SCCs.
@@ -124,7 +126,7 @@ impl<'tcx> OutlivesConstraintSet<'tcx> {
124126
continue;
125127
}
126128

127-
let annotation = sccs.annotation(scc);
129+
let annotation = annotations[scc];
128130

129131
// If this SCC participates in a universe violation,
130132
// e.g. if it reaches a region with a universe smaller than
@@ -154,7 +156,7 @@ impl<'tcx> OutlivesConstraintSet<'tcx> {
154156
self.compute_sccs(fr_static, definitions)
155157
} else {
156158
// If we didn't add any back-edges; no more work needs doing
157-
sccs
159+
(sccs, annotations)
158160
}
159161
}
160162
}

compiler/rustc_borrowck/src/region_infer/mod.rs

+43-10
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,13 @@ mod reverse_sccs;
4747

4848
pub(crate) mod values;
4949

50-
pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex, RegionTracker>;
50+
pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex>;
51+
pub(crate) type AnnotatedSccs = (ConstraintSccs, IndexVec<ConstraintSccIndex, RegionTracker>);
5152

5253
/// An annotation for region graph SCCs that tracks
53-
/// the values of its elements.
54+
/// the values of its elements. This annotates a single SCC.
5455
#[derive(Copy, Debug, Clone)]
55-
pub struct RegionTracker {
56+
pub(crate) struct RegionTracker {
5657
/// The largest universe of a placeholder reached from this SCC.
5758
/// This includes placeholders within this SCC.
5859
max_placeholder_universe_reached: UniverseIndex,
@@ -97,6 +98,31 @@ impl scc::Annotation for RegionTracker {
9798
}
9899
}
99100

101+
/// A Visitor for SCC annotation construction.
102+
pub(crate) struct SccAnnotations<'d, 'tcx, A: scc::Annotation> {
103+
pub(crate) scc_to_annotation: IndexVec<ConstraintSccIndex, A>,
104+
definitions: &'d IndexVec<RegionVid, RegionDefinition<'tcx>>,
105+
}
106+
107+
impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> {
108+
pub(crate) fn new(definitions: &'d IndexVec<RegionVid, RegionDefinition<'tcx>>) -> Self {
109+
Self { scc_to_annotation: IndexVec::new(), definitions }
110+
}
111+
}
112+
113+
impl scc::Annotations<RegionVid, ConstraintSccIndex, RegionTracker>
114+
for SccAnnotations<'_, '_, RegionTracker>
115+
{
116+
fn new(&self, element: RegionVid) -> RegionTracker {
117+
RegionTracker::new(element, &self.definitions[element])
118+
}
119+
120+
fn annotate_scc(&mut self, scc: ConstraintSccIndex, annotation: RegionTracker) {
121+
let idx = self.scc_to_annotation.push(annotation);
122+
assert!(idx == scc);
123+
}
124+
}
125+
100126
impl RegionTracker {
101127
pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
102128
let (representative_is_placeholder, representative_is_existential) = match definition.origin
@@ -166,6 +192,8 @@ pub struct RegionInferenceContext<'tcx> {
166192
/// compute the values of each region.
167193
constraint_sccs: ConstraintSccs,
168194

195+
scc_annotations: IndexVec<ConstraintSccIndex, RegionTracker>,
196+
169197
/// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` exists if
170198
/// `B: A`. This is used to compute the universal regions that are required
171199
/// to outlive a given SCC. Computed lazily.
@@ -446,7 +474,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
446474

447475
let definitions = create_definitions(infcx, &universal_regions);
448476

449-
let constraint_sccs =
477+
let (constraint_sccs, scc_annotations) =
450478
outlives_constraints.add_outlives_static(&universal_regions, &definitions);
451479
let constraints = Frozen::freeze(outlives_constraints);
452480
let constraint_graph = Frozen::freeze(constraints.graph(definitions.len()));
@@ -472,6 +500,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
472500
constraints,
473501
constraint_graph,
474502
constraint_sccs,
503+
scc_annotations,
475504
rev_scc_graph: None,
476505
member_constraints,
477506
member_constraints_applied: Vec::new(),
@@ -757,6 +786,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
757786
debug!(value = ?self.scc_values.region_value_str(scc_a));
758787
}
759788

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

799832
// If the member region lives in a higher universe, we currently choose
800833
// the most conservative option by leaving it unchanged.
801-
if !self.constraint_sccs().annotation(scc).min_universe().is_root() {
834+
if !self.scc_annotations()[scc].min_universe().is_root() {
802835
return;
803836
}
804837

@@ -874,8 +907,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
874907
/// in `scc_a`. Used during constraint propagation, and only once
875908
/// the value of `scc_b` has been computed.
876909
fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccIndex) -> bool {
877-
let a_annotation = self.constraint_sccs().annotation(scc_a);
878-
let b_annotation = self.constraint_sccs().annotation(scc_b);
910+
let a_annotation = self.scc_annotations()[scc_a];
911+
let b_annotation = self.scc_annotations()[scc_b];
879912
let a_universe = a_annotation.min_universe();
880913

881914
// If scc_b's declared universe is a subset of
@@ -991,7 +1024,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
9911024
"lower_bound = {:?} r_scc={:?} universe={:?}",
9921025
lower_bound,
9931026
r_scc,
994-
self.constraint_sccs.annotation(r_scc).min_universe()
1027+
self.scc_annotations()[r_scc].min_universe()
9951028
);
9961029
// If the type test requires that `T: 'a` where `'a` is a
9971030
// placeholder from another universe, that effectively requires
@@ -1472,7 +1505,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
14721505
/// The minimum universe of any variable reachable from this
14731506
/// SCC, inside or outside of it.
14741507
fn scc_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
1475-
self.constraint_sccs().annotation(scc).min_universe()
1508+
self.scc_annotations()[scc].min_universe()
14761509
}
14771510

14781511
/// Checks the final value for the free region `fr` to see if it
@@ -2219,7 +2252,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
22192252
/// they *must* be equal (though not having the same repr does not
22202253
/// mean they are unequal).
22212254
fn scc_representative(&self, scc: ConstraintSccIndex) -> RegionVid {
2222-
self.constraint_sccs.annotation(scc).representative
2255+
self.scc_annotations()[scc].representative
22232256
}
22242257

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

0 commit comments

Comments
 (0)