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