Auto merge of #51133 - spastorino:make_borrowck_use_output, r=nikomatsakis
Make borrowck use polonius output
This commit is contained in:
commit
59c0f5913d
|
@ -557,6 +557,11 @@ dependencies = [
|
||||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "datafrog"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "debug_unreachable"
|
name = "debug_unreachable"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -1450,8 +1455,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polonius-engine"
|
name = "polonius-engine"
|
||||||
version = "0.1.1"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "precomputed-hash"
|
name = "precomputed-hash"
|
||||||
|
@ -1775,7 +1784,7 @@ dependencies = [
|
||||||
"jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"polonius-engine 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"polonius-engine 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"proc_macro 0.0.0",
|
"proc_macro 0.0.0",
|
||||||
"rustc_apfloat 0.0.0",
|
"rustc_apfloat 0.0.0",
|
||||||
"rustc_data_structures 0.0.0",
|
"rustc_data_structures 0.0.0",
|
||||||
|
@ -2159,10 +2168,11 @@ dependencies = [
|
||||||
"arena 0.0.0",
|
"arena 0.0.0",
|
||||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"graphviz 0.0.0",
|
"graphviz 0.0.0",
|
||||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"polonius-engine 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"polonius-engine 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc 0.0.0",
|
"rustc 0.0.0",
|
||||||
"rustc_apfloat 0.0.0",
|
"rustc_apfloat 0.0.0",
|
||||||
"rustc_data_structures 0.0.0",
|
"rustc_data_structures 0.0.0",
|
||||||
|
@ -3069,6 +3079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
|
"checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
|
||||||
"checksum curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf20bbe084f285f215eef2165feed70d6b75ba29cad24469badb853a4a287d0"
|
"checksum curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf20bbe084f285f215eef2165feed70d6b75ba29cad24469badb853a4a287d0"
|
||||||
"checksum curl-sys 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71c63a540a9ee4e15e56c3ed9b11a2f121239b9f6d7b7fe30f616e048148df9a"
|
"checksum curl-sys 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71c63a540a9ee4e15e56c3ed9b11a2f121239b9f6d7b7fe30f616e048148df9a"
|
||||||
|
"checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142"
|
||||||
"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
|
"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
|
||||||
"checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a"
|
"checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a"
|
||||||
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
|
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
|
||||||
|
@ -3162,7 +3173,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
|
"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
|
||||||
"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
|
"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
|
||||||
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
|
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
|
||||||
"checksum polonius-engine 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6201ffe79e3da53bd065fbec2a9b391e5a0dc21038b39bb300612ddc658eb7ee"
|
"checksum polonius-engine 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9385a6d8f8ff6fd7e48a803c6a77fb89cc929dc7e2af6bf972494bbc8ff8b9e4"
|
||||||
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||||
"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
|
"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
|
||||||
"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
|
"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
|
||||||
|
|
|
@ -16,7 +16,7 @@ graphviz = { path = "../libgraphviz" }
|
||||||
jobserver = "0.1"
|
jobserver = "0.1"
|
||||||
lazy_static = "1.0.0"
|
lazy_static = "1.0.0"
|
||||||
log = { version = "0.4", features = ["release_max_level_info", "std"] }
|
log = { version = "0.4", features = ["release_max_level_info", "std"] }
|
||||||
polonius-engine = "0.1.1"
|
polonius-engine = "0.4.0"
|
||||||
proc_macro = { path = "../libproc_macro" }
|
proc_macro = { path = "../libproc_macro" }
|
||||||
rustc_apfloat = { path = "../librustc_apfloat" }
|
rustc_apfloat = { path = "../librustc_apfloat" }
|
||||||
rustc_target = { path = "../librustc_target" }
|
rustc_target = { path = "../librustc_target" }
|
||||||
|
|
|
@ -1296,6 +1296,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||||
"dump facts from NLL analysis into side files"),
|
"dump facts from NLL analysis into side files"),
|
||||||
disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED],
|
disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"disable user provided type assertion in NLL"),
|
"disable user provided type assertion in NLL"),
|
||||||
|
polonius: bool = (false, parse_bool, [UNTRACKED],
|
||||||
|
"enable polonius-based borrow-checker"),
|
||||||
codegen_time_graph: bool = (false, parse_bool, [UNTRACKED],
|
codegen_time_graph: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"generate a graphical HTML report of time spent in codegen and LLVM"),
|
"generate a graphical HTML report of time spent in codegen and LLVM"),
|
||||||
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||||
|
|
|
@ -11,10 +11,11 @@ crate-type = ["dylib"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
arena = { path = "../libarena" }
|
arena = { path = "../libarena" }
|
||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
|
either = "1.5.0"
|
||||||
graphviz = { path = "../libgraphviz" }
|
graphviz = { path = "../libgraphviz" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
log_settings = "0.1.1"
|
log_settings = "0.1.1"
|
||||||
polonius-engine = "0.1.1"
|
polonius-engine = "0.4.0"
|
||||||
rustc = { path = "../librustc" }
|
rustc = { path = "../librustc" }
|
||||||
rustc_target = { path = "../librustc_target" }
|
rustc_target = { path = "../librustc_target" }
|
||||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||||
|
|
|
@ -14,15 +14,22 @@
|
||||||
//! but is not as ugly as it is right now.
|
//! but is not as ugly as it is right now.
|
||||||
|
|
||||||
use rustc::mir::{BasicBlock, Location};
|
use rustc::mir::{BasicBlock, Location};
|
||||||
|
use rustc::ty::RegionVid;
|
||||||
use rustc_data_structures::indexed_set::Iter;
|
use rustc_data_structures::indexed_set::Iter;
|
||||||
|
|
||||||
use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
|
use borrow_check::location::LocationIndex;
|
||||||
use dataflow::{EverInitializedPlaces, MovingOutStatements};
|
|
||||||
use dataflow::{Borrows};
|
use polonius_engine::Output;
|
||||||
use dataflow::{FlowAtLocation, FlowsAtLocation};
|
|
||||||
use dataflow::move_paths::HasMoveData;
|
|
||||||
use dataflow::move_paths::indexes::BorrowIndex;
|
use dataflow::move_paths::indexes::BorrowIndex;
|
||||||
|
use dataflow::move_paths::HasMoveData;
|
||||||
|
use dataflow::Borrows;
|
||||||
|
use dataflow::{EverInitializedPlaces, MovingOutStatements};
|
||||||
|
use dataflow::{FlowAtLocation, FlowsAtLocation};
|
||||||
|
use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
|
||||||
|
use either::Either;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
// (forced to be `pub` due to its use as an associated type below.)
|
// (forced to be `pub` due to its use as an associated type below.)
|
||||||
crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
|
crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
|
||||||
|
@ -31,6 +38,9 @@ crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
|
||||||
pub uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
|
pub uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
|
||||||
pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
|
pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
|
||||||
pub ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
|
pub ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
|
||||||
|
|
||||||
|
/// Polonius Output
|
||||||
|
pub polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
|
impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
|
||||||
|
@ -40,6 +50,7 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
|
||||||
uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
|
uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
|
||||||
move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
|
move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
|
||||||
ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
|
ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
|
||||||
|
polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Flows {
|
Flows {
|
||||||
borrows,
|
borrows,
|
||||||
|
@ -47,11 +58,19 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
|
||||||
uninits,
|
uninits,
|
||||||
move_outs,
|
move_outs,
|
||||||
ever_inits,
|
ever_inits,
|
||||||
|
polonius_output,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn borrows_in_scope(&self) -> impl Iterator<Item = BorrowIndex> + '_ {
|
crate fn borrows_in_scope(
|
||||||
self.borrows.iter_incoming()
|
&self,
|
||||||
|
location: LocationIndex,
|
||||||
|
) -> impl Iterator<Item = BorrowIndex> + '_ {
|
||||||
|
if let Some(ref polonius) = self.polonius_output {
|
||||||
|
Either::Left(polonius.errors_at(location).iter().cloned())
|
||||||
|
} else {
|
||||||
|
Either::Right(self.borrows.iter_incoming())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn with_outgoing_borrows(&self, op: impl FnOnce(Iter<BorrowIndex>)) {
|
crate fn with_outgoing_borrows(&self, op: impl FnOnce(Iter<BorrowIndex>)) {
|
||||||
|
@ -66,7 +85,7 @@ macro_rules! each_flow {
|
||||||
FlowAtLocation::$meth(&mut $this.uninits, $arg);
|
FlowAtLocation::$meth(&mut $this.uninits, $arg);
|
||||||
FlowAtLocation::$meth(&mut $this.move_outs, $arg);
|
FlowAtLocation::$meth(&mut $this.move_outs, $arg);
|
||||||
FlowAtLocation::$meth(&mut $this.ever_inits, $arg);
|
FlowAtLocation::$meth(&mut $this.ever_inits, $arg);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, 'gcx, 'tcx> FlowsAtLocation for Flows<'b, 'gcx, 'tcx> {
|
impl<'b, 'gcx, 'tcx> FlowsAtLocation for Flows<'b, 'gcx, 'tcx> {
|
||||||
|
@ -134,8 +153,7 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
|
||||||
s.push_str(", ");
|
s.push_str(", ");
|
||||||
};
|
};
|
||||||
saw_one = true;
|
saw_one = true;
|
||||||
let move_path =
|
let move_path = &self.uninits.operator().move_data().move_paths[mpi_uninit];
|
||||||
&self.uninits.operator().move_data().move_paths[mpi_uninit];
|
|
||||||
s.push_str(&format!("{}", move_path));
|
s.push_str(&format!("{}", move_path));
|
||||||
});
|
});
|
||||||
s.push_str("] ");
|
s.push_str("] ");
|
||||||
|
@ -159,8 +177,7 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
|
||||||
s.push_str(", ");
|
s.push_str(", ");
|
||||||
};
|
};
|
||||||
saw_one = true;
|
saw_one = true;
|
||||||
let ever_init =
|
let ever_init = &self.ever_inits.operator().move_data().inits[mpi_ever_init];
|
||||||
&self.ever_inits.operator().move_data().inits[mpi_ever_init];
|
|
||||||
s.push_str(&format!("{:?}", ever_init));
|
s.push_str(&format!("{:?}", ever_init));
|
||||||
});
|
});
|
||||||
s.push_str("]");
|
s.push_str("]");
|
||||||
|
|
|
@ -198,7 +198,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||||
let borrow_set = Rc::new(BorrowSet::build(tcx, mir));
|
let borrow_set = Rc::new(BorrowSet::build(tcx, mir));
|
||||||
|
|
||||||
// If we are in non-lexical mode, compute the non-lexical lifetimes.
|
// If we are in non-lexical mode, compute the non-lexical lifetimes.
|
||||||
let (regioncx, opt_closure_req) = nll::compute_regions(
|
let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions(
|
||||||
infcx,
|
infcx,
|
||||||
def_id,
|
def_id,
|
||||||
free_regions,
|
free_regions,
|
||||||
|
@ -259,6 +259,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||||
flow_uninits,
|
flow_uninits,
|
||||||
flow_move_outs,
|
flow_move_outs,
|
||||||
flow_ever_inits,
|
flow_ever_inits,
|
||||||
|
polonius_output,
|
||||||
);
|
);
|
||||||
|
|
||||||
mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
|
mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
|
||||||
|
@ -936,6 +937,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let mut error_reported = false;
|
let mut error_reported = false;
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let mir = self.mir;
|
let mir = self.mir;
|
||||||
|
let location_table = &LocationTable::new(mir);
|
||||||
|
let location = location_table.start_index(context.loc);
|
||||||
let borrow_set = self.borrow_set.clone();
|
let borrow_set = self.borrow_set.clone();
|
||||||
each_borrow_involving_path(
|
each_borrow_involving_path(
|
||||||
self,
|
self,
|
||||||
|
@ -944,7 +947,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
context,
|
context,
|
||||||
(sd, place_span.0),
|
(sd, place_span.0),
|
||||||
&borrow_set,
|
&borrow_set,
|
||||||
flow_state.borrows_in_scope(),
|
flow_state.borrows_in_scope(location),
|
||||||
|this, borrow_index, borrow|
|
|this, borrow_index, borrow|
|
||||||
match (rw, borrow.kind) {
|
match (rw, borrow.kind) {
|
||||||
// Obviously an activation is compatible with its own
|
// Obviously an activation is compatible with its own
|
||||||
|
|
|
@ -9,8 +9,9 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use borrow_check::borrow_set::BorrowSet;
|
use borrow_check::borrow_set::BorrowSet;
|
||||||
use borrow_check::location::LocationTable;
|
use borrow_check::location::{LocationIndex, LocationTable};
|
||||||
use borrow_check::nll::facts::AllFactsExt;
|
use borrow_check::nll::facts::AllFactsExt;
|
||||||
|
use dataflow::indexes::BorrowIndex;
|
||||||
use dataflow::move_paths::MoveData;
|
use dataflow::move_paths::MoveData;
|
||||||
use dataflow::FlowAtLocation;
|
use dataflow::FlowAtLocation;
|
||||||
use dataflow::MaybeInitializedPlaces;
|
use dataflow::MaybeInitializedPlaces;
|
||||||
|
@ -23,22 +24,24 @@ use std::collections::BTreeSet;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::rc::Rc;
|
||||||
use transform::MirSource;
|
use transform::MirSource;
|
||||||
use util::liveness::{LivenessResults, LocalSet};
|
use util::liveness::{LivenessResults, LocalSet};
|
||||||
|
|
||||||
use self::mir_util::PassWhere;
|
use self::mir_util::PassWhere;
|
||||||
|
use polonius_engine::{Algorithm, Output};
|
||||||
use util as mir_util;
|
use util as mir_util;
|
||||||
use util::pretty::{self, ALIGN};
|
use util::pretty::{self, ALIGN};
|
||||||
|
|
||||||
mod constraint_generation;
|
mod constraint_generation;
|
||||||
pub mod explain_borrow;
|
pub mod explain_borrow;
|
||||||
mod facts;
|
mod facts;
|
||||||
|
mod invalidation;
|
||||||
crate mod region_infer;
|
crate mod region_infer;
|
||||||
mod renumber;
|
mod renumber;
|
||||||
mod subtype_constraint_generation;
|
mod subtype_constraint_generation;
|
||||||
crate mod type_check;
|
crate mod type_check;
|
||||||
mod universal_regions;
|
mod universal_regions;
|
||||||
mod invalidation;
|
|
||||||
|
|
||||||
use self::facts::AllFacts;
|
use self::facts::AllFacts;
|
||||||
use self::region_infer::RegionInferenceContext;
|
use self::region_infer::RegionInferenceContext;
|
||||||
|
@ -83,6 +86,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
|
||||||
borrow_set: &BorrowSet<'tcx>,
|
borrow_set: &BorrowSet<'tcx>,
|
||||||
) -> (
|
) -> (
|
||||||
RegionInferenceContext<'tcx>,
|
RegionInferenceContext<'tcx>,
|
||||||
|
Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
|
||||||
Option<ClosureRegionRequirements<'gcx>>,
|
Option<ClosureRegionRequirements<'gcx>>,
|
||||||
) {
|
) {
|
||||||
// Run the MIR type-checker.
|
// Run the MIR type-checker.
|
||||||
|
@ -98,7 +102,9 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
|
||||||
move_data,
|
move_data,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut all_facts = if infcx.tcx.sess.opts.debugging_opts.nll_facts {
|
let mut all_facts = if infcx.tcx.sess.opts.debugging_opts.nll_facts
|
||||||
|
|| infcx.tcx.sess.opts.debugging_opts.polonius
|
||||||
|
{
|
||||||
Some(AllFacts::default())
|
Some(AllFacts::default())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -113,8 +119,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
|
||||||
// Create the region inference context, taking ownership of the region inference
|
// Create the region inference context, taking ownership of the region inference
|
||||||
// data that was contained in `infcx`.
|
// data that was contained in `infcx`.
|
||||||
let var_origins = infcx.take_region_var_origins();
|
let var_origins = infcx.take_region_var_origins();
|
||||||
let mut regioncx =
|
let mut regioncx = RegionInferenceContext::new(var_origins, universal_regions, mir);
|
||||||
RegionInferenceContext::new(var_origins, universal_regions, mir);
|
|
||||||
|
|
||||||
// Generate various constraints.
|
// Generate various constraints.
|
||||||
subtype_constraint_generation::generate(
|
subtype_constraint_generation::generate(
|
||||||
|
@ -138,15 +143,28 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
|
||||||
location_table,
|
location_table,
|
||||||
&mir,
|
&mir,
|
||||||
def_id,
|
def_id,
|
||||||
borrow_set
|
borrow_set,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Dump facts if requested.
|
// Dump facts if requested.
|
||||||
if let Some(all_facts) = all_facts {
|
let polonius_output = all_facts.and_then(|all_facts| {
|
||||||
let def_path = infcx.tcx.hir.def_path(def_id);
|
if infcx.tcx.sess.opts.debugging_opts.nll_facts {
|
||||||
let dir_path = PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate());
|
let def_path = infcx.tcx.hir.def_path(def_id);
|
||||||
all_facts.write_to_dir(dir_path, location_table).unwrap();
|
let dir_path =
|
||||||
}
|
PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate());
|
||||||
|
all_facts.write_to_dir(dir_path, location_table).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if infcx.tcx.sess.opts.debugging_opts.polonius {
|
||||||
|
Some(Rc::new(Output::compute(
|
||||||
|
&all_facts,
|
||||||
|
Algorithm::DatafrogOpt,
|
||||||
|
false,
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Solve the region constraints.
|
// Solve the region constraints.
|
||||||
let closure_region_requirements = regioncx.solve(infcx, &mir, def_id);
|
let closure_region_requirements = regioncx.solve(infcx, &mir, def_id);
|
||||||
|
@ -166,7 +184,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
|
||||||
// information
|
// information
|
||||||
dump_annotation(infcx, &mir, def_id, ®ioncx, &closure_region_requirements);
|
dump_annotation(infcx, &mir, def_id, ®ioncx, &closure_region_requirements);
|
||||||
|
|
||||||
(regioncx, closure_region_requirements)
|
(regioncx, polonius_output, closure_region_requirements)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump_mir_results<'a, 'gcx, 'tcx>(
|
fn dump_mir_results<'a, 'gcx, 'tcx>(
|
||||||
|
@ -181,7 +199,8 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let regular_liveness_per_location: FxHashMap<_, _> = mir.basic_blocks()
|
let regular_liveness_per_location: FxHashMap<_, _> = mir
|
||||||
|
.basic_blocks()
|
||||||
.indices()
|
.indices()
|
||||||
.flat_map(|bb| {
|
.flat_map(|bb| {
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
|
@ -194,7 +213,8 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let drop_liveness_per_location: FxHashMap<_, _> = mir.basic_blocks()
|
let drop_liveness_per_location: FxHashMap<_, _> = mir
|
||||||
|
.basic_blocks()
|
||||||
.indices()
|
.indices()
|
||||||
.flat_map(|bb| {
|
.flat_map(|bb| {
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
|
@ -207,47 +227,55 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
mir_util::dump_mir(infcx.tcx, None, "nll", &0, source, mir, |pass_where, out| {
|
mir_util::dump_mir(
|
||||||
match pass_where {
|
infcx.tcx,
|
||||||
// Before the CFG, dump out the values for each region variable.
|
None,
|
||||||
PassWhere::BeforeCFG => {
|
"nll",
|
||||||
regioncx.dump_mir(out)?;
|
&0,
|
||||||
|
source,
|
||||||
|
mir,
|
||||||
|
|pass_where, out| {
|
||||||
|
match pass_where {
|
||||||
|
// Before the CFG, dump out the values for each region variable.
|
||||||
|
PassWhere::BeforeCFG => {
|
||||||
|
regioncx.dump_mir(out)?;
|
||||||
|
|
||||||
if let Some(closure_region_requirements) = closure_region_requirements {
|
if let Some(closure_region_requirements) = closure_region_requirements {
|
||||||
writeln!(out, "|")?;
|
writeln!(out, "|")?;
|
||||||
writeln!(out, "| Free Region Constraints")?;
|
writeln!(out, "| Free Region Constraints")?;
|
||||||
for_each_region_constraint(closure_region_requirements, &mut |msg| {
|
for_each_region_constraint(closure_region_requirements, &mut |msg| {
|
||||||
writeln!(out, "| {}", msg)
|
writeln!(out, "| {}", msg)
|
||||||
})?;
|
})?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Before each basic block, dump out the values
|
// Before each basic block, dump out the values
|
||||||
// that are live on entry to the basic block.
|
// that are live on entry to the basic block.
|
||||||
PassWhere::BeforeBlock(bb) => {
|
PassWhere::BeforeBlock(bb) => {
|
||||||
let s = live_variable_set(&liveness.regular.ins[bb], &liveness.drop.ins[bb]);
|
let s = live_variable_set(&liveness.regular.ins[bb], &liveness.drop.ins[bb]);
|
||||||
writeln!(out, " | Live variables on entry to {:?}: {}", bb, s)?;
|
writeln!(out, " | Live variables on entry to {:?}: {}", bb, s)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
PassWhere::BeforeLocation(location) => {
|
PassWhere::BeforeLocation(location) => {
|
||||||
let s = live_variable_set(
|
let s = live_variable_set(
|
||||||
®ular_liveness_per_location[&location],
|
®ular_liveness_per_location[&location],
|
||||||
&drop_liveness_per_location[&location],
|
&drop_liveness_per_location[&location],
|
||||||
);
|
);
|
||||||
writeln!(
|
writeln!(
|
||||||
out,
|
out,
|
||||||
"{:ALIGN$} | Live variables on entry to {:?}: {}",
|
"{:ALIGN$} | Live variables on entry to {:?}: {}",
|
||||||
"",
|
"",
|
||||||
location,
|
location,
|
||||||
s,
|
s,
|
||||||
ALIGN = ALIGN
|
ALIGN = ALIGN
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
|
PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Also dump the inference graph constraints as a graphviz file.
|
// Also dump the inference graph constraints as a graphviz file.
|
||||||
let _: io::Result<()> = do catch {
|
let _: io::Result<()> = do catch {
|
||||||
|
@ -278,7 +306,8 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
|
||||||
// better.
|
// better.
|
||||||
|
|
||||||
if let Some(closure_region_requirements) = closure_region_requirements {
|
if let Some(closure_region_requirements) = closure_region_requirements {
|
||||||
let mut err = tcx.sess
|
let mut err = tcx
|
||||||
|
.sess
|
||||||
.diagnostic()
|
.diagnostic()
|
||||||
.span_note_diag(mir.span, "External requirements");
|
.span_note_diag(mir.span, "External requirements");
|
||||||
|
|
||||||
|
@ -298,7 +327,8 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
|
||||||
|
|
||||||
err.emit();
|
err.emit();
|
||||||
} else {
|
} else {
|
||||||
let mut err = tcx.sess
|
let mut err = tcx
|
||||||
|
.sess
|
||||||
.diagnostic()
|
.diagnostic()
|
||||||
.span_note_diag(mir.span, "No external requirements");
|
.span_note_diag(mir.span, "No external requirements");
|
||||||
regioncx.annotate(&mut err);
|
regioncx.annotate(&mut err);
|
||||||
|
@ -317,8 +347,7 @@ fn for_each_region_constraint(
|
||||||
};
|
};
|
||||||
with_msg(&format!(
|
with_msg(&format!(
|
||||||
"where {:?}: {:?}",
|
"where {:?}: {:?}",
|
||||||
subject,
|
subject, req.outlived_free_region,
|
||||||
req.outlived_free_region,
|
|
||||||
))?;
|
))?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -38,6 +38,7 @@ extern crate arena;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
|
extern crate either;
|
||||||
extern crate graphviz as dot;
|
extern crate graphviz as dot;
|
||||||
extern crate polonius_engine;
|
extern crate polonius_engine;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -73,6 +73,7 @@ static WHITELIST: &'static [Crate] = &[
|
||||||
Crate("crossbeam-deque"),
|
Crate("crossbeam-deque"),
|
||||||
Crate("crossbeam-epoch"),
|
Crate("crossbeam-epoch"),
|
||||||
Crate("crossbeam-utils"),
|
Crate("crossbeam-utils"),
|
||||||
|
Crate("datafrog"),
|
||||||
Crate("either"),
|
Crate("either"),
|
||||||
Crate("ena"),
|
Crate("ena"),
|
||||||
Crate("env_logger"),
|
Crate("env_logger"),
|
||||||
|
|
Loading…
Reference in New Issue