]>
Commit | Line | Data |
---|---|---|
9fa01778 | 1 | use crate::borrow_check::location::{LocationIndex, LocationTable}; |
e1599b0c | 2 | use crate::dataflow::indexes::{BorrowIndex, MovePathIndex}; |
60c5eb7d | 3 | use polonius_engine::AllFacts as PoloniusFacts; |
94b46f34 | 4 | use polonius_engine::Atom; |
e74abb32 | 5 | use rustc_index::vec::Idx; |
ba9703b0 XL |
6 | use rustc_middle::mir::Local; |
7 | use rustc_middle::ty::{RegionVid, TyCtxt}; | |
83c7162d XL |
8 | use std::error::Error; |
9 | use std::fmt::Debug; | |
10 | use std::fs::{self, File}; | |
74b04a01 | 11 | use std::io::{BufWriter, Write}; |
83c7162d XL |
12 | use std::path::Path; |
13 | ||
60c5eb7d XL |
14 | #[derive(Copy, Clone, Debug)] |
15 | crate struct RustcFacts; | |
16 | ||
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; | |
23 | } | |
24 | ||
25 | crate type AllFacts = PoloniusFacts<RustcFacts>; | |
83c7162d | 26 | |
94b46f34 | 27 | crate trait AllFactsExt { |
9fa01778 | 28 | /// Returns `true` if there is a need to gather `AllFacts` given the |
8faf50e0 | 29 | /// current `-Z` flags. |
dc9dc135 | 30 | fn enabled(tcx: TyCtxt<'_>) -> bool; |
8faf50e0 | 31 | |
94b46f34 XL |
32 | fn write_to_dir( |
33 | &self, | |
34 | dir: impl AsRef<Path>, | |
35 | location_table: &LocationTable, | |
36 | ) -> Result<(), Box<dyn Error>>; | |
83c7162d XL |
37 | } |
38 | ||
94b46f34 | 39 | impl AllFactsExt for AllFacts { |
8faf50e0 | 40 | /// Return |
dc9dc135 | 41 | fn enabled(tcx: TyCtxt<'_>) -> bool { |
416331ca | 42 | tcx.sess.opts.debugging_opts.nll_facts || tcx.sess.opts.debugging_opts.polonius |
8faf50e0 XL |
43 | } |
44 | ||
94b46f34 | 45 | fn write_to_dir( |
83c7162d XL |
46 | &self, |
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 . [ | |
55 | $($field:ident,)* | |
56 | ])) => { | |
57 | $( | |
58 | $wr.write_facts_to_path( | |
59 | &$this.$field, | |
60 | &format!("{}.facts", stringify!($field)) | |
61 | )?; | |
62 | )* | |
63 | } | |
64 | } | |
65 | write_facts_to_path! { | |
66 | wr.write_facts_to_path(self.[ | |
67 | borrow_region, | |
68 | universal_region, | |
60c5eb7d | 69 | placeholder, |
83c7162d XL |
70 | cfg_edge, |
71 | killed, | |
72 | outlives, | |
94b46f34 | 73 | invalidates, |
74b04a01 XL |
74 | var_used_at, |
75 | var_defined_at, | |
76 | var_dropped_at, | |
77 | use_of_var_derefs_origin, | |
78 | drop_of_var_derefs_origin, | |
79 | child_path, | |
80 | path_is_var, | |
81 | path_assigned_at_base, | |
82 | path_moved_at_base, | |
83 | path_accessed_at_base, | |
60c5eb7d | 84 | known_subset, |
83c7162d XL |
85 | ]) |
86 | } | |
87 | Ok(()) | |
88 | } | |
89 | } | |
90 | ||
94b46f34 XL |
91 | impl Atom for BorrowIndex { |
92 | fn index(self) -> usize { | |
93 | Idx::index(self) | |
94 | } | |
95 | } | |
96 | ||
94b46f34 XL |
97 | impl Atom for LocationIndex { |
98 | fn index(self) -> usize { | |
99 | Idx::index(self) | |
100 | } | |
101 | } | |
102 | ||
e1599b0c XL |
103 | impl Atom for MovePathIndex { |
104 | fn index(self) -> usize { | |
105 | Idx::index(self) | |
106 | } | |
107 | } | |
108 | ||
83c7162d XL |
109 | struct FactWriter<'w> { |
110 | location_table: &'w LocationTable, | |
111 | dir: &'w Path, | |
112 | } | |
113 | ||
114 | impl<'w> FactWriter<'w> { | |
416331ca | 115 | fn write_facts_to_path<T>(&self, rows: &[T], file_name: &str) -> Result<(), Box<dyn Error>> |
83c7162d XL |
116 | where |
117 | T: FactRow, | |
118 | { | |
119 | let file = &self.dir.join(file_name); | |
74b04a01 | 120 | let mut file = BufWriter::new(File::create(file)?); |
83c7162d XL |
121 | for row in rows { |
122 | row.write(&mut file, self.location_table)?; | |
123 | } | |
124 | Ok(()) | |
125 | } | |
126 | } | |
127 | ||
128 | trait FactRow { | |
74b04a01 XL |
129 | fn write( |
130 | &self, | |
131 | out: &mut dyn Write, | |
132 | location_table: &LocationTable, | |
133 | ) -> Result<(), Box<dyn Error>>; | |
83c7162d XL |
134 | } |
135 | ||
136 | impl FactRow for RegionVid { | |
74b04a01 XL |
137 | fn write( |
138 | &self, | |
139 | out: &mut dyn Write, | |
140 | location_table: &LocationTable, | |
141 | ) -> Result<(), Box<dyn Error>> { | |
83c7162d XL |
142 | write_row(out, location_table, &[self]) |
143 | } | |
144 | } | |
145 | ||
146 | impl<A, B> FactRow for (A, B) | |
147 | where | |
148 | A: FactCell, | |
149 | B: FactCell, | |
150 | { | |
74b04a01 XL |
151 | fn write( |
152 | &self, | |
153 | out: &mut dyn Write, | |
154 | location_table: &LocationTable, | |
155 | ) -> Result<(), Box<dyn Error>> { | |
83c7162d XL |
156 | write_row(out, location_table, &[&self.0, &self.1]) |
157 | } | |
158 | } | |
159 | ||
160 | impl<A, B, C> FactRow for (A, B, C) | |
161 | where | |
162 | A: FactCell, | |
163 | B: FactCell, | |
164 | C: FactCell, | |
165 | { | |
74b04a01 XL |
166 | fn write( |
167 | &self, | |
168 | out: &mut dyn Write, | |
169 | location_table: &LocationTable, | |
170 | ) -> Result<(), Box<dyn Error>> { | |
83c7162d XL |
171 | write_row(out, location_table, &[&self.0, &self.1, &self.2]) |
172 | } | |
173 | } | |
174 | ||
175 | impl<A, B, C, D> FactRow for (A, B, C, D) | |
176 | where | |
177 | A: FactCell, | |
178 | B: FactCell, | |
179 | C: FactCell, | |
180 | D: FactCell, | |
181 | { | |
74b04a01 XL |
182 | fn write( |
183 | &self, | |
184 | out: &mut dyn Write, | |
185 | location_table: &LocationTable, | |
186 | ) -> Result<(), Box<dyn Error>> { | |
83c7162d XL |
187 | write_row(out, location_table, &[&self.0, &self.1, &self.2, &self.3]) |
188 | } | |
189 | } | |
190 | ||
191 | fn write_row( | |
192 | out: &mut dyn Write, | |
193 | location_table: &LocationTable, | |
194 | columns: &[&dyn FactCell], | |
195 | ) -> Result<(), Box<dyn Error>> { | |
196 | for (index, c) in columns.iter().enumerate() { | |
416331ca | 197 | let tail = if index == columns.len() - 1 { "\n" } else { "\t" }; |
83c7162d XL |
198 | write!(out, "{:?}{}", c.to_string(location_table), tail)?; |
199 | } | |
200 | Ok(()) | |
201 | } | |
202 | ||
203 | trait FactCell { | |
204 | fn to_string(&self, location_table: &LocationTable) -> String; | |
205 | } | |
206 | ||
207 | impl<A: Debug> FactCell for A { | |
208 | default fn to_string(&self, _location_table: &LocationTable) -> String { | |
209 | format!("{:?}", self) | |
210 | } | |
211 | } | |
212 | ||
213 | impl FactCell for LocationIndex { | |
214 | fn to_string(&self, location_table: &LocationTable) -> String { | |
215 | format!("{:?}", location_table.to_location(*self)) | |
216 | } | |
217 | } |