Skip to content

Commit fbe2418

Browse files
committed
Only annotate region graph SCCs with their representative for functions without placeholders
1 parent 07c353b commit fbe2418

File tree

3 files changed

+97
-43
lines changed

3 files changed

+97
-43
lines changed

compiler/rustc_borrowck/src/handle_placeholders.rs

Lines changed: 76 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,59 @@ use crate::type_check::{Locations, MirTypeckRegionConstraints};
2424
use crate::universal_regions::UniversalRegions;
2525
use crate::{BorrowckInferCtxt, NllRegionVariableOrigin};
2626

27+
pub(crate) trait RegionSccs {
28+
fn representative(&self, scc: ConstraintSccIndex) -> RegionVid;
29+
fn reachable_placeholders(&self, _scc: ConstraintSccIndex) -> Option<PlaceholderReachability> {
30+
None
31+
}
32+
/// The largest universe this SCC can name. It's the smallest
33+
/// largest nameable universe of any reachable region, or
34+
/// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)`
35+
fn max_nameable_universe(&self, _scc: ConstraintSccIndex) -> UniverseIndex {
36+
UniverseIndex::ROOT
37+
}
38+
fn max_placeholder_universe_reached(&self, _scc: ConstraintSccIndex) -> UniverseIndex {
39+
UniverseIndex::ROOT
40+
}
41+
}
42+
43+
impl RegionSccs for IndexVec<ConstraintSccIndex, RegionTracker> {
44+
fn representative(&self, scc: ConstraintSccIndex) -> RegionVid {
45+
self[scc].representative.rvid()
46+
}
47+
48+
fn reachable_placeholders(&self, scc: ConstraintSccIndex) -> Option<PlaceholderReachability> {
49+
self[scc].reachable_placeholders
50+
}
51+
52+
fn max_nameable_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
53+
// Note that this is stricter than it might need to be!
54+
self[scc].min_max_nameable_universe
55+
}
56+
57+
fn max_placeholder_universe_reached(&self, scc: ConstraintSccIndex) -> UniverseIndex {
58+
self[scc].reachable_placeholders.map(|p| p.max_universe.u).unwrap_or(UniverseIndex::ROOT)
59+
}
60+
}
61+
62+
impl RegionSccs for IndexVec<ConstraintSccIndex, Representative> {
63+
fn representative(&self, scc: ConstraintSccIndex) -> RegionVid {
64+
self[scc].rvid()
65+
}
66+
}
67+
68+
impl FromRegionDefinition for Representative {
69+
fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
70+
Representative::new(rvid, definition)
71+
}
72+
}
73+
2774
/// A set of outlives constraints after rewriting to remove
2875
/// higher-kinded constraints.
2976
pub(crate) struct LoweredConstraints<'tcx> {
3077
pub(crate) constraint_sccs: Sccs<RegionVid, ConstraintSccIndex>,
3178
pub(crate) definitions: Frozen<IndexVec<RegionVid, RegionDefinition<'tcx>>>,
32-
pub(crate) scc_annotations: IndexVec<ConstraintSccIndex, RegionTracker>,
79+
pub(crate) scc_annotations: Box<dyn RegionSccs>,
3380
pub(crate) outlives_constraints: Frozen<OutlivesConstraintSet<'tcx>>,
3481
pub(crate) type_tests: Vec<TypeTest<'tcx>>,
3582
pub(crate) liveness_constraints: LivenessValues,
@@ -42,23 +89,28 @@ impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> {
4289
}
4390
}
4491

92+
trait FromRegionDefinition {
93+
fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self;
94+
}
95+
4596
/// A Visitor for SCC annotation construction.
4697
pub(crate) struct SccAnnotations<'d, 'tcx, A: scc::Annotation> {
4798
pub(crate) scc_to_annotation: IndexVec<ConstraintSccIndex, A>,
4899
definitions: &'d IndexVec<RegionVid, RegionDefinition<'tcx>>,
49100
}
50-
51-
impl scc::Annotations<RegionVid> for SccAnnotations<'_, '_, RegionTracker> {
52-
fn new(&self, element: RegionVid) -> RegionTracker {
53-
RegionTracker::new(element, &self.definitions[element])
101+
impl<A: scc::Annotation + FromRegionDefinition> scc::Annotations<RegionVid>
102+
for SccAnnotations<'_, '_, A>
103+
{
104+
fn new(&self, element: RegionVid) -> A {
105+
A::new(element, &self.definitions[element])
54106
}
55107

56-
fn annotate_scc(&mut self, scc: ConstraintSccIndex, annotation: RegionTracker) {
108+
fn annotate_scc(&mut self, scc: ConstraintSccIndex, annotation: A) {
57109
let idx = self.scc_to_annotation.push(annotation);
58110
assert!(idx == scc);
59111
}
60112

61-
type Ann = RegionTracker;
113+
type Ann = A;
62114
type SccIdx = ConstraintSccIndex;
63115
}
64116

@@ -127,8 +179,8 @@ pub(crate) struct RegionTracker {
127179
pub(crate) representative: Representative,
128180
}
129181

130-
impl RegionTracker {
131-
pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
182+
impl FromRegionDefinition for RegionTracker {
183+
fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
132184
use NllRegionVariableOrigin::*;
133185

134186
let min_max_nameable_universe = definition.universe;
@@ -163,24 +215,12 @@ impl RegionTracker {
163215
},
164216
}
165217
}
166-
167-
/// The largest universe this SCC can name. It's the smallest
168-
/// largest nameable universe of any reachable region, or
169-
/// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)`
170-
pub(crate) fn max_nameable_universe(self) -> UniverseIndex {
171-
// Note that this is stricter than it might need to be!
172-
self.min_max_nameable_universe
173-
}
174-
175-
pub(crate) fn max_placeholder_universe_reached(self) -> UniverseIndex {
176-
self.reachable_placeholders.map(|p| p.max_universe.u).unwrap_or(UniverseIndex::ROOT)
177-
}
178218
}
179219

180220
impl scc::Annotation for RegionTracker {
181221
fn update_scc(&mut self, other: &Self) {
182222
trace!("{:?} << {:?}", self.representative, other.representative);
183-
self.representative = self.representative.min(other.representative);
223+
self.representative.update_scc(&other.representative);
184224
self.is_placeholder = self.is_placeholder.max(other.is_placeholder);
185225
self.update_reachable(other); // SCC membership implies reachability.
186226
}
@@ -291,26 +331,32 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
291331
)
292332
};
293333

294-
let mut scc_annotations = SccAnnotations::init(&definitions);
295-
let constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
296-
297-
// This code structure is a bit convoluted because it allows for a planned
298-
// future change where the early return here has a different type of annotation
299-
// that does much less work.
300334
if !has_placeholders {
301335
debug!("No placeholder regions found; skipping rewriting logic!");
302336

337+
// We skip the extra logic and only record representatives.
338+
let mut scc_annotations: SccAnnotations<'_, '_, Representative> =
339+
SccAnnotations::init(&definitions);
340+
let constraint_sccs = ConstraintSccs::new_with_annotation(
341+
&outlives_constraints
342+
.graph(definitions.len())
343+
.region_graph(&outlives_constraints, fr_static),
344+
&mut scc_annotations,
345+
);
346+
303347
return LoweredConstraints {
304348
type_tests,
305349
constraint_sccs,
306-
scc_annotations: scc_annotations.scc_to_annotation,
350+
scc_annotations: Box::new(scc_annotations.scc_to_annotation),
307351
definitions,
308352
outlives_constraints: Frozen::freeze(outlives_constraints),
309353
liveness_constraints,
310354
universe_causes,
311355
};
312356
}
313357
debug!("Placeholders present; activating placeholder handling logic!");
358+
let mut scc_annotations = SccAnnotations::init(&definitions);
359+
let constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
314360

315361
let added_constraints = rewrite_placeholder_outlives(
316362
&constraint_sccs,
@@ -338,7 +384,7 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
338384
LoweredConstraints {
339385
constraint_sccs,
340386
definitions,
341-
scc_annotations,
387+
scc_annotations: Box::new(scc_annotations),
342388
outlives_constraints: Frozen::freeze(outlives_constraints),
343389
type_tests,
344390
liveness_constraints,

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::rc::Rc;
33

44
use rustc_data_structures::frozen::Frozen;
55
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
6-
use rustc_data_structures::graph::scc::Sccs;
6+
use rustc_data_structures::graph::scc::{self, Sccs};
77
use rustc_errors::Diag;
88
use rustc_hir::def_id::CRATE_DEF_ID;
99
use rustc_index::IndexVec;
@@ -26,7 +26,7 @@ use crate::constraints::graph::NormalConstraintGraph;
2626
use crate::constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet};
2727
use crate::dataflow::BorrowIndex;
2828
use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo};
29-
use crate::handle_placeholders::{LoweredConstraints, RegionTracker};
29+
use crate::handle_placeholders::{LoweredConstraints, RegionSccs, RegionTracker};
3030
use crate::polonius::LiveLoans;
3131
use crate::polonius::legacy::PoloniusOutput;
3232
use crate::region_infer::values::{LivenessValues, RegionElement, RegionValues, ToElementIndex};
@@ -74,6 +74,14 @@ impl Representative {
7474
}
7575
}
7676

77+
impl scc::Annotation for Representative {
78+
fn update_scc(&mut self, other: &Self) {
79+
*self = (*self).min(*other);
80+
}
81+
82+
fn update_reachable(&mut self, _other: &Self) {}
83+
}
84+
7785
pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex>;
7886

7987
pub struct RegionInferenceContext<'tcx> {
@@ -102,7 +110,7 @@ pub struct RegionInferenceContext<'tcx> {
102110
/// compute the values of each region.
103111
constraint_sccs: ConstraintSccs,
104112

105-
scc_annotations: IndexVec<ConstraintSccIndex, RegionTracker>,
113+
scc_annotations: Box<dyn RegionSccs>,
106114

107115
/// Map universe indexes to information on why we created it.
108116
universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
@@ -499,9 +507,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
499507
scc_a: ConstraintSccIndex,
500508
scc_b: ConstraintSccIndex,
501509
) -> bool {
502-
self.scc_annotations[scc_a]
503-
.max_nameable_universe()
504-
.can_name(self.scc_annotations[scc_b].max_placeholder_universe_reached())
510+
self.scc_annotations
511+
.max_nameable_universe(scc_a)
512+
.can_name(self.scc_annotations.max_placeholder_universe_reached(scc_b))
505513
}
506514

507515
/// Once regions have been propagated, this method is used to see
@@ -613,7 +621,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
613621
//
614622
// It doesn't matter *what* universe because the promoted `T` will
615623
// always be in the root universe.
616-
if !self.scc_annotations[r_scc].max_placeholder_universe_reached().is_root() {
624+
if !self.scc_annotations.max_placeholder_universe_reached(r_scc).is_root() {
617625
debug!("encountered placeholder in higher universe, requiring 'static");
618626
let static_r = self.universal_regions().fr_static;
619627
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
@@ -1091,7 +1099,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
10911099

10921100
/// The largest universe of any region nameable from this SCC.
10931101
fn max_nameable_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
1094-
self.scc_annotations[scc].max_nameable_universe()
1102+
self.scc_annotations.max_nameable_universe(scc)
10951103
}
10961104

10971105
/// Checks the final value for the free region `fr` to see if it
@@ -1452,7 +1460,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
14521460
scc: ConstraintSccIndex,
14531461
) -> Option<ty::PlaceholderRegion> {
14541462
if let NllRegionVariableOrigin::Placeholder(p) =
1455-
self.definitions[self.scc_annotations[scc].representative.rvid()].origin
1463+
self.definitions[self.scc_annotations.representative(scc)].origin
14561464
{
14571465
Some(p)
14581466
} else {
@@ -1465,7 +1473,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
14651473
&self,
14661474
scc: ConstraintSccIndex,
14671475
) -> Option<ty::PlaceholderRegion> {
1468-
let ps = self.scc_annotations[scc].reachable_placeholders?;
1476+
let ps = self.scc_annotations.reachable_placeholders(scc)?;
14691477

14701478
if let NllRegionVariableOrigin::Placeholder(p) = self.definitions[ps.min_placeholder].origin
14711479
&& ps.min_placeholder == ps.max_placeholder
@@ -1775,7 +1783,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
17751783
/// they *must* be equal (though not having the same repr does not
17761784
/// mean they are unequal).
17771785
fn scc_representative(&self, scc: ConstraintSccIndex) -> RegionVid {
1778-
self.scc_annotations[scc].representative.rvid()
1786+
self.scc_annotations.representative(scc)
17791787
}
17801788

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

compiler/rustc_borrowck/src/region_infer/opaque_types/region_ctxt.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_mir_dataflow::points::DenseLocationMap;
99
use crate::BorrowckInferCtxt;
1010
use crate::constraints::ConstraintSccIndex;
1111
use crate::diagnostics::RegionErrors;
12-
use crate::handle_placeholders::{SccAnnotations, region_definitions};
12+
use crate::handle_placeholders::{RegionSccs, SccAnnotations, region_definitions};
1313
use crate::region_infer::reverse_sccs::ReverseSccGraph;
1414
use crate::region_infer::values::RegionValues;
1515
use crate::region_infer::{
@@ -110,7 +110,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
110110
&self,
111111
scc: ConstraintSccIndex,
112112
) -> UniverseIndex {
113-
self.scc_annotations[scc].max_placeholder_universe_reached()
113+
self.scc_annotations.max_placeholder_universe_reached(scc)
114114
}
115115

116116
pub(super) fn universal_regions(&self) -> &UniversalRegions<'tcx> {

0 commit comments

Comments
 (0)