]>
Commit | Line | Data |
---|---|---|
62682a34 | 1 | // Helpers for handling cast expressions, used in both |
94b46f34 | 2 | // typeck and codegen. |
62682a34 | 3 | |
9fa01778 | 4 | use crate::ty::{self, Ty}; |
2b03887a | 5 | use rustc_middle::mir; |
62682a34 | 6 | |
532ac7d7 | 7 | use rustc_macros::HashStable; |
62682a34 SL |
8 | |
9 | /// Types that are represented as ints. | |
10 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | |
11 | pub enum IntTy { | |
5869c6ff | 12 | U(ty::UintTy), |
62682a34 SL |
13 | I, |
14 | CEnum, | |
15 | Bool, | |
dfeec247 | 16 | Char, |
62682a34 SL |
17 | } |
18 | ||
064997fb FG |
19 | impl IntTy { |
20 | pub fn is_signed(self) -> bool { | |
21 | matches!(self, Self::I) | |
22 | } | |
23 | } | |
24 | ||
62682a34 SL |
25 | // Valid types for the result of a non-coercion cast |
26 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | |
27 | pub enum CastTy<'tcx> { | |
28 | /// Various types that are represented as ints and handled mostly | |
29 | /// in the same way, merged for easier matching. | |
30 | Int(IntTy), | |
5869c6ff | 31 | /// Floating-point types. |
62682a34 | 32 | Float, |
5869c6ff | 33 | /// Function pointers. |
62682a34 | 34 | FnPtr, |
5869c6ff | 35 | /// Raw pointers. |
94b46f34 | 36 | Ptr(ty::TypeAndMut<'tcx>), |
f2b60f7d FG |
37 | /// Casting into a `dyn*` value. |
38 | DynStar, | |
62682a34 SL |
39 | } |
40 | ||
5869c6ff | 41 | /// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html) |
2b03887a | 42 | /// (or rustc_hir_analysis/check/cast.rs). |
3dfed10e | 43 | #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] |
62682a34 SL |
44 | pub enum CastKind { |
45 | CoercionCast, | |
46 | PtrPtrCast, | |
47 | PtrAddrCast, | |
48 | AddrPtrCast, | |
49 | NumericCast, | |
50 | EnumCast, | |
51 | PrimIntCast, | |
52 | U8CharCast, | |
53 | ArrayPtrCast, | |
54 | FnPtrPtrCast, | |
dfeec247 | 55 | FnPtrAddrCast, |
f2b60f7d | 56 | DynStarCast, |
62682a34 SL |
57 | } |
58 | ||
59 | impl<'tcx> CastTy<'tcx> { | |
0bf4aa26 | 60 | /// Returns `Some` for integral/pointer casts. |
5869c6ff | 61 | /// Casts like unsizing casts will return `None`. |
e9174d1e | 62 | pub fn from_ty(t: Ty<'tcx>) -> Option<CastTy<'tcx>> { |
1b1a35ee | 63 | match *t.kind() { |
b7449926 XL |
64 | ty::Bool => Some(CastTy::Int(IntTy::Bool)), |
65 | ty::Char => Some(CastTy::Int(IntTy::Char)), | |
66 | ty::Int(_) => Some(CastTy::Int(IntTy::I)), | |
67 | ty::Infer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::I)), | |
68 | ty::Infer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float), | |
69 | ty::Uint(u) => Some(CastTy::Int(IntTy::U(u))), | |
70 | ty::Float(_) => Some(CastTy::Float), | |
dfeec247 | 71 | ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)), |
b7449926 | 72 | ty::RawPtr(mt) => Some(CastTy::Ptr(mt)), |
b7449926 | 73 | ty::FnPtr(..) => Some(CastTy::FnPtr), |
f2b60f7d | 74 | ty::Dynamic(_, _, ty::DynStar) => Some(CastTy::DynStar), |
62682a34 SL |
75 | _ => None, |
76 | } | |
77 | } | |
78 | } | |
2b03887a FG |
79 | |
80 | /// Returns `mir::CastKind` from the given parameters. | |
81 | pub fn mir_cast_kind<'tcx>(from_ty: Ty<'tcx>, cast_ty: Ty<'tcx>) -> mir::CastKind { | |
82 | let from = CastTy::from_ty(from_ty); | |
83 | let cast = CastTy::from_ty(cast_ty); | |
84 | let cast_kind = match (from, cast) { | |
85 | (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => { | |
86 | mir::CastKind::PointerExposeAddress | |
87 | } | |
88 | (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PointerFromExposedAddress, | |
89 | (_, Some(CastTy::DynStar)) => mir::CastKind::DynStar, | |
90 | (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => mir::CastKind::IntToInt, | |
91 | (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => mir::CastKind::FnPtrToPtr, | |
92 | ||
93 | (Some(CastTy::Float), Some(CastTy::Int(_))) => mir::CastKind::FloatToInt, | |
94 | (Some(CastTy::Int(_)), Some(CastTy::Float)) => mir::CastKind::IntToFloat, | |
95 | (Some(CastTy::Float), Some(CastTy::Float)) => mir::CastKind::FloatToFloat, | |
96 | (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PtrToPtr, | |
97 | ||
98 | (_, _) => { | |
99 | bug!("Attempting to cast non-castable types {:?} and {:?}", from_ty, cast_ty) | |
100 | } | |
101 | }; | |
102 | cast_kind | |
103 | } |