]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/cast.rs
Auto merge of #102596 - scottmcm:option-bool-calloc, r=Mark-Simulacrum
[rust.git] / compiler / rustc_middle / src / ty / cast.rs
1 // Helpers for handling cast expressions, used in both
2 // typeck and codegen.
3
4 use crate::ty::{self, Ty};
5 use rustc_middle::mir;
6
7 use rustc_macros::HashStable;
8
9 /// Types that are represented as ints.
10 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
11 pub enum IntTy {
12     U(ty::UintTy),
13     I,
14     CEnum,
15     Bool,
16     Char,
17 }
18
19 impl IntTy {
20     pub fn is_signed(self) -> bool {
21         matches!(self, Self::I)
22     }
23 }
24
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),
31     /// Floating-point types.
32     Float,
33     /// Function pointers.
34     FnPtr,
35     /// Raw pointers.
36     Ptr(ty::TypeAndMut<'tcx>),
37     /// Casting into a `dyn*` value.
38     DynStar,
39 }
40
41 /// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html)
42 /// (or rustc_hir_analysis/check/cast.rs).
43 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
44 pub enum CastKind {
45     CoercionCast,
46     PtrPtrCast,
47     PtrAddrCast,
48     AddrPtrCast,
49     NumericCast,
50     EnumCast,
51     PrimIntCast,
52     U8CharCast,
53     ArrayPtrCast,
54     FnPtrPtrCast,
55     FnPtrAddrCast,
56     DynStarCast,
57 }
58
59 impl<'tcx> CastTy<'tcx> {
60     /// Returns `Some` for integral/pointer casts.
61     /// Casts like unsizing casts will return `None`.
62     pub fn from_ty(t: Ty<'tcx>) -> Option<CastTy<'tcx>> {
63         match *t.kind() {
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),
71             ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)),
72             ty::RawPtr(mt) => Some(CastTy::Ptr(mt)),
73             ty::FnPtr(..) => Some(CastTy::FnPtr),
74             ty::Dynamic(_, _, ty::DynStar) => Some(CastTy::DynStar),
75             _ => None,
76         }
77     }
78 }
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 }