1#![allow(dead_code)]
2#![allow(unused_variables)]
3
4pub mod default;
5mod extract;
6mod graph;
7mod visitor;
8
9use petgraph::{graph::NodeIndex, Graph};
10use rustc_hir::def_id::DefId;
11use rustc_middle::ty::{self, Ty, TyCtxt};
12
13use std::{collections::HashMap, hash::Hash};
14
15pub trait ApiDependencyAnalysis<'tcx> {
16 fn get_api_dependency_graph(&self) -> ApiDependencyGraph<'tcx>;
17}
18
19type InnerGraph<'tcx> = Graph<Node<'tcx>, Edge>;
20
21#[derive(Clone)]
22pub struct ApiDependencyGraph<'tcx> {
23 graph: InnerGraph<'tcx>,
24 node_indices: HashMap<Node<'tcx>, NodeIndex>,
25}
26
27#[derive(Clone, Debug, Eq, PartialEq, Hash)]
28pub enum Node<'tcx> {
29 Api(DefId),
30 Ty(TyWrapper<'tcx>),
31 GenericParamDef(DefId, usize, String, bool), }
33
34#[derive(Clone, Copy, Eq, PartialEq, Debug)]
35pub enum Edge {
36 Arg(usize),
37 Ret,
38 Fn2Generic,
39}
40#[derive(Hash, Eq, PartialEq, Debug)]
41pub enum LifetimeKind {
42 Static,
43 Bound(usize),
44 Any(usize),
45}
46
47#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
48pub struct Lifetime {
49 pub id: usize,
51}
52
53#[derive(Clone, Eq, Debug)]
56pub struct TyWrapper<'tcx> {
57 ty: ty::Ty<'tcx>,
58 lifetime_map: Vec<Lifetime>,
59}
60
61impl Hash for TyWrapper<'_> {
62 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
63 hash_ty(self.ty, state, &mut 0);
64 }
65}
66
67fn eq_ty<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>) -> bool {
68 match (lhs.kind(), rhs.kind()) {
69 (ty::TyKind::Adt(adt_def1, generic_arg1), ty::TyKind::Adt(adt_def2, generic_arg2)) => {
70 if adt_def1.did() != adt_def2.did() {
71 return false;
72 }
73 for (arg1, arg2) in generic_arg1.iter().zip(generic_arg2.iter()) {
74 match (arg1.kind(), arg2.kind()) {
75 (ty::GenericArgKind::Lifetime(_), ty::GenericArgKind::Lifetime(_)) => continue,
76 (ty::GenericArgKind::Type(ty1), ty::GenericArgKind::Type(ty2)) => {
77 if !eq_ty(ty1, ty2) {
78 return false;
79 }
80 }
81 (ty::GenericArgKind::Const(ct1), ty::GenericArgKind::Const(ct2)) => {
82 if ct1 != ct2 {
83 return false;
84 }
85 }
86 _ => return false,
87 }
88 }
89 true
90 }
91 (
92 ty::TyKind::RawPtr(inner_ty1, mutability1),
93 ty::TyKind::RawPtr(inner_ty2, mutability2),
94 )
95 | (
96 ty::TyKind::Ref(_, inner_ty1, mutability1),
97 ty::TyKind::Ref(_, inner_ty2, mutability2),
98 ) => mutability1 == mutability2 && eq_ty(*inner_ty1, *inner_ty2),
99 (ty::TyKind::Array(inner_ty1, _), ty::TyKind::Array(inner_ty2, _))
100 | (ty::TyKind::Pat(inner_ty1, _), ty::TyKind::Pat(inner_ty2, _))
101 | (ty::TyKind::Slice(inner_ty1), ty::TyKind::Slice(inner_ty2)) => {
102 eq_ty(*inner_ty1, *inner_ty2)
103 }
104 (ty::TyKind::Tuple(tys1), ty::TyKind::Tuple(tys2)) => {
105 if tys1.len() != tys2.len() {
106 return false;
107 }
108 tys1.iter()
109 .zip(tys2.iter())
110 .all(|(ty1, ty2)| eq_ty(ty1, ty2))
111 }
112 _ => lhs == rhs,
113 }
114}
115
116fn traverse_ty_with_lifetime<'tcx, F: Fn(ty::Region, usize)>(ty: Ty<'tcx>, no: &mut usize, f: &F) {
117 match ty.kind() {
118 ty::TyKind::Adt(_, generic_arg) => {
119 for arg in generic_arg.iter() {
120 match arg.kind() {
121 ty::GenericArgKind::Lifetime(lt) => {
122 *no = *no + 1;
123 f(lt, *no);
124 }
125 ty::GenericArgKind::Type(ty) => {
126 traverse_ty_with_lifetime(ty, no, f);
127 }
128 ty::GenericArgKind::Const(_) => {}
129 }
130 }
131 }
132
133 ty::TyKind::RawPtr(inner_ty, _) => {
134 traverse_ty_with_lifetime(*inner_ty, no, f);
135 }
136
137 ty::TyKind::Ref(region, inner_ty, _) => {
138 *no = *no + 1;
139 f(*region, *no);
140 traverse_ty_with_lifetime(*inner_ty, no, f);
141 }
142 ty::TyKind::Array(inner_ty, _)
143 | ty::TyKind::Pat(inner_ty, _)
144 | ty::TyKind::Slice(inner_ty) => {
145 traverse_ty_with_lifetime(*inner_ty, no, f);
146 }
147 ty::TyKind::Tuple(tys) => {
148 for inner_ty in tys.iter() {
149 traverse_ty_with_lifetime(inner_ty, no, f);
150 }
151 }
152 _ => {
153 unreachable!("unexpected ty kind");
154 }
155 }
156}
157
158fn hash_ty<'tcx, H: std::hash::Hasher>(ty: Ty<'tcx>, state: &mut H, no: &mut usize) {
160 match ty.kind() {
162 ty::TyKind::Adt(..) => 0,
163 ty::TyKind::RawPtr(..) => 1,
164 ty::TyKind::Ref(..) => 2,
165 ty::TyKind::Array(..) => 3,
166 ty::TyKind::Pat(..) => 4,
167 ty::TyKind::Slice(..) => 5,
168 ty::TyKind::Tuple(..) => 6,
169 _ => {
170 ty.hash(state);
171 return;
172 }
173 }
174 .hash(state);
175
176 match ty.kind() {
178 ty::TyKind::Adt(adt_def, generic_arg) => {
179 adt_def.did().hash(state);
180 for arg in generic_arg.iter() {
181 match arg.kind() {
182 ty::GenericArgKind::Lifetime(_) => {
183 *no = *no + 1;
184 no.hash(state);
185 }
186 ty::GenericArgKind::Type(ty) => {
187 hash_ty(ty, state, no);
188 }
189 ty::GenericArgKind::Const(ct) => {
190 ct.hash(state);
191 }
192 }
193 }
194 }
195
196 ty::TyKind::RawPtr(inner_ty, mutability) => {
197 mutability.hash(state);
198 hash_ty(*inner_ty, state, no);
199 }
200 ty::TyKind::Ref(_, inner_ty, mutability) => {
201 mutability.hash(state);
202 *no = *no + 1;
203 no.hash(state);
204 hash_ty(*inner_ty, state, no);
205 }
206 ty::TyKind::Array(inner_ty, _)
207 | ty::TyKind::Pat(inner_ty, _)
208 | ty::TyKind::Slice(inner_ty) => {
209 hash_ty(*inner_ty, state, no);
210 }
211 ty::TyKind::Tuple(tys) => {
212 for inner_ty in tys.iter() {
213 hash_ty(inner_ty, state, no);
214 }
215 }
216 _ => {
217 unreachable!("unexpected ty kind");
218 }
219 }
220}
221
222pub fn desc_ty_str<'tcx>(ty: Ty<'tcx>, no: &mut usize, tcx: TyCtxt<'tcx>) -> String {
223 match ty.kind() {
224 ty::TyKind::Adt(adt_def, generic_arg) => {
225 let mut ty_str = tcx.def_path_str(adt_def.did());
226 if !generic_arg.is_empty() {
227 ty_str += "<";
228 ty_str += &generic_arg
229 .iter()
230 .map(|arg| match arg.kind() {
231 ty::GenericArgKind::Lifetime(_) => {
232 let current_no = *no;
233 *no = *no + 1;
234 format!("'#{:?}", current_no)
235 }
236 ty::GenericArgKind::Type(ty) => desc_ty_str(ty, no, tcx),
237 ty::GenericArgKind::Const(ct) => format!("{:?}", ct),
238 })
239 .collect::<Vec<String>>()
240 .join(", ");
241 ty_str += ">";
242 }
243 ty_str
244 }
245
246 ty::TyKind::RawPtr(inner_ty, mutability) => {
247 let mut_str = {
248 match mutability {
249 ty::Mutability::Mut => "mut",
250 ty::Mutability::Not => "const",
251 }
252 };
253 format!("*{} {}", mut_str, desc_ty_str(*inner_ty, no, tcx))
254 }
255 ty::TyKind::Ref(_, inner_ty, mutability) => {
256 let mut_str = {
257 match mutability {
258 ty::Mutability::Mut => "mut",
259 ty::Mutability::Not => "",
260 }
261 };
262 let current_no = *no;
263 *no = *no + 1;
264 format!(
265 "&'#{}{} {}",
266 current_no,
267 mut_str,
268 desc_ty_str(*inner_ty, no, tcx)
269 )
270 }
271 ty::TyKind::Array(inner_ty, _)
272 | ty::TyKind::Pat(inner_ty, _)
273 | ty::TyKind::Slice(inner_ty) => desc_ty_str(*inner_ty, no, tcx),
274 ty::TyKind::Tuple(tys) => format!(
275 "({})",
276 tys.iter()
277 .map(|ty| desc_ty_str(ty, no, tcx,))
278 .collect::<Vec<String>>()
279 .join(", "),
280 ),
281 _ => format!("{:?}", ty),
282 }
283}
284
285impl<'tcx> TyWrapper<'tcx> {
286 pub fn desc_str(&self, tcx: TyCtxt<'tcx>) -> String {
287 desc_ty_str(self.ty, &mut 0, tcx)
288 }
289}
290
291impl<'tcx> From<Ty<'tcx>> for TyWrapper<'tcx> {
292 fn from(ty: ty::Ty<'tcx>) -> TyWrapper<'tcx> {
293 let lifetime_map = Vec::new();
295 TyWrapper { ty, lifetime_map }
296 }
297}
298
299impl PartialEq for TyWrapper<'_> {
300 fn eq(&self, other: &Self) -> bool {
301 eq_ty(self.ty, other.ty)
302 }
303}