rapx/analysis/alias_analysis/default/
types.rs

1use rustc_middle::ty::{self, Ty, TyCtxt};
2
3#[derive(PartialEq, Debug, Copy, Clone)]
4/// Represents different kinds of types for alias analysis purposes.
5/// This is a wrapper of rustc_middle::ty::TyKind, except that treat some types as special cases;
6pub enum ValueKind {
7    /// Algebraic Data Type (structs, enums, basic composite types).
8    Adt,
9    /// Raw pointer type, e.g., `*const T` or `*mut T`.
10    RawPtr,
11    /// Reference type, e.g., `&T` or `&mut T`.
12    Ref,
13    /// Tuple type, e.g., `(T1, T2, ...)`.
14    Tuple,
15    /// Special cases such as `RefCell`, `Rc`, etc., which need to be treated differently.
16    SpecialPtr,
17}
18
19/// Analyzes a `Ty` (Rustc type) and returns its `TyKind` for alias analysis.
20///
21/// This function inspects the Rustc type and categorizes it into one of the `TyKind` variants.
22/// Special types such as `RefCell`, `RefMut`, and `Rc` are further mapped to `SpecialPtr`.
23///
24/// # Arguments
25/// * `ty` - The type to be classified.
26///
27/// # Returns
28/// * `TyKind` - The classified type kind.
29pub fn kind(ty: Ty<'_>) -> ValueKind {
30    match ty.kind() {
31        ty::RawPtr(..) => ValueKind::RawPtr,
32        ty::Ref(..) => ValueKind::Ref,
33        ty::Tuple(..) => ValueKind::Tuple,
34        ty::Adt(adt, _) => {
35            // Use string matching to catch RefCell/RefMut/Rc for special handling.
36            let s = format!("{:?}", adt);
37            if s.contains("cell::RefMut")
38                || s.contains("cell::Ref")
39                || s.contains("rc::Rc")
40                || s.contains("sync::Arc")
41                || s.contains("sync::Weak")
42            {
43                ValueKind::SpecialPtr
44            } else {
45                ValueKind::Adt
46            }
47        }
48        _ => ValueKind::Adt,
49    }
50}
51
52/// Determines whether a given type will never need drop (i.e., is trivially copyable and has no destructor).
53///
54/// Recursively checks all fields of aggregate types (tuples/structs/arrays) to ensure none require drop.
55/// Used for optimization in alias analysis or memory management.
56///
57/// # Arguments
58/// * `tcx` - The type context from rustc.
59/// * `ty` - The type to check.
60///
61/// # Returns
62/// * `true` if the type and all its components are trivially "not drop", `false` otherwise.
63pub fn is_not_drop<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
64    match ty.kind() {
65        // Primitive types that never require drop.
66        ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => true,
67        // For arrays, check element type.
68        ty::Array(tys, _) => is_not_drop(tcx, *tys),
69        // For ADTs (structs, enums), check all fields.
70        ty::Adt(adtdef, substs) => {
71            for field in adtdef.all_fields() {
72                #[cfg(not(rapx_rustc_ge_198))]
73                let fty = field.ty(tcx, substs);
74                #[cfg(rapx_rustc_ge_198)]
75                let fty = field.ty(tcx, substs).skip_norm_wip();
76                if !is_not_drop(tcx, fty) {
77                    return false;
78                }
79            }
80            true
81        }
82        // For tuples, check each element recursively.
83        ty::Tuple(tuple_fields) => {
84            for tys in tuple_fields.iter() {
85                if !is_not_drop(tcx, tys) {
86                    return false;
87                }
88            }
89            true
90        }
91        // All other types may require drop.
92        _ => false,
93    }
94}