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}
;
10 use std
::fs
::{self, File}
;
11 use std
::io
::{BufWriter, Write}
;
14 #[derive(Copy, Clone, Debug)]
15 pub struct RustcFacts
;
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
;
25 pub type AllFacts
= PoloniusFacts
<RustcFacts
>;
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
;
34 dir
: impl AsRef
<Path
>,
35 location_table
: &LocationTable
,
36 ) -> Result
<(), Box
<dyn Error
>>;
39 impl AllFactsExt
for AllFacts
{
41 fn enabled(tcx
: TyCtxt
<'_
>) -> bool
{
42 tcx
.sess
.opts
.debugging_opts
.nll_facts
|| tcx
.sess
.opts
.debugging_opts
.polonius
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
. [
58 $wr
.write_facts_to_path(
60 &format
!("{}.facts", stringify
!($field
))
65 write_facts_to_path
! {
66 wr
.write_facts_to_path(self.[
76 use_of_var_derefs_origin
,
77 drop_of_var_derefs_origin
,
80 path_assigned_at_base
,
82 path_accessed_at_base
,
83 known_placeholder_subset
,
91 impl Atom
for BorrowIndex
{
92 fn index(self) -> usize {
97 impl Atom
for LocationIndex
{
98 fn index(self) -> usize {
103 impl Atom
for MovePathIndex
{
104 fn index(self) -> usize {
109 struct FactWriter
<'w
> {
110 location_table
: &'w LocationTable
,
114 impl<'w
> FactWriter
<'w
> {
115 fn write_facts_to_path
<T
>(&self, rows
: &[T
], file_name
: &str) -> Result
<(), Box
<dyn Error
>>
119 let file
= &self.dir
.join(file_name
);
120 let mut file
= BufWriter
::new(File
::create(file
)?
);
122 row
.write(&mut file
, self.location_table
)?
;
132 location_table
: &LocationTable
,
133 ) -> Result
<(), Box
<dyn Error
>>;
136 impl FactRow
for RegionVid
{
140 location_table
: &LocationTable
,
141 ) -> Result
<(), Box
<dyn Error
>> {
142 write_row(out
, location_table
, &[self])
146 impl<A
, B
> FactRow
for (A
, B
)
154 location_table
: &LocationTable
,
155 ) -> Result
<(), Box
<dyn Error
>> {
156 write_row(out
, location_table
, &[&self.0, &self.1])
160 impl<A
, B
, C
> FactRow
for (A
, B
, C
)
169 location_table
: &LocationTable
,
170 ) -> Result
<(), Box
<dyn Error
>> {
171 write_row(out
, location_table
, &[&self.0, &self.1, &self.2])
175 impl<A
, B
, C
, D
> FactRow
for (A
, B
, C
, D
)
185 location_table
: &LocationTable
,
186 ) -> Result
<(), Box
<dyn Error
>> {
187 write_row(out
, location_table
, &[&self.0, &self.1, &self.2, &self.3])
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
)?
;
204 fn to_string(&self, location_table
: &LocationTable
) -> String
;
207 impl<A
: Debug
> FactCell
for A
{
208 default fn to_string(&self, _location_table
: &LocationTable
) -> String
{
209 format
!("{:?}", self)
213 impl FactCell
for LocationIndex
{
214 fn to_string(&self, location_table
: &LocationTable
) -> String
{
215 format
!("{:?}", location_table
.to_location(*self))