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