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(self, krate: &TranslatedCrate, proj: ProjectionElem) -> Option<Self> {
57 Some(Place {
58 ty: proj.project_type(krate, &self.ty)?,
59 kind: PlaceKind::Projection(Box::new(self), proj),
60 })
61 }
62
63 pub fn deref(self) -> Place {
65 use TyKind::*;
66 let proj_ty = match self.ty.kind() {
67 Ref(_, ty, _) | RawPtr(ty, _) => ty.clone(),
68 Adt(tref) if matches!(tref.id, TypeId::Builtin(BuiltinTy::Box)) => {
69 tref.generics.types[0].clone()
70 }
71 Adt(..) | TypeVar(_) | Literal(_) | Never | TraitType(..) | DynTrait(..)
72 | FnPtr(..) | FnDef(..) | PtrMetadata(..) | Array(..) | Slice(_) | Pattern(..)
73 | Error(..) => {
74 panic!("internal type error")
75 }
76 };
77 Place {
78 ty: proj_ty,
79 kind: PlaceKind::Projection(Box::new(self), ProjectionElem::Deref),
80 }
81 }
82
83 pub fn projections(&self) -> impl Iterator<Item = &ProjectionElem> {
84 let mut place = self;
85 std::iter::from_fn(move || {
86 let (new_place, proj) = place.as_projection()?;
87 place = new_place;
88 Some(proj)
89 })
90 }
91}
92
93impl ConstantExpr {
94 pub fn mk_unit() -> Self {
95 ConstantExpr {
96 kind: ConstantExprKind::Adt(None, Vec::new()),
97 ty: Ty::mk_unit(),
98 }
99 }
100
101 pub fn mk_usize(scalar: ScalarValue) -> Self {
102 ConstantExpr {
103 kind: ConstantExprKind::Literal(Literal::Scalar(scalar)),
104 ty: Ty::mk_usize(),
105 }
106 }
107}
108
109impl Operand {
110 pub fn mk_const_unit() -> Self {
111 Operand::Const(Box::new(ConstantExpr::mk_unit()))
112 }
113
114 pub fn ty(&self) -> &Ty {
115 match self {
116 Operand::Copy(place) | Operand::Move(place) => place.ty(),
117 Operand::Const(constant_expr) => &constant_expr.ty,
118 }
119 }
120}
121
122impl Rvalue {
123 pub fn unit_value() -> Self {
124 Rvalue::Aggregate(
125 AggregateKind::Adt(
126 TypeDeclRef {
127 id: TypeId::Tuple,
128 generics: Box::new(GenericArgs::empty()),
129 },
130 None,
131 None,
132 ),
133 Vec::new(),
134 )
135 }
136}
137
138impl BorrowKind {
139 pub fn mutable(x: bool) -> Self {
140 if x { Self::Mut } else { Self::Shared }
141 }
142}
143
144impl From<BorrowKind> for RefKind {
145 fn from(value: BorrowKind) -> Self {
146 match value {
147 BorrowKind::Shared | BorrowKind::Shallow => RefKind::Shared,
148 BorrowKind::Mut | BorrowKind::TwoPhaseMut | BorrowKind::UniqueImmutable => RefKind::Mut,
149 }
150 }
151}
152
153impl From<RefKind> for BorrowKind {
154 fn from(value: RefKind) -> Self {
155 match value {
156 RefKind::Shared => BorrowKind::Shared,
157 RefKind::Mut => BorrowKind::Mut,
158 }
159 }
160}
161
162impl ProjectionElem {
163 pub fn project_type(&self, krate: &TranslatedCrate, ty: &Ty) -> Option<Ty> {
165 use ProjectionElem::*;
166 Some(match self {
167 Deref => {
168 use TyKind::*;
169 match ty.kind() {
170 Ref(_, ty, _) | RawPtr(ty, _) => ty.clone(),
171 Adt(tref) if matches!(tref.id, TypeId::Builtin(BuiltinTy::Box)) => {
172 tref.generics.types[0].clone()
173 }
174 Adt(..) | TypeVar(_) | Literal(_) | Never | TraitType(..) | DynTrait(..)
175 | Array(..) | Slice(..) | FnPtr(..) | FnDef(..) | PtrMetadata(..)
176 | Pattern(..) | Error(..) => {
177 return None;
179 }
180 }
181 }
182 Field(pkind, field_id) => {
183 use FieldProjKind::*;
185 match pkind {
186 Adt(type_decl_id, variant_id) => {
187 let type_decl = krate.type_decls.get(*type_decl_id)?;
189 let tref = ty.as_adt()?;
190 assert!(TypeId::Adt(*type_decl_id) == tref.id);
191 use TypeDeclKind::*;
192 match &type_decl.kind {
193 Struct(fields) | Union(fields) => {
194 if variant_id.is_some() {
195 return None;
196 };
197 fields.get(*field_id)?.ty.clone().substitute(&tref.generics)
198 }
199 Enum(variants) => {
200 let variant_id = (*variant_id)?;
201 let variant = variants.get(variant_id)?;
202 variant
203 .fields
204 .get(*field_id)?
205 .ty
206 .clone()
207 .substitute(&tref.generics)
208 }
209 Opaque | Alias(_) | Error(_) => return None,
210 }
211 }
212 Tuple(_) => ty
213 .as_tuple()?
214 .get(TypeVarId::from(usize::from(*field_id)))?
215 .clone(),
216 }
217 }
218 PtrMetadata => ty.get_ptr_metadata(krate).into_type(),
219 Index { .. } | Subslice { .. } => ty.as_array_or_slice()?.clone(),
220 })
221 }
222}
223
224impl BinOp {
225 pub fn with_overflow(&self, overflow: OverflowMode) -> Self {
226 match self {
227 BinOp::Add(_) | BinOp::AddChecked => BinOp::Add(overflow),
228 BinOp::Sub(_) | BinOp::SubChecked => BinOp::Sub(overflow),
229 BinOp::Mul(_) | BinOp::MulChecked => BinOp::Mul(overflow),
230 BinOp::Div(_) => BinOp::Div(overflow),
231 BinOp::Rem(_) => BinOp::Rem(overflow),
232 BinOp::Shl(_) => BinOp::Shl(overflow),
233 BinOp::Shr(_) => BinOp::Shr(overflow),
234 _ => {
235 panic!(
236 "Cannot set overflow mode for this binary operator: {:?}",
237 self
238 );
239 }
240 }
241 }
242}
243
244impl UnOp {
245 pub fn with_overflow(&self, overflow: OverflowMode) -> Self {
246 match self {
247 UnOp::Neg(_) => UnOp::Neg(overflow),
248 _ => {
249 panic!(
250 "Cannot set overflow mode for this unary operator: {:?}",
251 self
252 );
253 }
254 }
255 }
256}
257
258impl FnPtr {
259 pub fn new(kind: FnPtrKind, generics: impl Into<BoxedArgs>) -> Self {
260 Self {
261 kind: Box::new(kind),
262 generics: generics.into(),
263 }
264 }
265
266 pub fn pre_mono_generics<'a>(&'a self, krate: &'a TranslatedCrate) -> &'a GenericArgs {
268 match *self.kind {
269 FnPtrKind::Fun(FunId::Regular(fun_id)) => krate
270 .item_name(fun_id)
271 .mono_args()
272 .unwrap_or(&self.generics),
273 FnPtrKind::Fun(FunId::Builtin(..)) => &self.generics,
275 FnPtrKind::Trait(..) => &self.generics,
277 }
278 }
279}