1 use crate::borrow_check::location::{LocationIndex, LocationTable};
2 use crate::dataflow::indexes::{BorrowIndex, MovePathIndex};
3 use polonius_engine::AllFacts as PoloniusFacts;
4 use polonius_engine::Atom;
6 use rustc::ty::{RegionVid, TyCtxt};
7 use rustc_index::vec::Idx;
10 use std::fs::{self, File};
11 use std::io::{BufWriter, Write};
14 #[derive(Copy, Clone, Debug)]
15 crate struct RustcFacts;
17 impl polonius_engine::FactTypes for RustcFacts {
18 type Origin = RegionVid;
19 type Loan = BorrowIndex;
20 type Point = LocationIndex;
21 type Variable = Local;
22 type Path = MovePathIndex;
25 crate type AllFacts = PoloniusFacts<RustcFacts>;
27 crate trait AllFactsExt {
28 /// Returns `true` if there is a need to gather `AllFacts` given the
29 /// current `-Z` flags.
30 fn enabled(tcx: TyCtxt<'_>) -> bool;
34 dir: impl AsRef<Path>,
35 location_table: &LocationTable,
36 ) -> Result<(), Box<dyn Error>>;
39 impl AllFactsExt for AllFacts {
41 fn enabled(tcx: TyCtxt<'_>) -> bool {
42 tcx.sess.opts.debugging_opts.nll_facts || tcx.sess.opts.debugging_opts.polonius
47 dir: impl AsRef<Path>,
48 location_table: &LocationTable,
49 ) -> Result<(), Box<dyn Error>> {
50 let dir: &Path = dir.as_ref();
51 fs::create_dir_all(dir)?;
52 let wr = FactWriter { location_table, dir };
53 macro_rules! write_facts_to_path {
54 ($wr:ident . write_facts_to_path($this:ident . [
58 $wr.write_facts_to_path(
60 &format!("{}.facts", stringify!($field))
65 write_facts_to_path! {
66 wr.write_facts_to_path(self.[
91 impl Atom for BorrowIndex {
92 fn index(self) -> usize {
97 impl Atom for LocationIndex {
98 fn index(self) -> usize {
103 impl Atom for MovePathIndex {
104 fn index(self) -> usize {
109 struct FactWriter<'w> {
110 location_table: &'w LocationTable,
114 impl<'w> FactWriter<'w> {
115 fn write_facts_to_path<T>(&self, rows: &[T], file_name: &str) -> Result<(), Box<dyn Error>>
119 let file = &self.dir.join(file_name);
120 let mut file = BufWriter::new(File::create(file)?);
122 row.write(&mut file, self.location_table)?;
132 location_table: &LocationTable,
133 ) -> Result<(), Box<dyn Error>>;
136 impl FactRow for RegionVid {
140 location_table: &LocationTable,
141 ) -> Result<(), Box<dyn Error>> {
142 write_row(out, location_table, &[self])
146 impl<A, B> FactRow for (A, B)
154 location_table: &LocationTable,
155 ) -> Result<(), Box<dyn Error>> {
156 write_row(out, location_table, &[&self.0, &self.1])
160 impl<A, B, C> FactRow for (A, B, C)
169 location_table: &LocationTable,
170 ) -> Result<(), Box<dyn Error>> {
171 write_row(out, location_table, &[&self.0, &self.1, &self.2])
175 impl<A, B, C, D> FactRow for (A, B, C, D)
185 location_table: &LocationTable,
186 ) -> Result<(), Box<dyn Error>> {
187 write_row(out, location_table, &[&self.0, &self.1, &self.2, &self.3])
193 location_table: &LocationTable,
194 columns: &[&dyn FactCell],
195 ) -> Result<(), Box<dyn Error>> {
196 for (index, c) in columns.iter().enumerate() {
197 let tail = if index == columns.len() - 1 { "\n" } else { "\t" };
198 write!(out, "{:?}{}", c.to_string(location_table), tail)?;
204 fn to_string(&self, location_table: &LocationTable) -> String;
207 impl<A: Debug> FactCell for A {
208 default fn to_string(&self, _location_table: &LocationTable) -> String {
209 format!("{:?}", self)
213 impl FactCell for LocationIndex {
214 fn to_string(&self, location_table: &LocationTable) -> String {
215 format!("{:?}", location_table.to_location(*self))