Skip to content

Commit 08a60ac

Browse files
committed
Calculate liveness for the same locals with and without -Zpolonius
This fixes some test differences and also avoids overflow in issue-38591.rs.
1 parent 22bc9e1 commit 08a60ac

17 files changed

+84
-501
lines changed

src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs

+4
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ impl LocalUseMap {
7070
appearances: IndexVec::new(),
7171
};
7272

73+
if live_locals.is_empty() {
74+
return local_use_map;
75+
}
76+
7377
let mut locals_with_use_data: IndexVec<Local, bool> =
7478
IndexVec::from_elem_n(false, body.local_decls.len());
7579
live_locals.iter().for_each(|&local| locals_with_use_data[local] = true);

src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs

+30-22
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,39 @@ pub(super) fn generate<'tcx>(
3636
) {
3737
debug!("liveness::generate");
3838

39-
let live_locals: Vec<Local> = if AllFacts::enabled(typeck.tcx()) {
40-
// If "dump facts from NLL analysis" was requested perform
41-
// the liveness analysis for all `Local`s. This case opens
42-
// the possibility of the variables being analyzed in `trace`
43-
// to be *any* `Local`, not just the "live" ones, so we can't
44-
// make any assumptions past this point as to the characteristics
45-
// of the `live_locals`.
46-
// FIXME: Review "live" terminology past this point, we should
47-
// not be naming the `Local`s as live.
48-
body.local_decls.indices().collect()
39+
let free_regions = regions_that_outlive_free_regions(
40+
typeck.infcx.num_region_vars(),
41+
&typeck.borrowck_context.universal_regions,
42+
&typeck.borrowck_context.constraints.outlives_constraints,
43+
);
44+
let live_locals = compute_live_locals(typeck.tcx(), &free_regions, body);
45+
let facts_enabled = AllFacts::enabled(typeck.tcx());
46+
47+
48+
let polonius_drop_used = if facts_enabled {
49+
let mut drop_used = Vec::new();
50+
polonius::populate_access_facts(
51+
typeck,
52+
body,
53+
location_table,
54+
move_data,
55+
&mut drop_used,
56+
);
57+
Some(drop_used)
4958
} else {
50-
let free_regions = {
51-
regions_that_outlive_free_regions(
52-
typeck.infcx.num_region_vars(),
53-
&typeck.borrowck_context.universal_regions,
54-
&typeck.borrowck_context.constraints.outlives_constraints,
55-
)
56-
};
57-
compute_live_locals(typeck.tcx(), &free_regions, body)
59+
None
5860
};
5961

60-
if !live_locals.is_empty() {
61-
trace::trace(typeck, body, elements, flow_inits, move_data, live_locals);
62-
63-
polonius::populate_access_facts(typeck, body, location_table, move_data);
62+
if !live_locals.is_empty() || facts_enabled {
63+
trace::trace(
64+
typeck,
65+
body,
66+
elements,
67+
flow_inits,
68+
move_data,
69+
live_locals,
70+
polonius_drop_used,
71+
);
6472
}
6573
}
6674

src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct UseFactsExtractor<'me> {
1616
var_defined: &'me mut VarPointRelations,
1717
var_used: &'me mut VarPointRelations,
1818
location_table: &'me LocationTable,
19-
var_drop_used: &'me mut VarPointRelations,
19+
var_drop_used: &'me mut Vec<(Local, Location)>,
2020
move_data: &'me MoveData<'me>,
2121
path_accessed_at: &'me mut MovePathPointRelations,
2222
}
@@ -39,7 +39,7 @@ impl UseFactsExtractor<'_> {
3939

4040
fn insert_drop_use(&mut self, local: Local, location: Location) {
4141
debug!("LivenessFactsExtractor::insert_drop_use()");
42-
self.var_drop_used.push((local, self.location_to_index(location)));
42+
self.var_drop_used.push((local, location));
4343
}
4444

4545
fn insert_path_access(&mut self, path: MovePathIndex, location: Location) {
@@ -100,19 +100,24 @@ pub(super) fn populate_access_facts(
100100
body: &Body<'tcx>,
101101
location_table: &LocationTable,
102102
move_data: &MoveData<'_>,
103+
drop_used: &mut Vec<(Local, Location)>,
103104
) {
104105
debug!("populate_var_liveness_facts()");
105106

106107
if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
107108
UseFactsExtractor {
108109
var_defined: &mut facts.var_defined,
109110
var_used: &mut facts.var_used,
110-
var_drop_used: &mut facts.var_drop_used,
111+
var_drop_used: drop_used,
111112
path_accessed_at: &mut facts.path_accessed_at,
112113
location_table,
113114
move_data,
114115
}
115116
.visit_body(body);
117+
118+
facts.var_drop_used.extend(drop_used.iter().map(|&(local, location)| {
119+
(local, location_table.mid_index(location))
120+
}));
116121
}
117122

118123
for (local, local_decl) in body.local_decls.iter_enumerated() {

src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs

+35-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc::traits::query::type_op::outlives::DropckOutlives;
1313
use rustc::traits::query::type_op::TypeOp;
1414
use rustc::ty::{Ty, TypeFoldable};
1515
use rustc_index::bit_set::HybridBitSet;
16-
use rustc_data_structures::fx::FxHashMap;
16+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1717
use std::rc::Rc;
1818

1919
/// This is the heart of the liveness computation. For each variable X
@@ -37,6 +37,7 @@ pub(super) fn trace(
3737
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
3838
move_data: &MoveData<'tcx>,
3939
live_locals: Vec<Local>,
40+
polonius_drop_used: Option<Vec<(Local, Location)>>,
4041
) {
4142
debug!("trace()");
4243

@@ -52,7 +53,13 @@ pub(super) fn trace(
5253
drop_data: FxHashMap::default(),
5354
};
5455

55-
LivenessResults::new(cx).compute_for_all_locals(live_locals);
56+
let mut results = LivenessResults::new(cx);
57+
58+
if let Some(drop_used) = polonius_drop_used {
59+
results.add_extra_drop_facts(drop_used, live_locals.iter().copied().collect())
60+
}
61+
62+
results.compute_for_all_locals(live_locals);
5663
}
5764

5865
/// Contextual state for the type-liveness generator.
@@ -145,6 +152,32 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
145152
}
146153
}
147154

155+
/// Add extra drop facts needed for Polonius.
156+
///
157+
/// Add facts for all locals with free regions, since regions may outlive
158+
/// the function body only at certain nodes in the CFG.
159+
fn add_extra_drop_facts(
160+
&mut self,
161+
drop_used: Vec<(Local, Location)>,
162+
live_locals: FxHashSet<Local>,
163+
) {
164+
let locations = HybridBitSet::new_empty(self.cx.elements.num_points());
165+
166+
for (local, location) in drop_used {
167+
if !live_locals.contains(&local) {
168+
let local_ty = self.cx.body.local_decls[local].ty;
169+
if local_ty.has_free_regions() {
170+
self.cx.add_drop_live_facts_for(
171+
local,
172+
local_ty,
173+
&[location],
174+
&locations,
175+
);
176+
}
177+
}
178+
}
179+
}
180+
148181
/// Clear the value of fields that are "per local variable".
149182
fn reset_local_state(&mut self) {
150183
self.defs.clear();

src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr

-16
This file was deleted.

src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr

-16
This file was deleted.

src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr

-59
This file was deleted.

src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr

-16
This file was deleted.

0 commit comments

Comments
 (0)