rapx/analysis/api_dependency/graph/
transform.rs1use super::dep_edge::DepEdge;
2use super::{ApiDependencyGraph, DepNode, TyWrapper};
3use petgraph::graph::NodeIndex;
4use rustc_ast::Mutability;
5use rustc_middle::ty::{self};
6use serde::Serialize;
7use std::fmt::Display;
8
9static ALL_TRANSFORMKIND: [TransformKind; 2] = [
10 TransformKind::Ref(ty::Mutability::Not),
11 TransformKind::Ref(ty::Mutability::Mut),
12 ];
15
16#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)]
17pub enum TransformKind {
18 Ref(ty::Mutability),
19 Unwrap, }
21
22impl TransformKind {
23 pub fn all() -> &'static [TransformKind] {
24 &ALL_TRANSFORMKIND
25 }
26}
27
28impl Display for TransformKind {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 match self {
31 TransformKind::Ref(mutability) => write!(f, "{}T", mutability.ref_prefix_str()),
32 TransformKind::Unwrap => write!(f, "Unwrap"),
33 }
34 }
35}
36
37impl Serialize for TransformKind {
38 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
39 where
40 S: serde::Serializer,
41 {
42 serializer.serialize_str(match self {
43 TransformKind::Ref(Mutability::Not) => "ref",
44 TransformKind::Ref(Mutability::Mut) => "ref_mut",
45 TransformKind::Unwrap => "unwrap",
46 })
47 }
48}
49
50impl<'tcx> ApiDependencyGraph<'tcx> {
51 pub fn update_transform_edges(&mut self) {
52 for node_index in self.graph.node_indices() {
53 if let DepNode::Ty(ty) = self.graph[node_index] {
54 self.add_possible_transform::<3>(ty, 0);
55 }
56 }
57 }
58
59 fn add_possible_transform<const MAX_DEPTH: usize>(
60 &mut self,
61 current_ty: TyWrapper<'tcx>,
62 depth: usize,
63 ) -> Option<NodeIndex> {
64 if depth > 0 {
65 let index = self.get_index(DepNode::Ty(current_ty));
66 if index.is_some() {
67 return index;
68 }
69 }
70
71 if depth >= MAX_DEPTH {
72 return None;
73 }
74
75 let mut ret = None;
76 for kind in TransformKind::all() {
77 let new_ty = current_ty.transform(*kind, self.tcx()); if let Some(next_index) = self.add_possible_transform::<MAX_DEPTH>(new_ty, depth + 1) {
79 let current_index = self.get_or_create_index(DepNode::Ty(current_ty));
80 self.add_edge_once(current_index, next_index, DepEdge::transform(*kind));
81 ret = Some(current_index);
82 }
83 }
84 ret
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::TransformKind;
91 use rustc_middle::ty;
92
93 #[test]
94 fn serialize_ref_not_matches_expected() {
95 let kind = TransformKind::Ref(ty::Mutability::Not);
96 let serialized = serde_json::to_string(&kind).expect("serialize TransformKind::Ref(Not)");
97 assert_eq!(serialized, "\"ref\"");
98 }
99
100 #[test]
101 fn serialize_ref_mut_matches_expected() {
102 let kind = TransformKind::Ref(ty::Mutability::Mut);
103 let serialized = serde_json::to_string(&kind).expect("serialize TransformKind::Ref(Mut)");
104 assert_eq!(serialized, "\"ref_mut\"");
105 }
106
107 #[test]
108 fn serialize_unwrap_matches_expected() {
109 let kind = TransformKind::Unwrap;
110 let serialized = serde_json::to_string(&kind).expect("serialize TransformKind::Unwrap");
111 assert_eq!(serialized, "\"unwrap\"");
112 }
113}