Skip to main content

charon_lib/ast/
gast_utils.rs

1//! Implementations for [crate::gast]
2
3use crate::ast::*;
4
5impl FnPtrKind {
6    pub fn mk_builtin(aid: BuiltinFunId) -> Self {
7        Self::Fun(FunId::Builtin(aid))
8    }
9}
10
11impl GlobalDecl {
12    /// If this global's value is a call to its initializer function, returns the initializer's id.
13    pub fn init_fun_id(&self) -> Option<FunDeclId> {
14        match &self.value.kind {
15            ConstantExprKind::Call(fn_ptr, _) => match &*fn_ptr.kind {
16                FnPtrKind::Fun(FunId::Regular(id)) => Some(*id),
17                _ => None,
18            },
19            _ => None,
20        }
21    }
22}
23
24impl Body {
25    /// Whether there is an actual body with statements etc, as opposed to the body being missing
26    /// for some reason.
27    pub fn has_contents(&self) -> bool {
28        match self {
29            Body::Unstructured(..) | Body::Structured(..) => true,
30            Body::TraitMethodWithoutDefault
31            | Body::Extern(..)
32            | Body::Intrinsic { .. }
33            | Body::Opaque
34            | Body::Missing
35            | Body::Error(..)
36            | Body::TargetDispatch(..) => false,
37        }
38    }
39
40    pub fn locals(&self) -> &Locals {
41        match self {
42            Body::Structured(body) => &body.locals,
43            Body::Unstructured(body) => &body.locals,
44            _ => panic!("called `locals` on a missing body"),
45        }
46    }
47}
48
49impl Locals {
50    pub fn new(arg_count: usize) -> Self {
51        Self {
52            arg_count,
53            locals: Default::default(),
54        }
55    }
56
57    /// Creates a new variable and returns a place pointing to it.
58    /// Warning: don't forget to `StorageLive` it before using it.
59    pub fn new_var(&mut self, name: Option<String>, ty: Ty) -> Place {
60        let local_id = self.locals.push_with(|index| Local {
61            index,
62            name,
63            span: Span::dummy(),
64            ty: ty.clone(),
65        });
66        Place::new(local_id, ty)
67    }
68
69    /// Gets a place pointing to the corresponding variable.
70    pub fn place_for_var(&self, local_id: LocalId) -> Place {
71        let ty = self.locals[local_id].ty.clone();
72        Place::new(local_id, ty)
73    }
74
75    /// Returns whether this local is the special return local or one of the input argument locals.
76    pub fn is_return_or_arg(&self, lid: LocalId) -> bool {
77        lid.index() <= self.arg_count
78    }
79
80    /// The place where we write the return value.
81    pub fn return_place(&self) -> Place {
82        self.place_for_var(LocalId::new(0))
83    }
84
85    /// Locals that aren't arguments or return values.
86    pub fn non_argument_locals(&self) -> impl Iterator<Item = (LocalId, &Local)> {
87        self.locals.iter_enumerated().skip(1 + self.arg_count)
88    }
89}
90
91impl std::ops::Index<LocalId> for Locals {
92    type Output = Local;
93    fn index(&self, local_id: LocalId) -> &Self::Output {
94        &self.locals[local_id]
95    }
96}
97impl std::ops::IndexMut<LocalId> for Locals {
98    fn index_mut(&mut self, local_id: LocalId) -> &mut Self::Output {
99        &mut self.locals[local_id]
100    }
101}
102
103impl FunDecl {
104    /// Replace the generic parameters of this function with the ones given by the binder.
105    pub fn substitute_params(self, subst: Binder<GenericArgs>) -> Self {
106        let FunDecl {
107            def_id,
108            item_meta,
109            generics: _,
110            signature,
111            src,
112            is_global_initializer,
113            body,
114        } = self;
115        let signature = signature.substitute(&subst.skip_binder);
116        let src = src.substitute(&subst.skip_binder);
117        let body = body.substitute(&subst.skip_binder);
118        FunDecl {
119            def_id,
120            item_meta,
121            generics: subst.params,
122            signature,
123            src,
124            is_global_initializer,
125            body,
126        }
127    }
128}
129impl TraitDecl {
130    pub fn methods(&self) -> impl Iterator<Item = &Binder<TraitMethod>> {
131        self.methods.iter()
132    }
133}
134impl TraitImpl {
135    pub fn methods(&self) -> impl Iterator<Item = &Binder<FunDeclRef>> {
136        self.methods.iter()
137    }
138}
139
140impl Binder<TraitAssocTy> {
141    pub fn name(&self) -> &TraitItemName {
142        &self.skip_binder.name
143    }
144}
145impl Binder<TraitMethod> {
146    pub fn name(&self) -> TraitItemName {
147        self.skip_binder.name
148    }
149}