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