]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/borrow_check/facts.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_mir / borrow_check / facts.rs
CommitLineData
9fa01778 1use crate::borrow_check::location::{LocationIndex, LocationTable};
e1599b0c 2use crate::dataflow::indexes::{BorrowIndex, MovePathIndex};
60c5eb7d 3use polonius_engine::AllFacts as PoloniusFacts;
94b46f34 4use polonius_engine::Atom;
e74abb32 5use rustc_index::vec::Idx;
ba9703b0
XL
6use rustc_middle::mir::Local;
7use rustc_middle::ty::{RegionVid, TyCtxt};
83c7162d
XL
8use std::error::Error;
9use std::fmt::Debug;
10use std::fs::{self, File};
74b04a01 11use std::io::{BufWriter, Write};
83c7162d
XL
12use std::path::Path;
13
60c5eb7d
XL
14#[derive(Copy, Clone, Debug)]
15crate struct RustcFacts;
16
17impl 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
25crate type AllFacts = PoloniusFacts<RustcFacts>;
83c7162d 26
94b46f34 27crate 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 39impl 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
91impl Atom for BorrowIndex {
92 fn index(self) -> usize {
93 Idx::index(self)
94 }
95}
96
94b46f34
XL
97impl Atom for LocationIndex {
98 fn index(self) -> usize {
99 Idx::index(self)
100 }
101}
102
e1599b0c
XL
103impl Atom for MovePathIndex {
104 fn index(self) -> usize {
105 Idx::index(self)
106 }
107}
108
83c7162d
XL
109struct FactWriter<'w> {
110 location_table: &'w LocationTable,
111 dir: &'w Path,
112}
113
114impl<'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
128trait 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
136impl 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
146impl<A, B> FactRow for (A, B)
147where
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
160impl<A, B, C> FactRow for (A, B, C)
161where
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
175impl<A, B, C, D> FactRow for (A, B, C, D)
176where
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
191fn 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
203trait FactCell {
204 fn to_string(&self, location_table: &LocationTable) -> String;
205}
206
207impl<A: Debug> FactCell for A {
208 default fn to_string(&self, _location_table: &LocationTable) -> String {
209 format!("{:?}", self)
210 }
211}
212
213impl FactCell for LocationIndex {
214 fn to_string(&self, location_table: &LocationTable) -> String {
215 format!("{:?}", location_table.to_location(*self))
216 }
217}