rapx/analysis/api_dependency/graph/
avail.rs1use super::super::visit::FnVisitor;
2use super::ApiDependencyGraph;
3use super::Config;
4use super::dep_edge::DepEdge;
5use super::dep_node::DepNode;
6use super::transform::TransformKind;
7use super::ty_wrapper::TyWrapper;
8use super::utils;
9use crate::helpers::def_path::path_str_def_id;
10use crate::rap_debug;
11use crate::rap_trace;
12use petgraph::Direction;
13use petgraph::visit::EdgeRef;
14use rustc_middle::ty::{self, Ty, TyCtxt};
15use std::collections::HashSet;
16
17impl<'tcx> ApiDependencyGraph<'tcx> {
18 pub fn eligible_nodes_with(&self, tys: &[Ty<'tcx>]) -> Vec<DepNode<'tcx>> {
19 let check_ty = |ty: Ty<'tcx>| {
20 tys.iter()
21 .any(|avail_ty| utils::is_ty_eq(*avail_ty, ty, self.tcx))
22 };
23
24 self.graph
25 .node_indices()
26 .filter_map(|index| match self.graph[index] {
27 DepNode::Api(fn_did, args)
28 if self
29 .graph
30 .neighbors_directed(index, Direction::Incoming)
31 .all(|neighbor| {
32 let ty = self.graph[neighbor].expect_ty().ty();
33 utils::is_fuzzable_ty(ty, self.tcx) || check_ty(ty)
34 }) =>
35 {
36 Some(self.graph[index])
37 }
38 DepNode::Ty(ty)
39 if self
40 .graph
41 .neighbors_directed(index, Direction::Incoming)
42 .any(|neighbor| {
43 if let Some(ty) = self.graph[neighbor].as_ty() {
44 check_ty(ty.ty())
45 } else {
46 false
47 }
48 }) =>
49 {
50 Some(self.graph[index])
51 }
52 _ => None,
53 })
54 .collect()
55 }
56
57 pub fn eligible_transforms_to(&self, ty: Ty<'tcx>) -> Vec<(TyWrapper<'tcx>, TransformKind)> {
58 let mut set = HashSet::new();
59 if let Some(node) = self.get_index(DepNode::Ty(ty.into())) {
60 for edge in self.graph.edges_directed(node, Direction::Incoming) {
61 if let Some(kind) = edge.weight().as_transform_kind() {
62 let source_ty = self.graph[edge.source()].expect_ty();
63 set.insert((source_ty, kind));
64 }
65 }
66 }
67 set.into_iter().collect()
68 }
69}