use std::fmt;
use std::rc::Rc;
use std::sync::Arc;
use pedant_types::Capability;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IrSpan {
pub line: usize,
pub column: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum DataFlowKind {
TaintFlow,
DeadStore,
DiscardedResult,
PartialErrorHandling,
RepeatedCall,
UnnecessaryClone,
AllocationInLoop,
RedundantCollect,
LockAcrossAwait,
InconsistentLockOrder,
ImmutableGrowable,
SwallowedOk,
UnobservedSpawn,
}
impl DataFlowKind {
pub fn code(self) -> &'static str {
match self {
Self::TaintFlow => "taint-flow",
Self::DeadStore => "dead-store",
Self::DiscardedResult => "discarded-result",
Self::PartialErrorHandling => "partial-error-handling",
Self::RepeatedCall => "repeated-call",
Self::UnnecessaryClone => "unnecessary-clone",
Self::AllocationInLoop => "allocation-in-loop",
Self::RedundantCollect => "redundant-collect",
Self::LockAcrossAwait => "lock-across-await",
Self::InconsistentLockOrder => "inconsistent-lock-order",
Self::ImmutableGrowable => "immutable-growable",
Self::SwallowedOk => "swallowed-ok",
Self::UnobservedSpawn => "unobserved-spawn",
}
}
}
impl fmt::Display for DataFlowKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.code())
}
}
#[derive(Debug, Clone)]
pub struct DataFlowFact {
pub kind: DataFlowKind,
pub source_capability: Option<Capability>,
pub source_span: IrSpan,
pub sink_capability: Option<Capability>,
pub sink_span: IrSpan,
pub call_chain: Box<[Box<str>]>,
pub message: Box<str>,
}
#[derive(Debug)]
pub struct FileIr {
pub file_path: Arc<str>,
pub functions: Box<[FnFact]>,
pub type_defs: Box<[TypeDefFact]>,
pub impl_blocks: Box<[ImplFact]>,
pub use_paths: Box<[UsePathFact]>,
pub control_flow: Box<[ControlFlowFact]>,
pub bindings: Box<[BindingFact]>,
pub type_refs: Box<[TypeRefFact]>,
pub method_calls: Box<[MethodCallFact]>,
pub macro_invocations: Box<[MacroFact]>,
pub attributes: Box<[AttributeFact]>,
pub string_literals: Box<[StringLitFact]>,
pub unsafe_sites: Box<[UnsafeFact]>,
pub extern_blocks: Box<[ExternBlockFact]>,
pub modules: Box<[ModuleFact]>,
pub data_flows: std::sync::Arc<[DataFlowFact]>,
}
#[derive(Debug)]
pub struct FnFact {
pub name: Box<str>,
pub span: IrSpan,
pub is_unsafe: bool,
pub params: Box<[ParamFact]>,
pub return_type: Option<TypeInfo>,
pub signature_type_names: Box<[Rc<str>]>,
pub item_depth: usize,
pub has_arithmetic: bool,
pub body_type_edges: Box<[(Rc<str>, Rc<str>)]>,
}
#[derive(Debug)]
pub struct ParamFact {
pub name: Box<str>,
pub type_text: Box<str>,
}
#[derive(Debug)]
pub struct TypeInfo {
pub text: Box<str>,
pub involves_dyn: bool,
}
#[derive(Debug, Clone, Copy)]
pub struct ElseInfo {
pub chain_len: Option<usize>,
pub span: Option<IrSpan>,
}
#[derive(Debug)]
pub struct ControlFlowFact {
pub kind: ControlFlowKind,
pub span: IrSpan,
pub depth: usize,
pub loop_depth: usize,
pub parent_branch: Option<BranchContext>,
pub else_info: Option<ElseInfo>,
pub containing_fn: Option<usize>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ControlFlowKind {
If,
Match,
ForLoop,
WhileLoop,
Loop,
Closure,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BranchContext {
If,
Match,
}
#[derive(Debug)]
pub struct BindingFact {
pub name: Box<str>,
pub span: Option<IrSpan>,
pub loop_depth: usize,
pub is_refcounted: bool,
pub is_wildcard: bool,
pub has_init: bool,
pub init_is_write_macro: bool,
pub containing_fn: Option<usize>,
pub type_annotation_span: Option<IrSpan>,
pub resolved_type: Option<Box<str>>,
}
#[derive(Debug)]
pub struct TypeRefFact {
pub text: Box<str>,
pub span: IrSpan,
pub involves_dyn: bool,
pub is_vec_box_dyn: bool,
pub is_default_hasher: bool,
pub containing_fn: Option<usize>,
pub context: TypeRefContext,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TypeRefContext {
Return,
Param,
Field,
Body,
}
#[derive(Debug)]
pub struct TypeDefFact {
pub name: Rc<str>,
pub span: IrSpan,
pub kind: TypeDefKind,
pub edges: Box<[(Rc<str>, Rc<str>)]>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TypeDefKind {
Struct,
Enum,
Trait,
}
#[derive(Debug)]
pub struct ImplFact {
pub self_type: Rc<str>,
pub trait_name: Option<Box<str>>,
pub span: IrSpan,
pub edges: Box<[(Rc<str>, Rc<str>)]>,
}
#[derive(Debug)]
pub struct UsePathFact {
pub path: Box<str>,
pub span: IrSpan,
}
#[derive(Debug)]
pub struct MethodCallFact {
pub method_name: Box<str>,
pub text: Box<str>,
pub span: IrSpan,
pub receiver_ident: Option<Box<str>>,
pub receiver_span: IrSpan,
pub loop_depth: usize,
pub containing_fn: Option<usize>,
pub receiver_type: Option<Arc<str>>,
pub is_copy_receiver: bool,
}
#[derive(Debug)]
pub struct MacroFact {
pub text: Box<str>,
pub span: IrSpan,
}
#[derive(Debug)]
pub struct AttributeFact {
pub text: Box<str>,
pub span: IrSpan,
pub name: Box<str>,
}
#[derive(Debug)]
pub struct StringLitFact {
pub value: Box<str>,
pub span: IrSpan,
}
#[derive(Debug)]
pub struct UnsafeFact {
pub kind: UnsafeKind,
pub span: IrSpan,
pub evidence: Box<str>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnsafeKind {
Block,
Fn,
Impl,
}
#[derive(Debug)]
pub struct ExternBlockFact {
pub span: IrSpan,
}
#[derive(Debug)]
pub struct FnFingerprint {
pub fn_index: usize,
pub name: Box<str>,
pub span: IrSpan,
pub skeleton_hash: u64,
pub exact_hash: u64,
pub fact_count: usize,
}
#[derive(Debug)]
pub struct ModuleFact {
pub name: Box<str>,
pub span: IrSpan,
pub is_cfg_test: bool,
}