2 * Methods for the various MIR types. These are intended for use after
3 * building is complete.
7 use crate::ty
::subst
::Subst
;
8 use crate::ty
::{self, Ty, TyCtxt}
;
9 use crate::ty
::layout
::VariantIdx
;
11 use crate::ty
::util
::IntTypeExt
;
13 #[derive(Copy, Clone, Debug, TypeFoldable)]
14 pub struct PlaceTy
<'tcx
> {
16 /// Downcast to a particular variant of an enum, if included.
17 pub variant_index
: Option
<VariantIdx
>,
20 // At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers.
21 #[cfg(target_arch = "x86_64")]
22 static_assert_size
!(PlaceTy
<'_
>, 16);
24 impl<'tcx
> PlaceTy
<'tcx
> {
25 pub fn from_ty(ty
: Ty
<'tcx
>) -> PlaceTy
<'tcx
> {
26 PlaceTy { ty, variant_index: None }
29 /// `place_ty.field_ty(tcx, f)` computes the type at a given field
30 /// of a record or enum-variant. (Most clients of `PlaceTy` can
31 /// instead just extract the relevant type directly from their
32 /// `PlaceElem`, but some instances of `ProjectionElem<V, T>` do
33 /// not carry a `Ty` for `T`.)
35 /// Note that the resulting type has not been normalized.
36 pub fn field_ty(self, tcx
: TyCtxt
<'tcx
>, f
: &Field
) -> Ty
<'tcx
> {
37 let answer
= match self.ty
.kind
{
38 ty
::Adt(adt_def
, substs
) => {
39 let variant_def
= match self.variant_index
{
40 None
=> adt_def
.non_enum_variant(),
41 Some(variant_index
) => {
42 assert
!(adt_def
.is_enum());
43 &adt_def
.variants
[variant_index
]
46 let field_def
= &variant_def
.fields
[f
.index()];
47 field_def
.ty(tcx
, substs
)
49 ty
::Tuple(ref tys
) => tys
[f
.index()].expect_ty(),
50 _
=> bug
!("extracting field of non-tuple non-adt: {:?}", self),
52 debug
!("field_ty self: {:?} f: {:?} yields: {:?}", self, f
, answer
);
56 /// Convenience wrapper around `projection_ty_core` for
57 /// `PlaceElem`, where we can just use the `Ty` that is already
58 /// stored inline on field projection elems.
59 pub fn projection_ty(self, tcx
: TyCtxt
<'tcx
>, elem
: &PlaceElem
<'tcx
>) -> PlaceTy
<'tcx
> {
60 self.projection_ty_core(tcx
, ty
::ParamEnv
::empty(), elem
, |_
, _
, ty
| ty
)
63 /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
64 /// projects `place_ty` onto `elem`, returning the appropriate
65 /// `Ty` or downcast variant corresponding to that projection.
66 /// The `handle_field` callback must map a `Field` to its `Ty`,
67 /// (which should be trivial when `T` = `Ty`).
68 pub fn projection_ty_core
<V
, T
>(
71 param_env
: ty
::ParamEnv
<'tcx
>,
72 elem
: &ProjectionElem
<V
, T
>,
73 mut handle_field
: impl FnMut(&Self, &Field
, &T
) -> Ty
<'tcx
>,
79 let answer
= match *elem
{
80 ProjectionElem
::Deref
=> {
84 bug
!("deref projection of non-dereferenceable ty {:?}", self)
89 ProjectionElem
::Index(_
) | ProjectionElem
::ConstantIndex { .. }
=>
90 PlaceTy
::from_ty(self.ty
.builtin_index().unwrap()),
91 ProjectionElem
::Subslice { from, to, from_end }
=> {
92 PlaceTy
::from_ty(match self.ty
.kind
{
93 ty
::Slice(..) => self.ty
,
94 ty
::Array(inner
, _
) if !from_end
=> {
95 tcx
.mk_array(inner
, (to
- from
) as u64)
97 ty
::Array(inner
, size
) if from_end
=> {
98 let size
= size
.eval_usize(tcx
, param_env
);
99 let len
= size
- (from
as u64) - (to
as u64);
100 tcx
.mk_array(inner
, len
)
103 bug
!("cannot subslice non-array type: `{:?}`", self)
107 ProjectionElem
::Downcast(_name
, index
) =>
108 PlaceTy { ty: self.ty, variant_index: Some(index) }
,
109 ProjectionElem
::Field(ref f
, ref fty
) =>
110 PlaceTy
::from_ty(handle_field(&self, f
, fty
)),
112 debug
!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem
, answer
);
117 impl<'tcx
> Place
<'tcx
> {
119 base
: &PlaceBase
<'tcx
>,
120 projection
: &[PlaceElem
<'tcx
>],
124 where D
: HasLocalDecls
<'tcx
>
126 projection
.iter().fold(
127 base
.ty(local_decls
),
128 |place_ty
, elem
| place_ty
.projection_ty(tcx
, elem
)
132 pub fn ty
<D
>(&self, local_decls
: &D
, tcx
: TyCtxt
<'tcx
>) -> PlaceTy
<'tcx
>
134 D
: HasLocalDecls
<'tcx
>,
136 Place
::ty_from(&self.base
, &self.projection
, local_decls
, tcx
)
140 impl<'tcx
> PlaceBase
<'tcx
> {
141 pub fn ty
<D
>(&self, local_decls
: &D
) -> PlaceTy
<'tcx
>
142 where D
: HasLocalDecls
<'tcx
>
145 PlaceBase
::Local(index
) => PlaceTy
::from_ty(local_decls
.local_decls()[*index
].ty
),
146 PlaceBase
::Static(data
) => PlaceTy
::from_ty(data
.ty
),
151 pub enum RvalueInitializationState
{
156 impl<'tcx
> Rvalue
<'tcx
> {
157 pub fn ty
<D
>(&self, local_decls
: &D
, tcx
: TyCtxt
<'tcx
>) -> Ty
<'tcx
>
159 D
: HasLocalDecls
<'tcx
>,
162 Rvalue
::Use(ref operand
) => operand
.ty(local_decls
, tcx
),
163 Rvalue
::Repeat(ref operand
, count
) => {
164 tcx
.mk_array(operand
.ty(local_decls
, tcx
), count
)
166 Rvalue
::Ref(reg
, bk
, ref place
) => {
167 let place_ty
= place
.ty(local_decls
, tcx
).ty
;
171 mutbl
: bk
.to_mutbl_lossy()
175 Rvalue
::Len(..) => tcx
.types
.usize,
176 Rvalue
::Cast(.., ty
) => ty
,
177 Rvalue
::BinaryOp(op
, ref lhs
, ref rhs
) => {
178 let lhs_ty
= lhs
.ty(local_decls
, tcx
);
179 let rhs_ty
= rhs
.ty(local_decls
, tcx
);
180 op
.ty(tcx
, lhs_ty
, rhs_ty
)
182 Rvalue
::CheckedBinaryOp(op
, ref lhs
, ref rhs
) => {
183 let lhs_ty
= lhs
.ty(local_decls
, tcx
);
184 let rhs_ty
= rhs
.ty(local_decls
, tcx
);
185 let ty
= op
.ty(tcx
, lhs_ty
, rhs_ty
);
186 tcx
.intern_tup(&[ty
, tcx
.types
.bool
])
188 Rvalue
::UnaryOp(UnOp
::Not
, ref operand
) |
189 Rvalue
::UnaryOp(UnOp
::Neg
, ref operand
) => {
190 operand
.ty(local_decls
, tcx
)
192 Rvalue
::Discriminant(ref place
) => {
193 let ty
= place
.ty(local_decls
, tcx
).ty
;
195 ty
::Adt(adt_def
, _
) => adt_def
.repr
.discr_type().to_ty(tcx
),
196 ty
::Generator(_
, substs
, _
) => substs
.as_generator().discr_ty(tcx
),
198 // This can only be `0`, for now, so `u8` will suffice.
203 Rvalue
::NullaryOp(NullOp
::Box
, t
) => tcx
.mk_box(t
),
204 Rvalue
::NullaryOp(NullOp
::SizeOf
, _
) => tcx
.types
.usize,
205 Rvalue
::Aggregate(ref ak
, ref ops
) => {
207 AggregateKind
::Array(ty
) => {
208 tcx
.mk_array(ty
, ops
.len() as u64)
210 AggregateKind
::Tuple
=> {
211 tcx
.mk_tup(ops
.iter().map(|op
| op
.ty(local_decls
, tcx
)))
213 AggregateKind
::Adt(def
, _
, substs
, _
, _
) => {
214 tcx
.type_of(def
.did
).subst(tcx
, substs
)
216 AggregateKind
::Closure(did
, substs
) => {
217 tcx
.mk_closure(did
, substs
)
219 AggregateKind
::Generator(did
, substs
, movability
) => {
220 tcx
.mk_generator(did
, substs
, movability
)
228 /// Returns `true` if this rvalue is deeply initialized (most rvalues) or
229 /// whether its only shallowly initialized (`Rvalue::Box`).
230 pub fn initialization_state(&self) -> RvalueInitializationState
{
232 Rvalue
::NullaryOp(NullOp
::Box
, _
) => RvalueInitializationState
::Shallow
,
233 _
=> RvalueInitializationState
::Deep
238 impl<'tcx
> Operand
<'tcx
> {
239 pub fn ty
<D
>(&self, local_decls
: &D
, tcx
: TyCtxt
<'tcx
>) -> Ty
<'tcx
>
241 D
: HasLocalDecls
<'tcx
>,
244 &Operand
::Copy(ref l
) |
245 &Operand
::Move(ref l
) => l
.ty(local_decls
, tcx
).ty
,
246 &Operand
::Constant(ref c
) => c
.literal
.ty
,
252 pub fn ty(&self, tcx
: TyCtxt
<'tcx
>, lhs_ty
: Ty
<'tcx
>, rhs_ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
253 // FIXME: handle SIMD correctly
255 &BinOp
::Add
| &BinOp
::Sub
| &BinOp
::Mul
| &BinOp
::Div
| &BinOp
::Rem
|
256 &BinOp
::BitXor
| &BinOp
::BitAnd
| &BinOp
::BitOr
=> {
257 // these should be integers or floats of the same size.
258 assert_eq
!(lhs_ty
, rhs_ty
);
261 &BinOp
::Shl
| &BinOp
::Shr
| &BinOp
::Offset
=> {
262 lhs_ty
// lhs_ty can be != rhs_ty
264 &BinOp
::Eq
| &BinOp
::Lt
| &BinOp
::Le
|
265 &BinOp
::Ne
| &BinOp
::Ge
| &BinOp
::Gt
=> {
273 pub fn to_mutbl_lossy(self) -> hir
::Mutability
{
275 BorrowKind
::Mut { .. }
=> hir
::Mutability
::Mutable
,
276 BorrowKind
::Shared
=> hir
::Mutability
::Immutable
,
278 // We have no type corresponding to a unique imm borrow, so
279 // use `&mut`. It gives all the capabilities of an `&uniq`
280 // and hence is a safe "over approximation".
281 BorrowKind
::Unique
=> hir
::Mutability
::Mutable
,
283 // We have no type corresponding to a shallow borrow, so use
284 // `&` as an approximation.
285 BorrowKind
::Shallow
=> hir
::Mutability
::Immutable
,
291 pub fn to_hir_binop(self) -> hir
::BinOpKind
{
293 BinOp
::Add
=> hir
::BinOpKind
::Add
,
294 BinOp
::Sub
=> hir
::BinOpKind
::Sub
,
295 BinOp
::Mul
=> hir
::BinOpKind
::Mul
,
296 BinOp
::Div
=> hir
::BinOpKind
::Div
,
297 BinOp
::Rem
=> hir
::BinOpKind
::Rem
,
298 BinOp
::BitXor
=> hir
::BinOpKind
::BitXor
,
299 BinOp
::BitAnd
=> hir
::BinOpKind
::BitAnd
,
300 BinOp
::BitOr
=> hir
::BinOpKind
::BitOr
,
301 BinOp
::Shl
=> hir
::BinOpKind
::Shl
,
302 BinOp
::Shr
=> hir
::BinOpKind
::Shr
,
303 BinOp
::Eq
=> hir
::BinOpKind
::Eq
,
304 BinOp
::Ne
=> hir
::BinOpKind
::Ne
,
305 BinOp
::Lt
=> hir
::BinOpKind
::Lt
,
306 BinOp
::Gt
=> hir
::BinOpKind
::Gt
,
307 BinOp
::Le
=> hir
::BinOpKind
::Le
,
308 BinOp
::Ge
=> hir
::BinOpKind
::Ge
,
309 BinOp
::Offset
=> unreachable
!()