Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encode constraints that hold at all points as logical edges in location-sensitive polonius #135290

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
63 changes: 27 additions & 36 deletions compiler/rustc_borrowck/src/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,17 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
let sccs = self.regioncx.constraint_sccs();
let universal_regions = self.regioncx.universal_regions();

// The loop below was useful for the location-insensitive analysis but shouldn't be
// impactful in the location-sensitive case. It seems that it does, however, as without it a
// handful of tests fail. That likely means some liveness or outlives data related to choice
// regions is missing
// FIXME: investigate the impact of loans traversing applied member constraints and why some
// tests fail otherwise.
//
// We first handle the cases where the loan doesn't go out of scope, depending on the
// issuing region's successors.
for successor in graph::depth_first_search(&self.regioncx.region_graph(), issuing_region) {
// 1. Via applied member constraints
// Via applied member constraints
//
// The issuing region can flow into the choice regions, and they are either:
// - placeholders or free regions themselves,
Expand All @@ -346,14 +353,6 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
return;
}
}

// 2. Via regions that are live at all points: placeholders and free regions.
//
// If the issuing region outlives such a region, its loan escapes the function and
// cannot go out of scope. We can early return.
if self.regioncx.is_region_live_at_all_points(successor) {
return;
}
}

let first_block = loan_issued_at.block;
Expand Down Expand Up @@ -461,34 +460,26 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
regioncx: &RegionInferenceContext<'tcx>,
borrow_set: &'a BorrowSet<'tcx>,
) -> Self {
let mut borrows_out_of_scope_at_location =
calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set);

// The in-tree polonius analysis computes loans going out of scope using the set-of-loans
// model, and makes sure they're identical to the existing computation of the set-of-points
// model.
if tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
let mut polonius_prec = PoloniusOutOfScopePrecomputer::new(body, regioncx);
for (loan_idx, loan_data) in borrow_set.iter_enumerated() {
let issuing_region = loan_data.region;
let loan_issued_at = loan_data.reserve_location;

polonius_prec.precompute_loans_out_of_scope(
loan_idx,
issuing_region,
loan_issued_at,
);
}

assert_eq!(
borrows_out_of_scope_at_location, polonius_prec.loans_out_of_scope_at_location,
"polonius loan scopes differ from NLL borrow scopes, for body {:?}",
body.span,
);

borrows_out_of_scope_at_location = polonius_prec.loans_out_of_scope_at_location;
}
let borrows_out_of_scope_at_location =
if !tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set)
} else {
// The in-tree polonius analysis computes loans going out of scope using the
// set-of-loans model.
let mut polonius_prec = PoloniusOutOfScopePrecomputer::new(body, regioncx);
for (loan_idx, loan_data) in borrow_set.iter_enumerated() {
let issuing_region = loan_data.region;
let loan_issued_at = loan_data.reserve_location;

polonius_prec.precompute_loans_out_of_scope(
loan_idx,
issuing_region,
loan_issued_at,
);
}

polonius_prec.loans_out_of_scope_at_location
};
Borrows { tcx, body, borrow_set, borrows_out_of_scope_at_location }
}

Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_borrowck/src/nll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
constraints,
universal_region_relations,
opaque_type_values,
mut polonius_context,
polonius_context,
} = type_check::type_check(
infcx,
body,
Expand Down Expand Up @@ -142,10 +142,10 @@ pub(crate) fn compute_regions<'a, 'tcx>(
location_map,
);

// If requested for `-Zpolonius=next`, convert NLL constraints to localized outlives
// constraints.
let localized_outlives_constraints = polonius_context.as_mut().map(|polonius_context| {
polonius_context.create_localized_constraints(infcx.tcx, &regioncx, body)
// If requested for `-Zpolonius=next`, convert NLL constraints to localized outlives constraints
// and use them to compute loan liveness.
let localized_outlives_constraints = polonius_context.as_ref().map(|polonius_context| {
polonius_context.compute_loan_liveness(infcx.tcx, &mut regioncx, body, borrow_set)
});

// If requested: dump NLL facts, and run legacy polonius analysis.
Expand Down
Loading
Loading