rapx/analysis/core/api_dependency/graph/
transform.rs

1use super::dep_edge::DepEdge;
2use super::{ApiDependencyGraph, DepNode, TyWrapper};
3use petgraph::graph::NodeIndex;
4use rustc_middle::ty::{self};
5use std::fmt::Display;
6
7static ALL_TRANSFORMKIND: [TransformKind; 2] = [
8    TransformKind::Ref(ty::Mutability::Not),
9    TransformKind::Ref(ty::Mutability::Mut),
10    // TransformKind::Deref,
11    // TransformKind::Box,
12];
13
14#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)]
15pub enum TransformKind {
16    Ref(ty::Mutability),
17    Unwrap, // unwrap Option<T>, Result<T, E>
18}
19
20impl TransformKind {
21    pub fn all() -> &'static [TransformKind] {
22        &ALL_TRANSFORMKIND
23    }
24}
25
26impl Display for TransformKind {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        match self {
29            TransformKind::Ref(mutability) => write!(f, "{}T", mutability.ref_prefix_str()),
30            TransformKind::Unwrap => write!(f, "Unwrap"),
31        }
32    }
33}
34
35impl<'tcx> ApiDependencyGraph<'tcx> {
36    pub fn update_transform_edges(&mut self) {
37        for node_index in self.graph.node_indices() {
38            if let DepNode::Ty(ty) = self.graph[node_index] {
39                self.add_possible_transform::<3>(ty, 0);
40            }
41        }
42    }
43
44    fn add_possible_transform<const MAX_DEPTH: usize>(
45        &mut self,
46        current_ty: TyWrapper<'tcx>,
47        depth: usize,
48    ) -> Option<NodeIndex> {
49        if depth > 0 {
50            let index = self.get_index(DepNode::Ty(current_ty));
51            if index.is_some() {
52                return index;
53            }
54        }
55
56        if depth >= MAX_DEPTH {
57            return None;
58        }
59
60        let mut ret = None;
61        for kind in TransformKind::all() {
62            let new_ty = current_ty.transform(*kind, self.tcx()); // &T or &mut T
63            if let Some(next_index) = self.add_possible_transform::<MAX_DEPTH>(new_ty, depth + 1) {
64                let current_index = self.get_or_create_index(DepNode::Ty(current_ty));
65                self.add_edge_once(current_index, next_index, DepEdge::transform(*kind));
66                ret = Some(current_index);
67            }
68        }
69        ret
70    }
71}