mod context;
pub(crate) mod flow;
mod output;
pub mod utils;
use std::ops::{Deref, DerefMut};
pub use context::PermissionsCtxt;
use fluid_let::fluid_let;
pub use output::{compute, Output};
use polonius_engine::FactTypes;
use rustc_borrowck::consumers::RustcFacts;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::mir::Place;
use rustc_utils::source_map::range::CharRange;
use serde::Serialize;
use ts_rs::TS;
use crate::analysis::{LoanKey, MoveKey};
fluid_let!(pub static ENABLE_FLOW_PERMISSIONS: bool);
pub const ENABLE_FLOW_DEFAULT: bool = false;
#[derive(Copy, Clone, Debug)]
pub struct AquascopeFacts;
impl polonius_engine::FactTypes for AquascopeFacts {
type Origin = <RustcFacts as FactTypes>::Origin;
type Loan = <RustcFacts as FactTypes>::Loan;
type Point = <RustcFacts as FactTypes>::Point;
type Variable = <RustcFacts as FactTypes>::Variable;
type Path = PathIndex;
}
rustc_index::newtype_index! {
#[debug_format = "path{}"]
pub struct PathIndex {}
}
impl polonius_engine::Atom for PathIndex {
fn index(self) -> usize {
rustc_index::Idx::index(self)
}
}
pub type Origin = <AquascopeFacts as FactTypes>::Origin;
pub type Path = <AquascopeFacts as FactTypes>::Path;
pub type Point = <AquascopeFacts as FactTypes>::Point;
pub type Loan = <AquascopeFacts as FactTypes>::Loan;
pub type Variable = <AquascopeFacts as FactTypes>::Variable;
pub type Move = rustc_mir_dataflow::move_paths::MoveOutIndex;
#[derive(Clone, Copy, Hash, PartialEq, Eq, Serialize, TS)]
#[ts(export)]
pub struct Permissions {
pub read: bool,
pub write: bool,
pub drop: bool,
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, TS)]
#[ts(export)]
pub struct PermissionsData {
pub type_droppable: bool,
pub type_writeable: bool,
pub type_copyable: bool,
pub is_live: bool,
pub path_uninitialized: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub path_moved: Option<MoveKey>,
#[serde(skip_serializing_if = "Option::is_none")]
pub loan_read_refined: Option<LoanKey>,
#[serde(skip_serializing_if = "Option::is_none")]
pub loan_write_refined: Option<LoanKey>,
#[serde(skip_serializing_if = "Option::is_none")]
pub loan_drop_refined: Option<LoanKey>,
pub permissions: Permissions,
}
#[derive(Debug, Clone, Serialize, PartialEq, TS)]
#[ts(export)]
pub enum Refiner {
Loan(LoanKey),
Move(MoveKey),
}
#[derive(Debug, Clone, Serialize, PartialEq, TS)]
#[ts(export)]
pub struct RefinementRegion {
pub refiner_point: Refiner,
pub refined_ranges: Vec<CharRange>,
}
#[derive(Clone, PartialEq, Eq, Default, Debug)]
pub struct PermissionsDomain<'tcx>(FxHashMap<Place<'tcx>, PermissionsData>);
impl Permissions {
pub fn bottom() -> Self {
Permissions {
read: false,
write: false,
drop: false,
}
}
}
impl std::fmt::Debug for Permissions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if !self.read && !self.write && !self.drop {
write!(f, "∅")
} else {
if self.read {
write!(f, "R")?;
}
if self.write {
write!(f, "W")?;
}
if self.drop {
write!(f, "D")?;
}
Ok(())
}
}
}
impl<'tcx> From<FxHashMap<Place<'tcx>, PermissionsData>>
for PermissionsDomain<'tcx>
{
fn from(m: FxHashMap<Place<'tcx>, PermissionsData>) -> Self {
PermissionsDomain(m)
}
}
impl<'tcx> Deref for PermissionsDomain<'tcx> {
type Target = FxHashMap<Place<'tcx>, PermissionsData>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for PermissionsDomain<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}