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
50impl Rvalue {
51 pub fn unit_value() -> Self {
52 Rvalue::Aggregate(
53 AggregateKind::Adt(
54 TypeId::Tuple,
55 None,
56 None,
57 GenericArgs::empty(GenericsSource::Builtin),
58 ),
59 Vec::new(),
60 )
61 }
62}
63
64impl BorrowKind {
65 pub fn mutable(x: bool) -> Self {
66 if x {
67 Self::Mut
68 } else {
69 Self::Shared
70 }
71 }
72}
73
74impl ProjectionElem {
75 pub fn project_type(
77 &self,
78 type_decls: &Vector<TypeDeclId, TypeDecl>,
79 ty: &Ty,
80 ) -> Result<Ty, ()> {
81 use ProjectionElem::*;
82 Ok(match self {
83 Deref => {
84 use TyKind::*;
85 match ty.kind() {
86 Ref(_, ty, _) | RawPtr(ty, _) => ty.clone(),
87 Adt(TypeId::Builtin(BuiltinTy::Box), args) => {
88 args.types.get(TypeVarId::new(0)).unwrap().clone()
89 }
90 Adt(..) | TypeVar(_) | Literal(_) | Never | TraitType(..) | DynTrait(_)
91 | Arrow(..) | Error(..) => {
92 return Err(());
94 }
95 }
96 }
97 Field(pkind, field_id) => {
98 use FieldProjKind::*;
100 match pkind {
101 Adt(type_decl_id, variant_id) => {
102 let type_decl = type_decls.get(*type_decl_id).ok_or(())?;
104 let (type_id, generics) = ty.as_adt().ok_or(())?;
105 assert!(TypeId::Adt(*type_decl_id) == type_id);
106 assert!(
107 generics.regions.elem_count()
108 == type_decl.generics.regions.elem_count()
109 );
110 assert!(
111 generics.types.elem_count() == type_decl.generics.types.elem_count()
112 );
113 assert!(
114 generics.const_generics.elem_count()
115 == type_decl.generics.const_generics.elem_count()
116 );
117 assert!(
118 generics.trait_refs.elem_count()
119 == type_decl.generics.trait_clauses.elem_count()
120 );
121 use TypeDeclKind::*;
122 match &type_decl.kind {
123 Struct(fields) | Union(fields) => {
124 if variant_id.is_some() {
125 return Err(());
126 };
127 fields
128 .get(*field_id)
129 .ok_or(())?
130 .ty
131 .clone()
132 .substitute(generics)
133 }
134 Enum(variants) => {
135 let variant_id = variant_id.ok_or(())?;
136 let variant = variants.get(variant_id).ok_or(())?;
137 variant
138 .fields
139 .get(*field_id)
140 .ok_or(())?
141 .ty
142 .clone()
143 .substitute(generics)
144 }
145 Opaque | Alias(_) | Error(_) => return Err(()),
146 }
147 }
148 Tuple(_) => ty
149 .as_tuple()
150 .ok_or(())?
151 .get(TypeVarId::from(usize::from(*field_id)))
152 .ok_or(())?
153 .clone(),
154 ClosureState => return Err(()),
155 }
156 }
157 Index { .. } | Subslice { .. } => ty.as_array_or_slice().ok_or(())?.clone(),
158 })
159 }
160}