]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/cast.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / cast.rs
CommitLineData
62682a34 1// Helpers for handling cast expressions, used in both
94b46f34 2// typeck and codegen.
62682a34 3
9fa01778 4use crate::ty::{self, Ty};
2b03887a 5use rustc_middle::mir;
62682a34 6
532ac7d7 7use rustc_macros::HashStable;
62682a34
SL
8
9/// Types that are represented as ints.
10#[derive(Copy, Clone, Debug, PartialEq, Eq)]
11pub enum IntTy {
5869c6ff 12 U(ty::UintTy),
62682a34
SL
13 I,
14 CEnum,
15 Bool,
dfeec247 16 Char,
62682a34
SL
17}
18
064997fb
FG
19impl 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)]
27pub 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
44pub 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
59impl<'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.
81pub 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}