]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_mir/src/borrow_check/facts.rs
New upstream version 1.56.0~beta.4+dfsg1
[rustc.git] / compiler / rustc_mir / src / borrow_check / facts.rs
1 use crate::borrow_check::location::{LocationIndex, LocationTable};
2 use crate::dataflow::indexes::{BorrowIndex, MovePathIndex};
3 use polonius_engine::AllFacts as PoloniusFacts;
4 use polonius_engine::Atom;
5 use rustc_index::vec::Idx;
6 use rustc_middle::mir::Local;
7 use rustc_middle::ty::{RegionVid, TyCtxt};
8 use std::error::Error;
9 use std::fmt::Debug;
10 use std::fs::{self, File};
11 use std::io::{BufWriter, Write};
12 use std::path::Path;
13
14 #[derive(Copy, Clone, Debug)]
15 pub 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 pub type AllFacts = PoloniusFacts<RustcFacts>;
26
27 crate trait AllFactsExt {
28 /// Returns `true` if there is a need to gather `AllFacts` given the
29 /// current `-Z` flags.
30 fn enabled(tcx: TyCtxt<'_>) -> bool;
31
32 fn write_to_dir(
33 &self,
34 dir: impl AsRef<Path>,
35 location_table: &LocationTable,
36 ) -> Result<(), Box<dyn Error>>;
37 }
38
39 impl AllFactsExt for AllFacts {
40 /// Return
41 fn enabled(tcx: TyCtxt<'_>) -> bool {
42 tcx.sess.opts.debugging_opts.nll_facts || tcx.sess.opts.debugging_opts.polonius
43 }
44
45 fn write_to_dir(
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 loan_issued_at,
68 universal_region,
69 cfg_edge,
70 loan_killed_at,
71 subset_base,
72 loan_invalidated_at,
73 var_used_at,
74 var_defined_at,
75 var_dropped_at,
76 use_of_var_derefs_origin,
77 drop_of_var_derefs_origin,
78 child_path,
79 path_is_var,
80 path_assigned_at_base,
81 path_moved_at_base,
82 path_accessed_at_base,
83 known_placeholder_subset,
84 placeholder,
85 ])
86 }
87 Ok(())
88 }
89 }
90
91 impl Atom for BorrowIndex {
92 fn index(self) -> usize {
93 Idx::index(self)
94 }
95 }
96
97 impl Atom for LocationIndex {
98 fn index(self) -> usize {
99 Idx::index(self)
100 }
101 }
102
103 impl Atom for MovePathIndex {
104 fn index(self) -> usize {
105 Idx::index(self)
106 }
107 }
108
109 struct FactWriter<'w> {
110 location_table: &'w LocationTable,
111 dir: &'w Path,
112 }
113
114 impl<'w> FactWriter<'w> {
115 fn write_facts_to_path<T>(&self, rows: &[T], file_name: &str) -> Result<(), Box<dyn Error>>
116 where
117 T: FactRow,
118 {
119 let file = &self.dir.join(file_name);
120 let mut file = BufWriter::new(File::create(file)?);
121 for row in rows {
122 row.write(&mut file, self.location_table)?;
123 }
124 Ok(())
125 }
126 }
127
128 trait FactRow {
129 fn write(
130 &self,
131 out: &mut dyn Write,
132 location_table: &LocationTable,
133 ) -> Result<(), Box<dyn Error>>;
134 }
135
136 impl FactRow for RegionVid {
137 fn write(
138 &self,
139 out: &mut dyn Write,
140 location_table: &LocationTable,
141 ) -> Result<(), Box<dyn Error>> {
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 {
151 fn write(
152 &self,
153 out: &mut dyn Write,
154 location_table: &LocationTable,
155 ) -> Result<(), Box<dyn Error>> {
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 {
166 fn write(
167 &self,
168 out: &mut dyn Write,
169 location_table: &LocationTable,
170 ) -> Result<(), Box<dyn Error>> {
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 {
182 fn write(
183 &self,
184 out: &mut dyn Write,
185 location_table: &LocationTable,
186 ) -> Result<(), Box<dyn Error>> {
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() {
197 let tail = if index == columns.len() - 1 { "\n" } else { "\t" };
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 }