Skip to content

Commit de7a830

Browse files
committed
traverse region graph instead of SCCs to compute polonius loan scopes
By using SCC for better performance, we also have to take into account SCCs whose representative is an existential region but also contains a placeholder. By only checking the representative, we may miss that the loan escapes the function. This can be fixed by picking a better representative, or removing placeholders from the main path. This is the simplest fix: forgo efficiency and traverse the region graph instead of the SCCs.
1 parent 5020f7c commit de7a830

File tree

2 files changed

+14
-13
lines changed

2 files changed

+14
-13
lines changed

Diff for: compiler/rustc_borrowck/src/dataflow.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -273,11 +273,10 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
273273
) {
274274
let sccs = self.regioncx.constraint_sccs();
275275
let universal_regions = self.regioncx.universal_regions();
276-
let issuing_region_scc = sccs.scc(issuing_region);
277276

278277
// We first handle the cases where the loan doesn't go out of scope, depending on the issuing
279278
// region's successors.
280-
for scc in sccs.depth_first_search(issuing_region_scc) {
279+
for successor in self.regioncx.region_graph().depth_first_search(issuing_region) {
281280
// 1. Via applied member constraints
282281
//
283282
// The issuing region can flow into the choice regions, and they are either:
@@ -290,6 +289,7 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
290289
// For additional insurance via fuzzing and crater, we verify that the constraint's min
291290
// choice indeed escapes the function. In the future, we could e.g. turn this check into
292291
// a debug assert and early return as an optimization.
292+
let scc = sccs.scc(successor);
293293
for constraint in self.regioncx.applied_member_constraints(scc) {
294294
if universal_regions.is_universal_region(constraint.min_choice) {
295295
return;
@@ -300,7 +300,7 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
300300
//
301301
// If the issuing region outlives such a region, its loan escapes the function and
302302
// cannot go out of scope. We can early return.
303-
if self.regioncx.scc_is_live_at_all_points(scc) {
303+
if self.regioncx.is_region_live_at_all_points(successor) {
304304
return;
305305
}
306306
}

Diff for: compiler/rustc_borrowck/src/region_infer/mod.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,10 @@ use rustc_middle::traits::ObligationCauseCode;
2222
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
2323
use rustc_span::Span;
2424

25+
use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph};
2526
use crate::dataflow::BorrowIndex;
2627
use crate::{
27-
constraints::{
28-
graph::NormalConstraintGraph, ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
29-
},
28+
constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet},
3029
diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo},
3130
member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
3231
nll::PoloniusOutput,
@@ -2293,19 +2292,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
22932292
self.constraint_sccs.as_ref()
22942293
}
22952294

2296-
/// Returns whether the given SCC is live at all points: whether the representative is a
2295+
/// Access to the region graph, built from the outlives constraints.
2296+
pub(crate) fn region_graph(&self) -> RegionGraph<'_, 'tcx, graph::Normal> {
2297+
self.constraint_graph.region_graph(&self.constraints, self.universal_regions.fr_static)
2298+
}
2299+
2300+
/// Returns whether the given region is considered live at all points: whether it is a
22972301
/// placeholder or a free region.
2298-
pub(crate) fn scc_is_live_at_all_points(&self, scc: ConstraintSccIndex) -> bool {
2302+
pub(crate) fn is_region_live_at_all_points(&self, region: RegionVid) -> bool {
22992303
// FIXME: there must be a cleaner way to find this information. At least, when
23002304
// higher-ranked subtyping is abstracted away from the borrowck main path, we'll only
23012305
// need to check whether this is a universal region.
2302-
let representative = self.scc_representatives[scc];
2303-
let origin = self.var_infos[representative].origin;
2306+
let origin = self.region_definition(region).origin;
23042307
let live_at_all_points = matches!(
23052308
origin,
2306-
RegionVariableOrigin::Nll(
2307-
NllRegionVariableOrigin::Placeholder(_) | NllRegionVariableOrigin::FreeRegion
2308-
)
2309+
NllRegionVariableOrigin::Placeholder(_) | NllRegionVariableOrigin::FreeRegion
23092310
);
23102311
live_at_all_points
23112312
}

0 commit comments

Comments
 (0)