Skip to content

Commit a4744d6

Browse files
authored
Rollup merge of rust-lang#64749 - matthewjasper:liveness-opt, r=nikomatsakis
Fix most remaining Polonius test differences This fixes most of the Polonius test differences and also avoids overflow in issue-38591.rs. r? @nikomatsakis
2 parents 2daa404 + 2180c24 commit a4744d6

22 files changed

+142
-528
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/librustc_mir/borrow_check/nll/type_check/mod.rs

+41-23
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,17 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
276276

277277
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
278278
self.super_constant(constant, location);
279-
self.sanitize_type(constant, constant.literal.ty);
279+
let ty = self.sanitize_type(constant, constant.literal.ty);
280+
281+
self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
282+
let live_region_vid =
283+
self.cx.borrowck_context.universal_regions.to_region_vid(live_region);
284+
self.cx
285+
.borrowck_context
286+
.constraints
287+
.liveness_constraints
288+
.add_element(live_region_vid, location);
289+
});
280290

281291
if let Some(annotation_index) = constant.user_ty {
282292
if let Err(terr) = self.cx.relate_type_and_user_type(
@@ -528,56 +538,64 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
528538

529539
let parent_body = mem::replace(&mut self.body, promoted_body);
530540

541+
// Use new sets of constraints and closure bounds so that we can
542+
// modify their locations.
531543
let all_facts = &mut None;
532544
let mut constraints = Default::default();
533545
let mut closure_bounds = Default::default();
546+
let mut liveness_constraints = LivenessValues::new(
547+
Rc::new(RegionValueElements::new(promoted_body)),
548+
);
534549
// Don't try to add borrow_region facts for the promoted MIR
535-
mem::swap(self.cx.borrowck_context.all_facts, all_facts);
536550

537-
// Use a new sets of constraints and closure bounds so that we can
538-
// modify their locations.
539-
mem::swap(
540-
&mut self.cx.borrowck_context.constraints.outlives_constraints,
541-
&mut constraints
542-
);
543-
mem::swap(
544-
&mut self.cx.borrowck_context.constraints.closure_bounds_mapping,
545-
&mut closure_bounds
546-
);
551+
let mut swap_constraints = |this: &mut Self| {
552+
mem::swap(this.cx.borrowck_context.all_facts, all_facts);
553+
mem::swap(
554+
&mut this.cx.borrowck_context.constraints.outlives_constraints,
555+
&mut constraints
556+
);
557+
mem::swap(
558+
&mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
559+
&mut closure_bounds
560+
);
561+
mem::swap(
562+
&mut this.cx.borrowck_context.constraints.liveness_constraints,
563+
&mut liveness_constraints
564+
);
565+
};
566+
567+
swap_constraints(self);
547568

548569
self.visit_body(promoted_body);
549570

571+
550572
if !self.errors_reported {
551573
// if verifier failed, don't do further checks to avoid ICEs
552574
self.cx.typeck_mir(promoted_body);
553575
}
554576

555577
self.body = parent_body;
556578
// Merge the outlives constraints back in, at the given location.
557-
mem::swap(self.cx.borrowck_context.all_facts, all_facts);
558-
mem::swap(
559-
&mut self.cx.borrowck_context.constraints.outlives_constraints,
560-
&mut constraints
561-
);
562-
mem::swap(
563-
&mut self.cx.borrowck_context.constraints.closure_bounds_mapping,
564-
&mut closure_bounds
565-
);
579+
swap_constraints(self);
566580

567581
let locations = location.to_locations();
568582
for constraint in constraints.outlives().iter() {
569583
let mut constraint = *constraint;
570584
constraint.locations = locations;
571585
if let ConstraintCategory::Return
572-
| ConstraintCategory::UseAsConst
573-
| ConstraintCategory::UseAsStatic = constraint.category
586+
| ConstraintCategory::UseAsConst
587+
| ConstraintCategory::UseAsStatic = constraint.category
574588
{
575589
// "Returning" from a promoted is an assigment to a
576590
// temporary from the user's point of view.
577591
constraint.category = ConstraintCategory::Boring;
578592
}
579593
self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
580594
}
595+
for live_region in liveness_constraints.rows() {
596+
self.cx.borrowck_context.constraints.liveness_constraints
597+
.add_element(live_region, location);
598+
}
581599

582600
if !closure_bounds.is_empty() {
583601
let combined_bounds_mapping = closure_bounds

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)