charon_lib/ast/
expressions_utils.rs
1use 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 project_auto_ty(
50 self,
51 type_decls: &Vector<TypeDeclId, TypeDecl>,
52 proj: ProjectionElem,
53 ) -> Result<Self, ()> {
54 Ok(Place {
55 ty: proj.project_type(type_decls, &self.ty)?,
56 kind: PlaceKind::Projection(Box::new(self), proj),
57 })
58 }
59
60 pub fn deref(self) -> Place {
62 use TyKind::*;
63 let proj_ty = match self.ty.kind() {
64 Ref(_, ty, _) | RawPtr(ty, _) => ty.clone(),
65 Adt(tref) if matches!(tref.id, TypeId::Builtin(BuiltinTy::Box)) => {
66 tref.generics.types[0].clone()
67 }
68 Adt(..) | TypeVar(_) | Literal(_) | Never | TraitType(..) | DynTrait(_) | FnPtr(..)
69 | FnDef(..) | Error(..) => panic!("internal type error"),
70 };
71 Place {
72 ty: proj_ty,
73 kind: PlaceKind::Projection(Box::new(self), ProjectionElem::Deref),
74 }
75 }
76
77 pub fn projections<'a>(&'a self) -> impl Iterator<Item = &'a ProjectionElem> {
78 let mut place = self;
79 std::iter::from_fn(move || {
80 let (new_place, proj) = place.as_projection()?;
81 place = new_place;
82 Some(proj)
83 })
84 }
85}
86
87impl Rvalue {
88 pub fn unit_value() -> Self {
89 Rvalue::Aggregate(
90 AggregateKind::Adt(
91 TypeDeclRef {
92 id: TypeId::Tuple,
93 generics: Box::new(GenericArgs::empty()),
94 },
95 None,
96 None,
97 ),
98 Vec::new(),
99 )
100 }
101}
102
103impl BorrowKind {
104 pub fn mutable(x: bool) -> Self {
105 if x {
106 Self::Mut
107 } else {
108 Self::Shared
109 }
110 }
111}
112
113impl ProjectionElem {
114 pub fn project_type(
116 &self,
117 type_decls: &Vector<TypeDeclId, TypeDecl>,
118 ty: &Ty,
119 ) -> Result<Ty, ()> {
120 use ProjectionElem::*;
121 Ok(match self {
122 Deref => {
123 use TyKind::*;
124 match ty.kind() {
125 Ref(_, ty, _) | RawPtr(ty, _) => ty.clone(),
126 Adt(tref) if matches!(tref.id, TypeId::Builtin(BuiltinTy::Box)) => {
127 tref.generics.types[0].clone()
128 }
129 Adt(..) | TypeVar(_) | Literal(_) | Never | TraitType(..) | DynTrait(_)
130 | FnPtr(..) | FnDef(..) | Error(..) => {
131 return Err(());
133 }
134 }
135 }
136 Field(pkind, field_id) => {
137 use FieldProjKind::*;
139 match pkind {
140 Adt(type_decl_id, variant_id) => {
141 let type_decl = type_decls.get(*type_decl_id).ok_or(())?;
143 let tref = ty.as_adt().ok_or(())?;
144 assert!(TypeId::Adt(*type_decl_id) == tref.id);
145 use TypeDeclKind::*;
146 match &type_decl.kind {
147 Struct(fields) | Union(fields) => {
148 if variant_id.is_some() {
149 return Err(());
150 };
151 fields
152 .get(*field_id)
153 .ok_or(())?
154 .ty
155 .clone()
156 .substitute(&tref.generics)
157 }
158 Enum(variants) => {
159 let variant_id = variant_id.ok_or(())?;
160 let variant = variants.get(variant_id).ok_or(())?;
161 variant
162 .fields
163 .get(*field_id)
164 .ok_or(())?
165 .ty
166 .clone()
167 .substitute(&tref.generics)
168 }
169 Opaque | Alias(_) | Error(_) => return Err(()),
170 }
171 }
172 Tuple(_) => ty
173 .as_tuple()
174 .ok_or(())?
175 .get(TypeVarId::from(usize::from(*field_id)))
176 .ok_or(())?
177 .clone(),
178 }
179 }
180 Index { .. } | Subslice { .. } => ty.as_array_or_slice().ok_or(())?.clone(),
181 })
182 }
183}