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 | 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            span: Span::dummy(),
47            ty: ty.clone(),
48        });
49        Place::new(local_id, ty)
50    }
51
52    /// Gets a place pointing to the corresponding variable.
53    pub fn place_for_var(&self, local_id: LocalId) -> Place {
54        let ty = self.locals[local_id].ty.clone();
55        Place::new(local_id, ty)
56    }
57
58    /// Returns whether this local is the special return local or one of the input argument locals.
59    pub fn is_return_or_arg(&self, lid: LocalId) -> bool {
60        lid.index() <= self.arg_count
61    }
62
63    /// The place where we write the return value.
64    pub fn return_place(&self) -> Place {
65        self.place_for_var(LocalId::new(0))
66    }
67
68    /// Locals that aren't arguments or return values.
69    pub fn non_argument_locals(&self) -> impl Iterator<Item = (LocalId, &Local)> {
70        self.locals.iter_indexed().skip(1 + self.arg_count)
71    }
72}
73
74impl std::ops::Index<LocalId> for Locals {
75    type Output = Local;
76    fn index(&self, local_id: LocalId) -> &Self::Output {
77        &self.locals[local_id]
78    }
79}
80impl std::ops::IndexMut<LocalId> for Locals {
81    fn index_mut(&mut self, local_id: LocalId) -> &mut Self::Output {
82        &mut self.locals[local_id]
83    }
84}
85
86impl FunDecl {
87    /// Replace the generic parameters of this function with the ones given by the binder.
88    pub fn substitute_params(self, subst: Binder<GenericArgs>) -> Self {
89        let FunDecl {
90            def_id,
91            item_meta,
92            generics: _,
93            signature,
94            src,
95            is_global_initializer,
96            body,
97        } = self;
98        let signature = signature.substitute(&subst.skip_binder);
99        let src = src.substitute(&subst.skip_binder);
100        let body = body.substitute(&subst.skip_binder);
101        FunDecl {
102            def_id,
103            item_meta,
104            generics: subst.params,
105            signature,
106            src,
107            is_global_initializer,
108            body,
109        }
110    }
111}
112impl TraitDecl {
113    pub fn methods(&self) -> impl Iterator<Item = &Binder<TraitMethod>> {
114        self.methods.iter()
115    }
116}
117impl TraitImpl {
118    pub fn methods(&self) -> impl Iterator<Item = &(TraitItemName, Binder<FunDeclRef>)> {
119        self.methods.iter()
120    }
121}
122
123impl Binder<TraitAssocTy> {
124    pub fn name(&self) -> &TraitItemName {
125        &self.skip_binder.name
126    }
127}
128impl Binder<TraitMethod> {
129    pub fn name(&self) -> TraitItemName {
130        self.skip_binder.name
131    }
132}