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::Extern(..)
31            | Body::Intrinsic { .. }
32            | Body::Opaque
33            | Body::Missing
34            | Body::Error(..)
35            | Body::TargetDispatch(..) => false,
36        }
37    }
38
39    pub fn locals(&self) -> &Locals {
40        match self {
41            Body::Structured(body) => &body.locals,
42            Body::Unstructured(body) => &body.locals,
43            _ => panic!("called `locals` on a missing body"),
44        }
45    }
46}
47
48impl Locals {
49    pub fn new(arg_count: usize) -> Self {
50        Self {
51            arg_count,
52            locals: Default::default(),
53        }
54    }
55
56    /// Creates a new variable and returns a place pointing to it.
57    /// Warning: don't forget to `StorageLive` it before using it.
58    pub fn new_var(&mut self, name: Option<String>, ty: Ty) -> Place {
59        let local_id = self.locals.push_with(|index| Local {
60            index,
61            name,
62            span: Span::dummy(),
63            ty: ty.clone(),
64        });
65        Place::new(local_id, ty)
66    }
67
68    /// Gets a place pointing to the corresponding variable.
69    pub fn place_for_var(&self, local_id: LocalId) -> Place {
70        let ty = self.locals[local_id].ty.clone();
71        Place::new(local_id, ty)
72    }
73
74    /// Returns whether this local is the special return local or one of the input argument locals.
75    pub fn is_return_or_arg(&self, lid: LocalId) -> bool {
76        lid.index() <= self.arg_count
77    }
78
79    /// The place where we write the return value.
80    pub fn return_place(&self) -> Place {
81        self.place_for_var(LocalId::new(0))
82    }
83
84    /// Locals that aren't arguments or return values.
85    pub fn non_argument_locals(&self) -> impl Iterator<Item = (LocalId, &Local)> {
86        self.locals.iter_enumerated().skip(1 + self.arg_count)
87    }
88}
89
90impl std::ops::Index<LocalId> for Locals {
91    type Output = Local;
92    fn index(&self, local_id: LocalId) -> &Self::Output {
93        &self.locals[local_id]
94    }
95}
96impl std::ops::IndexMut<LocalId> for Locals {
97    fn index_mut(&mut self, local_id: LocalId) -> &mut Self::Output {
98        &mut self.locals[local_id]
99    }
100}
101
102impl FunDecl {
103    /// Replace the generic parameters of this function with the ones given by the binder.
104    pub fn substitute_params(self, subst: Binder<GenericArgs>) -> Self {
105        let FunDecl {
106            def_id,
107            item_meta,
108            generics: _,
109            signature,
110            src,
111            is_global_initializer,
112            body,
113        } = self;
114        let signature = signature.substitute(&subst.skip_binder);
115        let src = src.substitute(&subst.skip_binder);
116        let body = body.substitute(&subst.skip_binder);
117        FunDecl {
118            def_id,
119            item_meta,
120            generics: subst.params,
121            signature,
122            src,
123            is_global_initializer,
124            body,
125        }
126    }
127}
128impl TraitDecl {
129    pub fn methods(&self) -> impl Iterator<Item = &Binder<TraitMethod>> {
130        self.methods.iter()
131    }
132}
133impl TraitImpl {
134    pub fn methods(&self) -> impl Iterator<Item = &Binder<FunDeclRef>> {
135        self.methods.iter()
136    }
137}
138
139impl Binder<TraitAssocTy> {
140    pub fn name(&self) -> &TraitItemName {
141        &self.skip_binder.name
142    }
143}
144impl Binder<TraitMethod> {
145    pub fn name(&self) -> TraitItemName {
146        self.skip_binder.name
147    }
148}