Skip to main content

rustc_middle/ty/
region.rs

1use rustc_hir::def_id::DefId;
2use rustc_macros::{StableHash, TyDecodable, TyEncodable};
3use rustc_span::{Symbol, kw};
4pub use rustc_type_ir::RegionVid;
5use rustc_type_ir::{
6    LateParamRegion as IrLateParamRegion, Region as IrRegion, RegionKind as IrRegionKind,
7};
8
9use crate::ty::{self, BoundVar, TyCtxt};
10
11pub type Region<'tcx> = IrRegion<TyCtxt<'tcx>>;
12pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>;
13pub type LateParamRegion<'tcx> = IrLateParamRegion<TyCtxt<'tcx>>;
14
15#[derive(#[automatically_derived]
impl ::core::marker::Copy for EarlyParamRegion { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for EarlyParamRegion { }
#[automatically_derived]
impl ::core::clone::Clone for EarlyParamRegion {
    #[inline]
    fn clone(&self) -> EarlyParamRegion {
        let _: ::core::clone::AssertParamIsClone<u32>;
        let _: ::core::clone::AssertParamIsClone<Symbol>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for EarlyParamRegion { }
#[automatically_derived]
impl ::core::cmp::PartialEq for EarlyParamRegion {
    #[inline]
    fn eq(&self, other: &EarlyParamRegion) -> bool {
        self.index == other.index && self.name == other.name
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for EarlyParamRegion {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u32>;
        let _: ::core::cmp::AssertParamIsEq<Symbol>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for EarlyParamRegion {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.index, state);
        ::core::hash::Hash::hash(&self.name, state)
    }
}Hash, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for EarlyParamRegion {
            fn encode(&self, __encoder: &mut __E) {
                let EarlyParamRegion {
                        index: ref __binding_0, name: ref __binding_1 } = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                    __encoder);
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for EarlyParamRegion {
            fn decode(__decoder: &mut __D) -> Self {
                EarlyParamRegion {
                    index: ::rustc_serialize::Decodable::decode(__decoder),
                    name: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };TyDecodable)]
16#[derive(const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for
            EarlyParamRegion {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    EarlyParamRegion {
                        index: ref __binding_0, name: ref __binding_1 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
17pub struct EarlyParamRegion {
18    pub index: u32,
19    pub name: Symbol,
20}
21
22impl EarlyParamRegion {
23    #[inline]
24    pub fn get_name(&self) -> Option<Symbol> {
25        if self.is_named() { Some(self.name) } else { None }
26    }
27
28    #[inline]
29    /// Does this early bound region have a name? Early bound regions normally
30    /// always have names except when using anonymous lifetimes (`'_`).
31    pub fn is_named(&self) -> bool {
32        self.name != kw::UnderscoreLifetime
33    }
34}
35
36impl rustc_type_ir::inherent::ParamLike for EarlyParamRegion {
37    fn index(self) -> u32 {
38        self.index
39    }
40}
41
42impl<'tcx> rustc_type_ir::inherent::RegionName<TyCtxt<'tcx>> for EarlyParamRegion {
43    #[inline]
44    fn get_name(&self, _tcx: TyCtxt<'tcx>) -> Option<Symbol> {
45        self.get_name()
46    }
47
48    #[inline]
49    /// Does this early bound region have a name? Early bound regions normally
50    /// always have names except when using anonymous lifetimes (`'_`).
51    fn is_named(&self, _tcx: TyCtxt<'tcx>) -> bool {
52        self.is_named()
53    }
54}
55
56impl std::fmt::Debug for EarlyParamRegion {
57    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58        f.write_fmt(format_args!("{0}/#{1}", self.name, self.index))write!(f, "{}/#{}", self.name, self.index)
59    }
60}
61
62/// When liberating bound regions, we map their [`ty::BoundRegionKind`]
63/// to this as we need to track the index of anonymous regions. We
64/// otherwise end up liberating multiple bound regions to the same
65/// late-bound region.
66#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for LateParamRegionKind { }
#[automatically_derived]
impl ::core::clone::Clone for LateParamRegionKind {
    #[inline]
    fn clone(&self) -> LateParamRegionKind {
        let _: ::core::clone::AssertParamIsClone<u32>;
        let _: ::core::clone::AssertParamIsClone<Symbol>;
        let _: ::core::clone::AssertParamIsClone<DefId>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for LateParamRegionKind { }
#[automatically_derived]
impl ::core::cmp::PartialEq for LateParamRegionKind {
    #[inline]
    fn eq(&self, other: &LateParamRegionKind) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (LateParamRegionKind::Anon(__self_0),
                    LateParamRegionKind::Anon(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (LateParamRegionKind::NamedAnon(__self_0, __self_1),
                    LateParamRegionKind::NamedAnon(__arg1_0, __arg1_1)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (LateParamRegionKind::Named(__self_0),
                    LateParamRegionKind::Named(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for LateParamRegionKind {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u32>;
        let _: ::core::cmp::AssertParamIsEq<Symbol>;
        let _: ::core::cmp::AssertParamIsEq<DefId>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for LateParamRegionKind {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            LateParamRegionKind::Anon(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            LateParamRegionKind::NamedAnon(__self_0, __self_1) => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            LateParamRegionKind::Named(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for LateParamRegionKind {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        LateParamRegionKind::Anon(ref __binding_0) => { 0usize }
                        LateParamRegionKind::NamedAnon(ref __binding_0,
                            ref __binding_1) => {
                            1usize
                        }
                        LateParamRegionKind::Named(ref __binding_0) => { 2usize }
                        LateParamRegionKind::ClosureEnv => { 3usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    LateParamRegionKind::Anon(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    LateParamRegionKind::NamedAnon(ref __binding_0,
                        ref __binding_1) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                    LateParamRegionKind::Named(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    LateParamRegionKind::ClosureEnv => {}
                }
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for LateParamRegionKind {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        LateParamRegionKind::Anon(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => {
                        LateParamRegionKind::NamedAnon(::rustc_serialize::Decodable::decode(__decoder),
                            ::rustc_serialize::Decodable::decode(__decoder))
                    }
                    2usize => {
                        LateParamRegionKind::Named(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    3usize => { LateParamRegionKind::ClosureEnv }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `LateParamRegionKind`, expected 0..4, actual {0}",
                                n));
                    }
                }
            }
        }
    };TyDecodable, #[automatically_derived]
impl ::core::marker::Copy for LateParamRegionKind { }Copy)]
67#[derive(const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for
            LateParamRegionKind {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    LateParamRegionKind::Anon(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    LateParamRegionKind::NamedAnon(ref __binding_0,
                        ref __binding_1) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                    LateParamRegionKind::Named(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    LateParamRegionKind::ClosureEnv => {}
                }
            }
        }
    };StableHash)]
68pub enum LateParamRegionKind {
69    /// An anonymous region parameter for a given fn (&T)
70    ///
71    /// Unlike [`ty::BoundRegionKind::Anon`], this tracks the index of the
72    /// liberated bound region.
73    ///
74    /// We should ideally never liberate anonymous regions, but do so for the
75    /// sake of diagnostics in `FnCtxt::sig_of_closure_with_expectation`.
76    Anon(u32),
77
78    /// An anonymous region parameter with a `Symbol` name.
79    ///
80    /// Used to give late-bound regions names for things like pretty printing.
81    NamedAnon(u32, Symbol),
82
83    /// Late-bound regions that appear in the AST.
84    Named(DefId),
85
86    /// Anonymous region for the implicit env pointer parameter
87    /// to a closure
88    ClosureEnv,
89}
90
91impl LateParamRegionKind {
92    pub fn from_bound(var: BoundVar, br: ty::BoundRegionKind<'_>) -> LateParamRegionKind {
93        match br {
94            ty::BoundRegionKind::Anon => LateParamRegionKind::Anon(var.as_u32()),
95            ty::BoundRegionKind::Named(def_id) => LateParamRegionKind::Named(def_id),
96            ty::BoundRegionKind::ClosureEnv => LateParamRegionKind::ClosureEnv,
97            ty::BoundRegionKind::NamedForPrinting(name) => {
98                LateParamRegionKind::NamedAnon(var.as_u32(), name)
99            }
100        }
101    }
102
103    pub fn is_named(&self, tcx: TyCtxt<'_>) -> bool {
104        self.get_name(tcx).is_some()
105    }
106
107    pub fn get_name(&self, tcx: TyCtxt<'_>) -> Option<Symbol> {
108        match *self {
109            LateParamRegionKind::Named(def_id) => {
110                let name = tcx.item_name(def_id);
111                if name != kw::UnderscoreLifetime { Some(name) } else { None }
112            }
113            LateParamRegionKind::NamedAnon(_, name) => Some(name),
114            _ => None,
115        }
116    }
117
118    pub fn get_id(&self) -> Option<DefId> {
119        match *self {
120            LateParamRegionKind::Named(id) => Some(id),
121            _ => None,
122        }
123    }
124}
125
126impl<'tcx> rustc_type_ir::inherent::RegionName<TyCtxt<'tcx>> for LateParamRegionKind {
127    #[inline]
128    fn get_name(&self, tcx: TyCtxt<'tcx>) -> Option<Symbol> {
129        self.get_name(tcx)
130    }
131
132    #[inline]
133    fn is_named(&self, tcx: TyCtxt<'tcx>) -> bool {
134        self.is_named(tcx)
135    }
136}
137
138impl<'tcx> rustc_type_ir::inherent::DefIdGetter<TyCtxt<'tcx>> for LateParamRegionKind {
139    fn get_def_id(self) -> Option<DefId> {
140        self.get_id()
141    }
142}
143
144// Some types are used a lot. Make sure they don't unintentionally get bigger.
145#[cfg(target_pointer_width = "64")]
146mod size_asserts {
147    use rustc_data_structures::static_assert_size;
148
149    use super::*;
150    // tidy-alphabetical-start
151    const _: [(); 20] = [(); ::std::mem::size_of::<RegionKind<'_>>()];static_assert_size!(RegionKind<'_>, 20);
152    const _: [(); 28] =
    [(); ::std::mem::size_of::<ty::WithCachedTypeInfo<RegionKind<'_>>>()];static_assert_size!(ty::WithCachedTypeInfo<RegionKind<'_>>, 28);
153    // tidy-alphabetical-end
154}