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