Skip to content

Commit 3de68e0

Browse files
committed
extract polonius move fact generation
1 parent eca2789 commit 3de68e0

File tree

2 files changed

+91
-85
lines changed

2 files changed

+91
-85
lines changed

compiler/rustc_borrowck/src/nll.rs

Lines changed: 7 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,25 @@
22
#![deny(rustc::diagnostic_outside_of_impl)]
33
//! The entry point of the NLL borrow checker.
44
5+
use polonius_engine::{Algorithm, Output};
56
use rustc_data_structures::fx::FxIndexMap;
67
use rustc_hir::def_id::LocalDefId;
78
use rustc_index::IndexSlice;
89
use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
9-
use rustc_middle::mir::{
10-
Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted,
11-
START_BLOCK,
12-
};
10+
use rustc_middle::mir::{Body, ClosureOutlivesSubject, ClosureRegionRequirements, Promoted};
1311
use rustc_middle::ty::print::with_no_trimmed_paths;
1412
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
13+
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
14+
use rustc_mir_dataflow::move_paths::MoveData;
15+
use rustc_mir_dataflow::ResultsCursor;
1516
use rustc_span::symbol::sym;
1617
use std::env;
1718
use std::io;
1819
use std::path::PathBuf;
1920
use std::rc::Rc;
2021
use std::str::FromStr;
2122

22-
use polonius_engine::{Algorithm, Output};
23-
24-
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
25-
use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
26-
use rustc_mir_dataflow::ResultsCursor;
23+
mod polonius;
2724

2825
use crate::{
2926
borrow_set::BorrowSet,
@@ -78,81 +75,6 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
7875
universal_regions
7976
}
8077

81-
// This function populates an AllFacts instance with base facts related to
82-
// MovePaths and needed for the move analysis.
83-
fn populate_polonius_move_facts(
84-
all_facts: &mut AllFacts,
85-
move_data: &MoveData<'_>,
86-
location_table: &LocationTable,
87-
body: &Body<'_>,
88-
) {
89-
all_facts
90-
.path_is_var
91-
.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l)));
92-
93-
for (child, move_path) in move_data.move_paths.iter_enumerated() {
94-
if let Some(parent) = move_path.parent {
95-
all_facts.child_path.push((child, parent));
96-
}
97-
}
98-
99-
let fn_entry_start =
100-
location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
101-
102-
// initialized_at
103-
for init in move_data.inits.iter() {
104-
match init.location {
105-
InitLocation::Statement(location) => {
106-
let block_data = &body[location.block];
107-
let is_terminator = location.statement_index == block_data.statements.len();
108-
109-
if is_terminator && init.kind == InitKind::NonPanicPathOnly {
110-
// We are at the terminator of an init that has a panic path,
111-
// and where the init should not happen on panic
112-
113-
for successor in block_data.terminator().successors() {
114-
if body[successor].is_cleanup {
115-
continue;
116-
}
117-
118-
// The initialization happened in (or rather, when arriving at)
119-
// the successors, but not in the unwind block.
120-
let first_statement = Location { block: successor, statement_index: 0 };
121-
all_facts
122-
.path_assigned_at_base
123-
.push((init.path, location_table.start_index(first_statement)));
124-
}
125-
} else {
126-
// In all other cases, the initialization just happens at the
127-
// midpoint, like any other effect.
128-
all_facts
129-
.path_assigned_at_base
130-
.push((init.path, location_table.mid_index(location)));
131-
}
132-
}
133-
// Arguments are initialized on function entry
134-
InitLocation::Argument(local) => {
135-
assert!(body.local_kind(local) == LocalKind::Arg);
136-
all_facts.path_assigned_at_base.push((init.path, fn_entry_start));
137-
}
138-
}
139-
}
140-
141-
for (local, path) in move_data.rev_lookup.iter_locals_enumerated() {
142-
if body.local_kind(local) != LocalKind::Arg {
143-
// Non-arguments start out deinitialised; we simulate this with an
144-
// initial move:
145-
all_facts.path_moved_at_base.push((path, fn_entry_start));
146-
}
147-
}
148-
149-
// moved_out_at
150-
// deinitialisation is assumed to always happen!
151-
all_facts
152-
.path_moved_at_base
153-
.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
154-
}
155-
15678
/// Computes the (non-lexical) regions from the input MIR.
15779
///
15880
/// This may result in errors being reported.
@@ -206,7 +128,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
206128
if let Some(all_facts) = &mut all_facts {
207129
let _prof_timer = infcx.tcx.prof.generic_activity("polonius_fact_generation");
208130
all_facts.universal_region.extend(universal_regions.universal_regions());
209-
populate_polonius_move_facts(all_facts, move_data, location_table, body);
131+
polonius::emit_move_facts(all_facts, move_data, location_table, body);
210132

211133
// Emit universal regions facts, and their relations, for Polonius.
212134
//
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//! Functions dedicated to fact generation for the `-Zpolonius=legacy` datalog implementation.
2+
//!
3+
//! Will be removed in the future, once the in-tree `-Zpolonius=next` implementation reaches feature
4+
//! parity.
5+
6+
use rustc_middle::mir::{Body, LocalKind, Location, START_BLOCK};
7+
use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
8+
9+
use crate::facts::AllFacts;
10+
use crate::location::LocationTable;
11+
12+
/// Emit polonius facts needed for move/init analysis: moves and assignments.
13+
pub(crate) fn emit_move_facts(
14+
all_facts: &mut AllFacts,
15+
move_data: &MoveData<'_>,
16+
location_table: &LocationTable,
17+
body: &Body<'_>,
18+
) {
19+
all_facts
20+
.path_is_var
21+
.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l)));
22+
23+
for (child, move_path) in move_data.move_paths.iter_enumerated() {
24+
if let Some(parent) = move_path.parent {
25+
all_facts.child_path.push((child, parent));
26+
}
27+
}
28+
29+
let fn_entry_start =
30+
location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
31+
32+
// initialized_at
33+
for init in move_data.inits.iter() {
34+
match init.location {
35+
InitLocation::Statement(location) => {
36+
let block_data = &body[location.block];
37+
let is_terminator = location.statement_index == block_data.statements.len();
38+
39+
if is_terminator && init.kind == InitKind::NonPanicPathOnly {
40+
// We are at the terminator of an init that has a panic path,
41+
// and where the init should not happen on panic
42+
43+
for successor in block_data.terminator().successors() {
44+
if body[successor].is_cleanup {
45+
continue;
46+
}
47+
48+
// The initialization happened in (or rather, when arriving at)
49+
// the successors, but not in the unwind block.
50+
let first_statement = Location { block: successor, statement_index: 0 };
51+
all_facts
52+
.path_assigned_at_base
53+
.push((init.path, location_table.start_index(first_statement)));
54+
}
55+
} else {
56+
// In all other cases, the initialization just happens at the
57+
// midpoint, like any other effect.
58+
all_facts
59+
.path_assigned_at_base
60+
.push((init.path, location_table.mid_index(location)));
61+
}
62+
}
63+
// Arguments are initialized on function entry
64+
InitLocation::Argument(local) => {
65+
assert!(body.local_kind(local) == LocalKind::Arg);
66+
all_facts.path_assigned_at_base.push((init.path, fn_entry_start));
67+
}
68+
}
69+
}
70+
71+
for (local, path) in move_data.rev_lookup.iter_locals_enumerated() {
72+
if body.local_kind(local) != LocalKind::Arg {
73+
// Non-arguments start out deinitialised; we simulate this with an
74+
// initial move:
75+
all_facts.path_moved_at_base.push((path, fn_entry_start));
76+
}
77+
}
78+
79+
// moved_out_at
80+
// deinitialisation is assumed to always happen!
81+
all_facts
82+
.path_moved_at_base
83+
.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
84+
}

0 commit comments

Comments
 (0)