Skip to main content

rustc_middle/ty/
cast.rs

1// Helpers for handling cast expressions, used in both
2// typeck and codegen.
3
4use rustc_macros::{HashStable, TyDecodable, TyEncodable};
5
6use crate::mir;
7use crate::ty::{self, Ty};
8
9/// Types that are represented as ints.
10#[derive(#[automatically_derived]
impl ::core::marker::Copy for IntTy { }Copy, #[automatically_derived]
impl ::core::clone::Clone for IntTy {
    #[inline]
    fn clone(&self) -> IntTy {
        let _: ::core::clone::AssertParamIsClone<ty::UintTy>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for IntTy {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            IntTy::U(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "U",
                    &__self_0),
            IntTy::I => ::core::fmt::Formatter::write_str(f, "I"),
            IntTy::CEnum => ::core::fmt::Formatter::write_str(f, "CEnum"),
            IntTy::Bool => ::core::fmt::Formatter::write_str(f, "Bool"),
            IntTy::Char => ::core::fmt::Formatter::write_str(f, "Char"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for IntTy {
    #[inline]
    fn eq(&self, other: &IntTy) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (IntTy::U(__self_0), IntTy::U(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for IntTy {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ty::UintTy>;
    }
}Eq)]
11pub enum IntTy {
12    U(ty::UintTy),
13    I,
14    CEnum,
15    Bool,
16    Char,
17}
18
19impl IntTy {
20    pub fn is_signed(self) -> bool {
21        #[allow(non_exhaustive_omitted_patterns)] match self {
    Self::I => true,
    _ => false,
}matches!(self, Self::I)
22    }
23}
24
25// Valid types for the result of a non-coercion cast
26#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for CastTy<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for CastTy<'tcx> {
    #[inline]
    fn clone(&self) -> CastTy<'tcx> {
        let _: ::core::clone::AssertParamIsClone<IntTy>;
        let _: ::core::clone::AssertParamIsClone<ty::TypeAndMut<'tcx>>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for CastTy<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            CastTy::Int(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Int",
                    &__self_0),
            CastTy::Float => ::core::fmt::Formatter::write_str(f, "Float"),
            CastTy::FnPtr => ::core::fmt::Formatter::write_str(f, "FnPtr"),
            CastTy::Ptr(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Ptr",
                    &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for CastTy<'tcx> {
    #[inline]
    fn eq(&self, other: &CastTy<'tcx>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (CastTy::Int(__self_0), CastTy::Int(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (CastTy::Ptr(__self_0), CastTy::Ptr(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for CastTy<'tcx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<IntTy>;
        let _: ::core::cmp::AssertParamIsEq<ty::TypeAndMut<'tcx>>;
    }
}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),
31    /// Floating-point types.
32    Float,
33    /// Function pointers.
34    FnPtr,
35    /// Raw pointers.
36    Ptr(ty::TypeAndMut<'tcx>),
37}
38
39/// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html)
40/// (or rustc_hir_analysis/check/cast.rs).
41#[derive(#[automatically_derived]
impl ::core::marker::Copy for CastKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for CastKind {
    #[inline]
    fn clone(&self) -> CastKind { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for CastKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                CastKind::PtrPtrCast => "PtrPtrCast",
                CastKind::PtrAddrCast => "PtrAddrCast",
                CastKind::AddrPtrCast => "AddrPtrCast",
                CastKind::NumericCast => "NumericCast",
                CastKind::EnumCast => "EnumCast",
                CastKind::PrimIntCast => "PrimIntCast",
                CastKind::U8CharCast => "U8CharCast",
                CastKind::ArrayPtrCast => "ArrayPtrCast",
                CastKind::FnPtrPtrCast => "FnPtrPtrCast",
                CastKind::FnPtrAddrCast => "FnPtrAddrCast",
            })
    }
}Debug, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for CastKind {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        CastKind::PtrPtrCast => { 0usize }
                        CastKind::PtrAddrCast => { 1usize }
                        CastKind::AddrPtrCast => { 2usize }
                        CastKind::NumericCast => { 3usize }
                        CastKind::EnumCast => { 4usize }
                        CastKind::PrimIntCast => { 5usize }
                        CastKind::U8CharCast => { 6usize }
                        CastKind::ArrayPtrCast => { 7usize }
                        CastKind::FnPtrPtrCast => { 8usize }
                        CastKind::FnPtrAddrCast => { 9usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    CastKind::PtrPtrCast => {}
                    CastKind::PtrAddrCast => {}
                    CastKind::AddrPtrCast => {}
                    CastKind::NumericCast => {}
                    CastKind::EnumCast => {}
                    CastKind::PrimIntCast => {}
                    CastKind::U8CharCast => {}
                    CastKind::ArrayPtrCast => {}
                    CastKind::FnPtrPtrCast => {}
                    CastKind::FnPtrAddrCast => {}
                }
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for CastKind {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { CastKind::PtrPtrCast }
                    1usize => { CastKind::PtrAddrCast }
                    2usize => { CastKind::AddrPtrCast }
                    3usize => { CastKind::NumericCast }
                    4usize => { CastKind::EnumCast }
                    5usize => { CastKind::PrimIntCast }
                    6usize => { CastKind::U8CharCast }
                    7usize => { CastKind::ArrayPtrCast }
                    8usize => { CastKind::FnPtrPtrCast }
                    9usize => { CastKind::FnPtrAddrCast }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `CastKind`, expected 0..10, actual {0}",
                                n));
                    }
                }
            }
        }
    };TyDecodable, const _: () =
    {
        impl<'__ctx>
            ::rustc_data_structures::stable_hasher::HashStable<::rustc_query_system::ich::StableHashingContext<'__ctx>>
            for CastKind {
            #[inline]
            fn hash_stable(&self,
                __hcx:
                    &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    CastKind::PtrPtrCast => {}
                    CastKind::PtrAddrCast => {}
                    CastKind::AddrPtrCast => {}
                    CastKind::NumericCast => {}
                    CastKind::EnumCast => {}
                    CastKind::PrimIntCast => {}
                    CastKind::U8CharCast => {}
                    CastKind::ArrayPtrCast => {}
                    CastKind::FnPtrPtrCast => {}
                    CastKind::FnPtrAddrCast => {}
                }
            }
        }
    };HashStable)]
42pub enum CastKind {
43    PtrPtrCast,
44    PtrAddrCast,
45    AddrPtrCast,
46    NumericCast,
47    EnumCast,
48    PrimIntCast,
49    U8CharCast,
50    ArrayPtrCast,
51    FnPtrPtrCast,
52    FnPtrAddrCast,
53}
54
55impl<'tcx> CastTy<'tcx> {
56    /// Returns `Some` for integral/pointer casts.
57    /// Casts like unsizing casts will return `None`.
58    pub fn from_ty(t: Ty<'tcx>) -> Option<CastTy<'tcx>> {
59        match *t.kind() {
60            ty::Bool => Some(CastTy::Int(IntTy::Bool)),
61            ty::Char => Some(CastTy::Int(IntTy::Char)),
62            ty::Int(_) => Some(CastTy::Int(IntTy::I)),
63            ty::Infer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::I)),
64            ty::Infer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float),
65            ty::Uint(u) => Some(CastTy::Int(IntTy::U(u))),
66            ty::Float(_) => Some(CastTy::Float),
67            ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)),
68            ty::RawPtr(ty, mutbl) => Some(CastTy::Ptr(ty::TypeAndMut { ty, mutbl })),
69            ty::FnPtr(..) => Some(CastTy::FnPtr),
70            _ => None,
71        }
72    }
73}
74
75/// Returns `mir::CastKind` from the given parameters.
76pub fn mir_cast_kind<'tcx>(from_ty: Ty<'tcx>, cast_ty: Ty<'tcx>) -> mir::CastKind {
77    let from = CastTy::from_ty(from_ty);
78    let cast = CastTy::from_ty(cast_ty);
79    let cast_kind = match (from, cast) {
80        (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
81            mir::CastKind::PointerExposeProvenance
82        }
83        (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PointerWithExposedProvenance,
84        (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => mir::CastKind::IntToInt,
85        (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => mir::CastKind::FnPtrToPtr,
86
87        (Some(CastTy::Float), Some(CastTy::Int(_))) => mir::CastKind::FloatToInt,
88        (Some(CastTy::Int(_)), Some(CastTy::Float)) => mir::CastKind::IntToFloat,
89        (Some(CastTy::Float), Some(CastTy::Float)) => mir::CastKind::FloatToFloat,
90        (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PtrToPtr,
91
92        (_, _) => {
93            crate::util::bug::bug_fmt(format_args!("Attempting to cast non-castable types {0:?} and {1:?}",
        from_ty, cast_ty))bug!("Attempting to cast non-castable types {:?} and {:?}", from_ty, cast_ty)
94        }
95    };
96    cast_kind
97}