1 use crate::borrow_check::location::{LocationIndex, LocationTable};
2 use crate::dataflow::indexes::BorrowIndex;
3 use polonius_engine::AllFacts as PoloniusAllFacts;
4 use polonius_engine::Atom;
6 use rustc::ty::{RegionVid, TyCtxt};
7 use rustc_data_structures::indexed_vec::Idx;
10 use std::fs::{self, File};
14 crate type AllFacts = PoloniusAllFacts<RegionVid, BorrowIndex, LocationIndex, Local>;
16 crate trait AllFactsExt {
17 /// Returns `true` if there is a need to gather `AllFacts` given the
18 /// current `-Z` flags.
19 fn enabled(tcx: TyCtxt<'_>) -> bool;
23 dir: impl AsRef<Path>,
24 location_table: &LocationTable,
25 ) -> Result<(), Box<dyn Error>>;
28 impl AllFactsExt for AllFacts {
30 fn enabled(tcx: TyCtxt<'_>) -> bool {
31 tcx.sess.opts.debugging_opts.nll_facts || tcx.sess.opts.debugging_opts.polonius
36 dir: impl AsRef<Path>,
37 location_table: &LocationTable,
38 ) -> Result<(), Box<dyn Error>> {
39 let dir: &Path = dir.as_ref();
40 fs::create_dir_all(dir)?;
41 let wr = FactWriter { location_table, dir };
42 macro_rules! write_facts_to_path {
43 ($wr:ident . write_facts_to_path($this:ident . [
47 $wr.write_facts_to_path(
49 &format!("{}.facts", stringify!($field))
54 write_facts_to_path! {
55 wr.write_facts_to_path(self.[
68 var_initialized_on_exit,
75 impl Atom for BorrowIndex {
76 fn index(self) -> usize {
81 impl Atom for LocationIndex {
82 fn index(self) -> usize {
87 struct FactWriter<'w> {
88 location_table: &'w LocationTable,
92 impl<'w> FactWriter<'w> {
93 fn write_facts_to_path<T>(&self, rows: &[T], file_name: &str) -> Result<(), Box<dyn Error>>
97 let file = &self.dir.join(file_name);
98 let mut file = File::create(file)?;
100 row.write(&mut file, self.location_table)?;
107 fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>>;
110 impl FactRow for RegionVid {
111 fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
112 write_row(out, location_table, &[self])
116 impl<A, B> FactRow for (A, B)
121 fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
122 write_row(out, location_table, &[&self.0, &self.1])
126 impl<A, B, C> FactRow for (A, B, C)
132 fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
133 write_row(out, location_table, &[&self.0, &self.1, &self.2])
137 impl<A, B, C, D> FactRow for (A, B, C, D)
144 fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
145 write_row(out, location_table, &[&self.0, &self.1, &self.2, &self.3])
151 location_table: &LocationTable,
152 columns: &[&dyn FactCell],
153 ) -> Result<(), Box<dyn Error>> {
154 for (index, c) in columns.iter().enumerate() {
155 let tail = if index == columns.len() - 1 { "\n" } else { "\t" };
156 write!(out, "{:?}{}", c.to_string(location_table), tail)?;
162 fn to_string(&self, location_table: &LocationTable) -> String;
165 impl<A: Debug> FactCell for A {
166 default fn to_string(&self, _location_table: &LocationTable) -> String {
167 format!("{:?}", self)
171 impl FactCell for LocationIndex {
172 fn to_string(&self, location_table: &LocationTable) -> String {
173 format!("{:?}", location_table.to_location(*self))