]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/nll/facts.rs
Rollup merge of #62806 - mati865:clippy, r=TimNN
[rust.git] / src / librustc_mir / borrow_check / nll / facts.rs
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;
5 use rustc::mir::Local;
6 use rustc::ty::{RegionVid, TyCtxt};
7 use rustc_data_structures::indexed_vec::Idx;
8 use std::error::Error;
9 use std::fmt::Debug;
10 use std::fs::{self, File};
11 use std::io::Write;
12 use std::path::Path;
13
14 crate type AllFacts = PoloniusAllFacts<RegionVid, BorrowIndex, LocationIndex, Local>;
15
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;
20
21     fn write_to_dir(
22         &self,
23         dir: impl AsRef<Path>,
24         location_table: &LocationTable,
25     ) -> Result<(), Box<dyn Error>>;
26 }
27
28 impl AllFactsExt for AllFacts {
29     /// Return
30     fn enabled(tcx: TyCtxt<'_>) -> bool {
31         tcx.sess.opts.debugging_opts.nll_facts || tcx.sess.opts.debugging_opts.polonius
32     }
33
34     fn write_to_dir(
35         &self,
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 . [
44                 $($field:ident,)*
45             ])) => {
46                 $(
47                     $wr.write_facts_to_path(
48                         &$this.$field,
49                         &format!("{}.facts", stringify!($field))
50                     )?;
51                 )*
52             }
53         }
54         write_facts_to_path! {
55             wr.write_facts_to_path(self.[
56                 borrow_region,
57                 universal_region,
58                 cfg_edge,
59                 killed,
60                 outlives,
61                 region_live_at,
62                 invalidates,
63                 var_used,
64                 var_defined,
65                 var_drop_used,
66                 var_uses_region,
67                 var_drops_region,
68                 var_initialized_on_exit,
69             ])
70         }
71         Ok(())
72     }
73 }
74
75 impl Atom for BorrowIndex {
76     fn index(self) -> usize {
77         Idx::index(self)
78     }
79 }
80
81 impl Atom for LocationIndex {
82     fn index(self) -> usize {
83         Idx::index(self)
84     }
85 }
86
87 struct FactWriter<'w> {
88     location_table: &'w LocationTable,
89     dir: &'w Path,
90 }
91
92 impl<'w> FactWriter<'w> {
93     fn write_facts_to_path<T>(&self, rows: &[T], file_name: &str) -> Result<(), Box<dyn Error>>
94     where
95         T: FactRow,
96     {
97         let file = &self.dir.join(file_name);
98         let mut file = File::create(file)?;
99         for row in rows {
100             row.write(&mut file, self.location_table)?;
101         }
102         Ok(())
103     }
104 }
105
106 trait FactRow {
107     fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>>;
108 }
109
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])
113     }
114 }
115
116 impl<A, B> FactRow for (A, B)
117 where
118     A: FactCell,
119     B: FactCell,
120 {
121     fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
122         write_row(out, location_table, &[&self.0, &self.1])
123     }
124 }
125
126 impl<A, B, C> FactRow for (A, B, C)
127 where
128     A: FactCell,
129     B: FactCell,
130     C: FactCell,
131 {
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])
134     }
135 }
136
137 impl<A, B, C, D> FactRow for (A, B, C, D)
138 where
139     A: FactCell,
140     B: FactCell,
141     C: FactCell,
142     D: FactCell,
143 {
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])
146     }
147 }
148
149 fn write_row(
150     out: &mut dyn Write,
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)?;
157     }
158     Ok(())
159 }
160
161 trait FactCell {
162     fn to_string(&self, location_table: &LocationTable) -> String;
163 }
164
165 impl<A: Debug> FactCell for A {
166     default fn to_string(&self, _location_table: &LocationTable) -> String {
167         format!("{:?}", self)
168     }
169 }
170
171 impl FactCell for LocationIndex {
172     fn to_string(&self, location_table: &LocationTable) -> String {
173         format!("{:?}", location_table.to_location(*self))
174     }
175 }