Skip to content

Commit 031b389

Browse files
committed
Auto merge of rust-lang#117593 - lqd:polonius-crater, r=<try>
crater: assert_eq!(NLL, location-insensitive polonius); Crater run to check `-Zpolonius=next`. Any differences in how NLLs and location-insensitive polonius compute scopes will cause an assert to trip and an ICE. Depends on rust-lang#117560 to fix the last known fuzzing example where there was such a difference. r? `@ghost`
2 parents a42d94e + 16af7f5 commit 031b389

File tree

6 files changed

+115
-14
lines changed

6 files changed

+115
-14
lines changed

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
}

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
}

compiler/rustc_session/src/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3414,13 +3414,13 @@ impl DumpMonoStatsFormat {
34143414
#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
34153415
pub enum Polonius {
34163416
/// The default value: disabled.
3417-
#[default]
34183417
Off,
34193418

34203419
/// Legacy version, using datalog and the `polonius-engine` crate. Historical value for `-Zpolonius`.
34213420
Legacy,
34223421

34233422
/// In-tree prototype, extending the NLL infrastructure.
3423+
#[default]
34243424
Next,
34253425
}
34263426

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
error[E0597]: `a` does not live long enough
2+
--> $DIR/location-insensitive-scopes-issue-117146.rs:10:18
3+
|
4+
LL | let b = |_| &a;
5+
| --- -^
6+
| | ||
7+
| | |borrowed value does not live long enough
8+
| | returning this value requires that `a` is borrowed for `'static`
9+
| value captured here
10+
...
11+
LL | }
12+
| - `a` dropped here while still borrowed
13+
|
14+
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
15+
--> $DIR/location-insensitive-scopes-issue-117146.rs:20:22
16+
|
17+
LL | fn bad<F: Fn(&()) -> &()>(_: F) {}
18+
| ^^^
19+
20+
error: implementation of `Fn` is not general enough
21+
--> $DIR/location-insensitive-scopes-issue-117146.rs:13:5
22+
|
23+
LL | bad(&b);
24+
| ^^^^^^^ implementation of `Fn` is not general enough
25+
|
26+
= note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`...
27+
= note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2`
28+
29+
error: implementation of `FnOnce` is not general enough
30+
--> $DIR/location-insensitive-scopes-issue-117146.rs:13:5
31+
|
32+
LL | bad(&b);
33+
| ^^^^^^^ implementation of `FnOnce` is not general enough
34+
|
35+
= note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
36+
= note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
37+
38+
error: aborting due to 3 previous errors
39+
40+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
error[E0597]: `a` does not live long enough
2+
--> $DIR/location-insensitive-scopes-issue-117146.rs:10:18
3+
|
4+
LL | let b = |_| &a;
5+
| --- -^
6+
| | ||
7+
| | |borrowed value does not live long enough
8+
| | returning this value requires that `a` is borrowed for `'static`
9+
| value captured here
10+
...
11+
LL | }
12+
| - `a` dropped here while still borrowed
13+
|
14+
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
15+
--> $DIR/location-insensitive-scopes-issue-117146.rs:20:22
16+
|
17+
LL | fn bad<F: Fn(&()) -> &()>(_: F) {}
18+
| ^^^
19+
20+
error: implementation of `Fn` is not general enough
21+
--> $DIR/location-insensitive-scopes-issue-117146.rs:13:5
22+
|
23+
LL | bad(&b);
24+
| ^^^^^^^ implementation of `Fn` is not general enough
25+
|
26+
= note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`...
27+
= note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2`
28+
29+
error: implementation of `FnOnce` is not general enough
30+
--> $DIR/location-insensitive-scopes-issue-117146.rs:13:5
31+
|
32+
LL | bad(&b);
33+
| ^^^^^^^ implementation of `FnOnce` is not general enough
34+
|
35+
= note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
36+
= note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
37+
38+
error: aborting due to 3 previous errors
39+
40+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// This is a non-regression test for issue #117146, where NLL and `-Zpolonius=next` computed
2+
// different loan scopes when a region flowed into an SCC whose representative was an existential
3+
// region.
4+
5+
// revisions: nll polonius
6+
// [polonius] compile-flags: -Zpolonius=next
7+
8+
fn main() {
9+
let a = ();
10+
let b = |_| &a;
11+
//[nll]~^ ERROR `a` does not live long enough
12+
//[polonius]~^^ ERROR `a` does not live long enough
13+
bad(&b);
14+
//[nll]~^ ERROR implementation of `Fn`
15+
//[nll]~| ERROR implementation of `FnOnce`
16+
//[polonius]~^^^ ERROR implementation of `Fn`
17+
//[polonius]~| ERROR implementation of `FnOnce`
18+
}
19+
20+
fn bad<F: Fn(&()) -> &()>(_: F) {}

0 commit comments

Comments
 (0)