Skip to main content

rustc_middle/ty/
cast.rs

1// Helpers for handling cast expressions.
2
3use rustc_span::bug;
4
5use crate::mir;
6use crate::ty::{self, Ty};
7
8/// Valid types for the result of a non-coercion cast
9#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for CastTy<'tcx> { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for CastTy<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for CastTy<'tcx> {
    #[inline]
    fn clone(&self) -> Self {
        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 {
            Self::Int => ::core::fmt::Formatter::write_str(f, "Int"),
            Self::CEnum => ::core::fmt::Formatter::write_str(f, "CEnum"),
            Self::Bool => ::core::fmt::Formatter::write_str(f, "Bool"),
            Self::Char => ::core::fmt::Formatter::write_str(f, "Char"),
            Self::Float => ::core::fmt::Formatter::write_str(f, "Float"),
            Self::FnPtr => ::core::fmt::Formatter::write_str(f, "FnPtr"),
            Self::Ptr(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Ptr",
                    &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::marker::StructuralPartialEq for CastTy<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for CastTy<'tcx> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::Ptr(__self_0), Self::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_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ty::TypeAndMut<'tcx>>;
    }
}Eq)]
10pub enum CastTy<'tcx> {
11    /// `iN`, `uN`, and integer inference variables.
12    Int,
13    /// C-like (fieldless) enums.
14    CEnum,
15    Bool,
16    Char,
17    /// `fN` and float inference variables.
18    Float,
19    /// Function pointers.
20    FnPtr,
21    /// Raw pointers.
22    Ptr(ty::TypeAndMut<'tcx>),
23}
24
25impl<'tcx> CastTy<'tcx> {
26    /// Returns `Some` for integral/pointer casts.
27    /// Casts like unsizing casts will return `None`.
28    pub fn from_ty(t: Ty<'tcx>) -> Option<CastTy<'tcx>> {
29        match *t.kind() {
30            ty::Bool => Some(CastTy::Bool),
31            ty::Char => Some(CastTy::Char),
32            ty::Int(_) | ty::Uint(_) | ty::Infer(ty::InferTy::IntVar(_)) => Some(CastTy::Int),
33            ty::Float(_) | ty::Infer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float),
34            ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::CEnum),
35            ty::RawPtr(ty, mutbl) => Some(CastTy::Ptr(ty::TypeAndMut { ty, mutbl })),
36            ty::FnPtr(..) => Some(CastTy::FnPtr),
37            _ => None,
38        }
39    }
40
41    pub fn is_int_like(self) -> bool {
42        match self {
43            CastTy::Int | CastTy::CEnum | CastTy::Bool | CastTy::Char => true,
44            CastTy::Float | CastTy::FnPtr | CastTy::Ptr(_) => false,
45        }
46    }
47}
48
49/// Returns `mir::CastKind` from the given parameters.
50pub fn mir_cast_kind<'tcx>(from_ty: Ty<'tcx>, cast_ty: Ty<'tcx>) -> mir::CastKind {
51    let from = CastTy::from_ty(from_ty);
52    let cast = CastTy::from_ty(cast_ty);
53    let cast_kind = match (from, cast) {
54        (Some(from), Some(cast)) if from.is_int_like() && cast.is_int_like() => {
55            mir::CastKind::IntToInt
56        }
57        (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int)) => {
58            mir::CastKind::PointerExposeProvenance
59        }
60        (Some(CastTy::Int), Some(CastTy::Ptr(_))) => mir::CastKind::PointerWithExposedProvenance,
61        (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => mir::CastKind::FnPtrToPtr,
62
63        (Some(CastTy::Float), Some(CastTy::Int)) => mir::CastKind::FloatToInt,
64        (Some(CastTy::Int), Some(CastTy::Float)) => mir::CastKind::IntToFloat,
65        (Some(CastTy::Float), Some(CastTy::Float)) => mir::CastKind::FloatToFloat,
66        (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PtrToPtr,
67
68        (_, _) => {
69            ::rustc_span::macros::bug_impl(None,
    format_args!("Attempting to cast non-castable types {0:?} and {1:?}",
        from_ty, cast_ty), Location::caller())bug!("Attempting to cast non-castable types {:?} and {:?}", from_ty, cast_ty)
70        }
71    };
72    cast_kind
73}