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