charon_lib/ast/
expressions_utils.rs1use crate::ast::*;
3use crate::ids::Vector;
4
5impl Place {
6 pub fn new(local_id: LocalId, ty: Ty) -> Place {
7 Place {
8 kind: PlaceKind::Local(local_id),
9 ty,
10 }
11 }
12
13 pub fn ty(&self) -> &Ty {
14 &self.ty
15 }
16
17 pub fn is_local(&self) -> bool {
19 self.as_local().is_some()
20 }
21
22 pub fn as_local(&self) -> Option<LocalId> {
24 self.kind.as_local().copied()
25 }
26
27 pub fn as_projection(&self) -> Option<(&Self, &ProjectionElem)> {
28 self.kind.as_projection().map(|(pl, pj)| (pl.as_ref(), pj))
29 }
30
31 #[deprecated(note = "use `local_id` instead")]
32 pub fn var_id(&self) -> LocalId {
33 self.local_id()
34 }
35 pub fn local_id(&self) -> LocalId {
36 match &self.kind {
37 PlaceKind::Local(var_id) => *var_id,
38 PlaceKind::Projection(subplace, _) => subplace.local_id(),
39 }
40 }
41
42 pub fn project(self, elem: ProjectionElem, ty: Ty) -> Self {
43 Self {
44 kind: PlaceKind::Projection(Box::new(self), elem),
45 ty,
46 }
47 }
48
49 pub fn projections<'a>(&'a self) -> impl Iterator<Item = &'a ProjectionElem> {
50 let mut place = self;
51 std::iter::from_fn(move || {
52 let (new_place, proj) = place.as_projection()?;
53 place = new_place;
54 Some(proj)
55 })
56 }
57}
58
59impl Rvalue {
60 pub fn unit_value() -> Self {
61 Rvalue::Aggregate(
62 AggregateKind::Adt(
63 TypeId::Tuple,
64 None,
65 None,
66 Box::new(GenericArgs::empty(GenericsSource::Builtin)),
67 ),
68 Vec::new(),
69 )
70 }
71}
72
73impl BorrowKind {
74 pub fn mutable(x: bool) -> Self {
75 if x {
76 Self::Mut
77 } else {
78 Self::Shared
79 }
80 }
81}
82
83impl ProjectionElem {
84 pub fn project_type(
86 &self,
87 type_decls: &Vector<TypeDeclId, TypeDecl>,
88 ty: &Ty,
89 ) -> Result<Ty, ()> {
90 use ProjectionElem::*;
91 Ok(match self {
92 Deref => {
93 use TyKind::*;
94 match ty.kind() {
95 Ref(_, ty, _) | RawPtr(ty, _) => ty.clone(),
96 Adt(TypeId::Builtin(BuiltinTy::Box), args) => {
97 args.types.get(TypeVarId::new(0)).unwrap().clone()
98 }
99 Adt(..)
100 | TypeVar(_)
101 | Literal(_)
102 | Never
103 | TraitType(..)
104 | DynTrait(_)
105 | Arrow(..)
106 | Closure { .. }
107 | Error(..) => {
108 return Err(());
110 }
111 }
112 }
113 Field(pkind, field_id) => {
114 use FieldProjKind::*;
116 match pkind {
117 Adt(type_decl_id, variant_id) => {
118 let type_decl = type_decls.get(*type_decl_id).ok_or(())?;
120 let (type_id, generics) = ty.as_adt().ok_or(())?;
121 assert!(TypeId::Adt(*type_decl_id) == type_id);
122 use TypeDeclKind::*;
123 match &type_decl.kind {
124 Struct(fields) | Union(fields) => {
125 if variant_id.is_some() {
126 return Err(());
127 };
128 fields
129 .get(*field_id)
130 .ok_or(())?
131 .ty
132 .clone()
133 .substitute(generics)
134 }
135 Enum(variants) => {
136 let variant_id = variant_id.ok_or(())?;
137 let variant = variants.get(variant_id).ok_or(())?;
138 variant
139 .fields
140 .get(*field_id)
141 .ok_or(())?
142 .ty
143 .clone()
144 .substitute(generics)
145 }
146 Opaque | Alias(_) | Error(_) => return Err(()),
147 }
148 }
149 Tuple(_) => ty
150 .as_tuple()
151 .ok_or(())?
152 .get(TypeVarId::from(usize::from(*field_id)))
153 .ok_or(())?
154 .clone(),
155 ClosureState => return Err(()),
156 }
157 }
158 Index { .. } | Subslice { .. } => ty.as_array_or_slice().ok_or(())?.clone(),
159 })
160 }
161}