charon_lib/ast/
expressions_utils.rs1use crate::ast::*;
3
4impl Place {
5 pub fn new(local_id: LocalId, ty: Ty) -> Place {
6 Place {
7 kind: PlaceKind::Local(local_id),
8 ty,
9 }
10 }
11
12 pub fn new_global(global: GlobalDeclRef, ty: Ty) -> Place {
13 Place {
14 kind: PlaceKind::Global(global),
15 ty,
16 }
17 }
18
19 pub fn ty(&self) -> &Ty {
20 &self.ty
21 }
22
23 pub fn is_local(&self) -> bool {
25 self.as_local().is_some()
26 }
27
28 pub fn as_local(&self) -> Option<LocalId> {
30 self.kind.as_local().copied()
31 }
32
33 pub fn as_projection(&self) -> Option<(&Self, &ProjectionElem)> {
34 self.kind.as_projection().map(|(pl, pj)| (pl.as_ref(), pj))
35 }
36
37 #[deprecated(note = "use `local_id` instead")]
38 pub fn var_id(&self) -> Option<LocalId> {
39 self.local_id()
40 }
41 pub fn local_id(&self) -> Option<LocalId> {
42 match &self.kind {
43 PlaceKind::Local(var_id) => Some(*var_id),
44 PlaceKind::Projection(subplace, _) => subplace.local_id(),
45 PlaceKind::Global(_) => None,
46 }
47 }
48
49 pub fn project(self, elem: ProjectionElem, ty: Ty) -> Self {
50 Self {
51 kind: PlaceKind::Projection(Box::new(self), elem),
52 ty,
53 }
54 }
55
56 pub fn project_auto_ty(
57 self,
58 krate: &TranslatedCrate,
59 proj: ProjectionElem,
60 ) -> Result<Self, ()> {
61 Ok(Place {
62 ty: proj.project_type(krate, &self.ty)?,
63 kind: PlaceKind::Projection(Box::new(self), proj),
64 })
65 }
66
67 pub fn deref(self) -> Place {
69 use TyKind::*;
70 let proj_ty = match self.ty.kind() {
71 Ref(_, ty, _) | RawPtr(ty, _) => ty.clone(),
72 Adt(tref) if matches!(tref.id, TypeId::Builtin(BuiltinTy::Box)) => {
73 tref.generics.types[0].clone()
74 }
75 Adt(..) | TypeVar(_) | Literal(_) | Never | TraitType(..) | DynTrait(..)
76 | FnPtr(..) | FnDef(..) | PtrMetadata(..) | Error(..) => panic!("internal type error"),
77 };
78 Place {
79 ty: proj_ty,
80 kind: PlaceKind::Projection(Box::new(self), ProjectionElem::Deref),
81 }
82 }
83
84 pub fn projections<'a>(&'a self) -> impl Iterator<Item = &'a ProjectionElem> {
85 let mut place = self;
86 std::iter::from_fn(move || {
87 let (new_place, proj) = place.as_projection()?;
88 place = new_place;
89 Some(proj)
90 })
91 }
92}
93
94impl Operand {
95 pub fn mk_const_unit() -> Self {
96 Operand::Const(Box::new(ConstantExpr {
97 kind: ConstantExprKind::Adt(None, Vec::new()),
98 ty: Ty::mk_unit(),
99 }))
100 }
101
102 pub fn ty(&self) -> &Ty {
103 match self {
104 Operand::Copy(place) | Operand::Move(place) => place.ty(),
105 Operand::Const(constant_expr) => &constant_expr.ty,
106 }
107 }
108}
109
110impl Rvalue {
111 pub fn unit_value() -> Self {
112 Rvalue::Aggregate(
113 AggregateKind::Adt(
114 TypeDeclRef {
115 id: TypeId::Tuple,
116 generics: Box::new(GenericArgs::empty()),
117 },
118 None,
119 None,
120 ),
121 Vec::new(),
122 )
123 }
124}
125
126impl BorrowKind {
127 pub fn mutable(x: bool) -> Self {
128 if x { Self::Mut } else { Self::Shared }
129 }
130}
131
132impl ProjectionElem {
133 pub fn project_type(&self, krate: &TranslatedCrate, ty: &Ty) -> Result<Ty, ()> {
135 use ProjectionElem::*;
136 Ok(match self {
137 Deref => {
138 use TyKind::*;
139 match ty.kind() {
140 Ref(_, ty, _) | RawPtr(ty, _) => ty.clone(),
141 Adt(tref) if matches!(tref.id, TypeId::Builtin(BuiltinTy::Box)) => {
142 tref.generics.types[0].clone()
143 }
144 Adt(..) | TypeVar(_) | Literal(_) | Never | TraitType(..) | DynTrait(..)
145 | FnPtr(..) | FnDef(..) | PtrMetadata(..) | Error(..) => {
146 return Err(());
148 }
149 }
150 }
151 Field(pkind, field_id) => {
152 use FieldProjKind::*;
154 match pkind {
155 Adt(type_decl_id, variant_id) => {
156 let type_decl = krate.type_decls.get(*type_decl_id).ok_or(())?;
158 let tref = ty.as_adt().ok_or(())?;
159 assert!(TypeId::Adt(*type_decl_id) == tref.id);
160 use TypeDeclKind::*;
161 match &type_decl.kind {
162 Struct(fields) | Union(fields) => {
163 if variant_id.is_some() {
164 return Err(());
165 };
166 fields
167 .get(*field_id)
168 .ok_or(())?
169 .ty
170 .clone()
171 .substitute(&tref.generics)
172 }
173 Enum(variants) => {
174 let variant_id = variant_id.ok_or(())?;
175 let variant = variants.get(variant_id).ok_or(())?;
176 variant
177 .fields
178 .get(*field_id)
179 .ok_or(())?
180 .ty
181 .clone()
182 .substitute(&tref.generics)
183 }
184 Opaque | Alias(_) | Error(_) => return Err(()),
185 }
186 }
187 Tuple(_) => ty
188 .as_tuple()
189 .ok_or(())?
190 .get(TypeVarId::from(usize::from(*field_id)))
191 .ok_or(())?
192 .clone(),
193 }
194 }
195 PtrMetadata => ty.get_ptr_metadata(krate).into_type(),
196 Index { .. } | Subslice { .. } => ty.as_array_or_slice().ok_or(())?.clone(),
197 })
198 }
199}
200
201impl From<ConstGeneric> for ConstantExprKind {
202 fn from(cg: ConstGeneric) -> Self {
203 match cg {
204 ConstGeneric::Global(id) => ConstantExprKind::Global(GlobalDeclRef {
205 id,
206 generics: Box::new(GenericArgs::empty()),
207 }),
208 ConstGeneric::Var(var) => ConstantExprKind::Var(var),
209 ConstGeneric::Value(lit) => ConstantExprKind::Literal(lit),
210 }
211 }
212}
213
214impl BinOp {
215 pub fn with_overflow(&self, overflow: OverflowMode) -> Self {
216 match self {
217 BinOp::Add(_) | BinOp::AddChecked => BinOp::Add(overflow),
218 BinOp::Sub(_) | BinOp::SubChecked => BinOp::Sub(overflow),
219 BinOp::Mul(_) | BinOp::MulChecked => BinOp::Mul(overflow),
220 BinOp::Div(_) => BinOp::Div(overflow),
221 BinOp::Rem(_) => BinOp::Rem(overflow),
222 BinOp::Shl(_) => BinOp::Shl(overflow),
223 BinOp::Shr(_) => BinOp::Shr(overflow),
224 _ => {
225 panic!(
226 "Cannot set overflow mode for this binary operator: {:?}",
227 self
228 );
229 }
230 }
231 }
232}
233
234impl UnOp {
235 pub fn with_overflow(&self, overflow: OverflowMode) -> Self {
236 match self {
237 UnOp::Neg(_) => UnOp::Neg(overflow),
238 _ => {
239 panic!(
240 "Cannot set overflow mode for this unary operator: {:?}",
241 self
242 );
243 }
244 }
245 }
246}