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