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