rapx/analysis/core/api_dependency/
utils.rs

1#![allow(warnings, unused)]
2
3use rustc_hir::LangItem;
4use rustc_hir::def_id::DefId;
5use rustc_middle::ty::{self, FnSig, Ty, TyCtxt, TyKind};
6use rustc_span::sym;
7
8fn is_fuzzable_std_ty<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
9    match ty.kind() {
10        ty::Adt(def, _) => {
11            tcx.is_lang_item(def.did(), LangItem::String)
12                || tcx.is_diagnostic_item(sym::Vec, def.did())
13                || tcx.is_diagnostic_item(sym::Arc, def.did())
14        }
15        _ => false,
16    }
17}
18
19pub fn is_fuzzable_ty<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
20    if is_fuzzable_std_ty(ty, tcx) {
21        return true;
22    }
23
24    match ty.kind() {
25        // Basical data type
26        TyKind::Bool
27        | TyKind::Char
28        | TyKind::Int(_)
29        | TyKind::Uint(_)
30        | TyKind::Float(_)
31        | TyKind::Str => true,
32
33        // Infer
34        TyKind::Infer(
35            ty::InferTy::IntVar(_)
36            | ty::InferTy::FreshIntTy(_)
37            | ty::InferTy::FloatVar(_)
38            | ty::InferTy::FreshFloatTy(_),
39        ) => true,
40
41        // Reference, Array, Slice
42        TyKind::Ref(_, inner_ty, _) | TyKind::Array(inner_ty, _) | TyKind::Slice(inner_ty) => {
43            is_fuzzable_ty(inner_ty.peel_refs(), tcx)
44        }
45
46        // Tuple
47        TyKind::Tuple(tys) => tys
48            .iter()
49            .all(|inner_ty| is_fuzzable_ty(inner_ty.peel_refs(), tcx)),
50
51        // ADT
52        TyKind::Adt(adt_def, substs) => {
53            if adt_def.variant_list_has_applicable_non_exhaustive() {
54                return false;
55            }
56            if adt_def.is_struct() {
57                // 检查所有字段是否为 pub 且类型可 Fuzz
58                adt_def.all_fields().all(|field| {
59                    field.vis.is_public() && // 字段必须是 pub
60                    is_fuzzable_ty(field.ty(tcx, substs).peel_refs(), tcx)
61                })
62            } else if adt_def.is_enum() {
63                adt_def.variants().iter().all(|variant| {
64                    variant
65                        .fields
66                        .iter()
67                        .all(|field| is_fuzzable_ty(field.ty(tcx, substs).peel_refs(), tcx))
68                })
69            } else {
70                false // union 暂不处理
71            }
72        }
73
74        // 其他类型默认不可 Fuzz
75        _ => false,
76    }
77}
78
79pub fn fn_sig_without_binders<'tcx>(fn_did: DefId, tcx: TyCtxt<'tcx>) -> FnSig<'tcx> {
80    let early_fn_sig = tcx.fn_sig(fn_did);
81    let binder_fn_sig = early_fn_sig.instantiate_identity();
82    tcx.liberate_late_bound_regions(fn_did, binder_fn_sig)
83}
84
85pub fn fn_sig_with_generic_args<'tcx>(
86    fn_did: DefId,
87    args: &[ty::GenericArg<'tcx>],
88    tcx: TyCtxt<'tcx>,
89) -> FnSig<'tcx> {
90    let early_fn_sig = tcx.fn_sig(fn_did);
91    let binder_fn_sig = early_fn_sig.instantiate(tcx, args);
92    tcx.liberate_late_bound_regions(fn_did, binder_fn_sig)
93}
94
95pub fn fn_requires_monomorphization<'tcx>(fn_did: DefId, tcx: TyCtxt<'_>) -> bool {
96    tcx.generics_of(fn_did).requires_monomorphization(tcx)
97}
98
99pub fn is_ty_eq<'tcx>(ty1: Ty<'tcx>, ty2: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
100    let ty1 = tcx.erase_and_anonymize_regions(ty1);
101    let ty2 = tcx.erase_and_anonymize_regions(ty2);
102    return ty1 == ty2;
103}
104
105pub fn ty_complexity<'tcx>(ty: Ty<'tcx>) -> usize {
106    match ty.kind() {
107        // Reference, Array, Slice
108        TyKind::Ref(_, inner_ty, _) | TyKind::Array(inner_ty, _) | TyKind::Slice(inner_ty) => {
109            ty_complexity(*inner_ty) + 1
110        }
111
112        // Tuple
113        TyKind::Tuple(tys) => tys.iter().fold(0, |ans, ty| ans.max(ty_complexity(ty))) + 1,
114
115        // ADT
116        TyKind::Adt(_, args) => {
117            args.iter().fold(0, |ans, arg| {
118                if let Some(ty) = arg.as_type() {
119                    ans.max(ty_complexity(ty))
120                } else {
121                    ans
122                }
123            }) + 1
124        }
125
126        // the depth of other primitive type default to 1
127        _ => 1,
128    }
129}