]>
Commit | Line | Data |
---|---|---|
9fa01778 XL |
1 | use crate::borrow_check::location::{LocationIndex, LocationTable}; |
2 | use crate::dataflow::indexes::BorrowIndex; | |
94b46f34 XL |
3 | use polonius_engine::AllFacts as PoloniusAllFacts; |
4 | use polonius_engine::Atom; | |
8faf50e0 | 5 | use rustc::ty::{RegionVid, TyCtxt}; |
94b46f34 | 6 | use rustc_data_structures::indexed_vec::Idx; |
83c7162d XL |
7 | use std::error::Error; |
8 | use std::fmt::Debug; | |
9 | use std::fs::{self, File}; | |
10 | use std::io::Write; | |
11 | use std::path::Path; | |
12 | ||
94b46f34 | 13 | crate type AllFacts = PoloniusAllFacts<RegionVid, BorrowIndex, LocationIndex>; |
83c7162d | 14 | |
94b46f34 | 15 | crate trait AllFactsExt { |
9fa01778 | 16 | /// Returns `true` if there is a need to gather `AllFacts` given the |
8faf50e0 XL |
17 | /// current `-Z` flags. |
18 | fn enabled(tcx: TyCtxt<'_, '_, '_>) -> bool; | |
19 | ||
94b46f34 XL |
20 | fn write_to_dir( |
21 | &self, | |
22 | dir: impl AsRef<Path>, | |
23 | location_table: &LocationTable, | |
24 | ) -> Result<(), Box<dyn Error>>; | |
83c7162d XL |
25 | } |
26 | ||
94b46f34 | 27 | impl AllFactsExt for AllFacts { |
8faf50e0 XL |
28 | /// Return |
29 | fn enabled(tcx: TyCtxt<'_, '_, '_>) -> bool { | |
30 | tcx.sess.opts.debugging_opts.nll_facts | |
31 | || tcx.sess.opts.debugging_opts.polonius | |
32 | } | |
33 | ||
94b46f34 | 34 | fn write_to_dir( |
83c7162d XL |
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, | |
94b46f34 | 62 | invalidates, |
83c7162d XL |
63 | ]) |
64 | } | |
65 | Ok(()) | |
66 | } | |
67 | } | |
68 | ||
94b46f34 XL |
69 | impl Atom for BorrowIndex { |
70 | fn index(self) -> usize { | |
71 | Idx::index(self) | |
72 | } | |
73 | } | |
74 | ||
75 | impl From<usize> for BorrowIndex { | |
76 | fn from(i: usize) -> BorrowIndex { | |
77 | BorrowIndex::new(i) | |
78 | } | |
79 | } | |
80 | ||
81 | impl From<BorrowIndex> for usize { | |
82 | fn from(vid: BorrowIndex) -> usize { | |
83 | Idx::index(vid) | |
84 | } | |
85 | } | |
86 | ||
87 | impl Atom for LocationIndex { | |
88 | fn index(self) -> usize { | |
89 | Idx::index(self) | |
90 | } | |
91 | } | |
92 | ||
83c7162d XL |
93 | struct FactWriter<'w> { |
94 | location_table: &'w LocationTable, | |
95 | dir: &'w Path, | |
96 | } | |
97 | ||
98 | impl<'w> FactWriter<'w> { | |
99 | fn write_facts_to_path<T>( | |
100 | &self, | |
8faf50e0 | 101 | rows: &[T], |
83c7162d XL |
102 | file_name: &str, |
103 | ) -> Result<(), Box<dyn Error>> | |
104 | where | |
105 | T: FactRow, | |
106 | { | |
107 | let file = &self.dir.join(file_name); | |
108 | let mut file = File::create(file)?; | |
109 | for row in rows { | |
110 | row.write(&mut file, self.location_table)?; | |
111 | } | |
112 | Ok(()) | |
113 | } | |
114 | } | |
115 | ||
116 | trait FactRow { | |
117 | fn write( | |
118 | &self, | |
119 | out: &mut File, | |
120 | location_table: &LocationTable, | |
121 | ) -> Result<(), Box<dyn Error>>; | |
122 | } | |
123 | ||
124 | impl FactRow for RegionVid { | |
125 | fn write( | |
126 | &self, | |
127 | out: &mut File, | |
128 | location_table: &LocationTable, | |
129 | ) -> Result<(), Box<dyn Error>> { | |
130 | write_row(out, location_table, &[self]) | |
131 | } | |
132 | } | |
133 | ||
134 | impl<A, B> FactRow for (A, B) | |
135 | where | |
136 | A: FactCell, | |
137 | B: FactCell, | |
138 | { | |
139 | fn write( | |
140 | &self, | |
141 | out: &mut File, | |
142 | location_table: &LocationTable, | |
143 | ) -> Result<(), Box<dyn Error>> { | |
144 | write_row(out, location_table, &[&self.0, &self.1]) | |
145 | } | |
146 | } | |
147 | ||
148 | impl<A, B, C> FactRow for (A, B, C) | |
149 | where | |
150 | A: FactCell, | |
151 | B: FactCell, | |
152 | C: FactCell, | |
153 | { | |
154 | fn write( | |
155 | &self, | |
156 | out: &mut File, | |
157 | location_table: &LocationTable, | |
158 | ) -> Result<(), Box<dyn Error>> { | |
159 | write_row(out, location_table, &[&self.0, &self.1, &self.2]) | |
160 | } | |
161 | } | |
162 | ||
163 | impl<A, B, C, D> FactRow for (A, B, C, D) | |
164 | where | |
165 | A: FactCell, | |
166 | B: FactCell, | |
167 | C: FactCell, | |
168 | D: FactCell, | |
169 | { | |
170 | fn write( | |
171 | &self, | |
172 | out: &mut File, | |
173 | location_table: &LocationTable, | |
174 | ) -> Result<(), Box<dyn Error>> { | |
175 | write_row(out, location_table, &[&self.0, &self.1, &self.2, &self.3]) | |
176 | } | |
177 | } | |
178 | ||
179 | fn write_row( | |
180 | out: &mut dyn Write, | |
181 | location_table: &LocationTable, | |
182 | columns: &[&dyn FactCell], | |
183 | ) -> Result<(), Box<dyn Error>> { | |
184 | for (index, c) in columns.iter().enumerate() { | |
185 | let tail = if index == columns.len() - 1 { | |
186 | "\n" | |
187 | } else { | |
188 | "\t" | |
189 | }; | |
190 | write!(out, "{:?}{}", c.to_string(location_table), tail)?; | |
191 | } | |
192 | Ok(()) | |
193 | } | |
194 | ||
195 | trait FactCell { | |
196 | fn to_string(&self, location_table: &LocationTable) -> String; | |
197 | } | |
198 | ||
199 | impl<A: Debug> FactCell for A { | |
200 | default fn to_string(&self, _location_table: &LocationTable) -> String { | |
201 | format!("{:?}", self) | |
202 | } | |
203 | } | |
204 | ||
205 | impl FactCell for LocationIndex { | |
206 | fn to_string(&self, location_table: &LocationTable) -> String { | |
207 | format!("{:?}", location_table.to_location(*self)) | |
208 | } | |
209 | } |