rustc_middle/middle/
deduced_param_attrs.rs

1use rustc_macros::{Decodable, Encodable, HashStable};
2
3use crate::ty::{Ty, TyCtxt, TypingEnv};
4
5/// Summarizes how a parameter (a return place or an argument) is used inside a MIR body.
6#[derive(#[automatically_derived]
impl ::core::clone::Clone for UsageSummary {
    #[inline]
    fn clone(&self) -> UsageSummary {
        let _: ::core::clone::AssertParamIsClone<u8>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for UsageSummary { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for UsageSummary {
    #[inline]
    fn eq(&self, other: &UsageSummary) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for UsageSummary {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "UsageSummary",
            &&self.0)
    }
}Debug, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for UsageSummary {
            fn decode(__decoder: &mut __D) -> Self {
                UsageSummary(::rustc_serialize::Decodable::decode(__decoder))
            }
        }
    };Decodable, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for UsageSummary {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    UsageSummary(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<'__ctx>
            ::rustc_data_structures::stable_hasher::HashStable<::rustc_query_system::ich::StableHashingContext<'__ctx>>
            for UsageSummary {
            #[inline]
            fn hash_stable(&self,
                __hcx:
                    &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    UsageSummary(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable)]
7pub struct UsageSummary(u8);
8
9impl UsageSummary {
    #[doc = r" This parameter is dropped when it `needs_drop`."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const DROP: Self = Self::from_bits_retain(1 << 0);
    #[doc = r" There is a shared borrow to this parameter."]
    #[doc = r" It allows for mutation unless parameter is `Freeze`."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const SHARED_BORROW: Self = Self::from_bits_retain(1 << 1);
    #[doc =
    r" This parameter is mutated (excluding through a drop or a shared borrow)."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const MUTATE: Self = Self::from_bits_retain(1 << 2);
    #[doc = r" This parameter is captured (excluding through a drop)."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const CAPTURE: Self = Self::from_bits_retain(1 << 3);
}
impl ::bitflags::Flags for UsageSummary {
    const FLAGS: &'static [::bitflags::Flag<UsageSummary>] =
        &[{

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("DROP", UsageSummary::DROP)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("SHARED_BORROW",
                            UsageSummary::SHARED_BORROW)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("MUTATE", UsageSummary::MUTATE)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("CAPTURE", UsageSummary::CAPTURE)
                    }];
    type Bits = u8;
    fn bits(&self) -> u8 { UsageSummary::bits(self) }
    fn from_bits_retain(bits: u8) -> UsageSummary {
        UsageSummary::from_bits_retain(bits)
    }
}
#[allow(dead_code, deprecated, unused_doc_comments, unused_attributes,
unused_mut, unused_imports, non_upper_case_globals, clippy ::
assign_op_pattern, clippy :: iter_without_into_iter,)]
const _: () =
    {
        #[allow(dead_code, deprecated, unused_attributes)]
        impl UsageSummary {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self {
                Self(<u8 as ::bitflags::Bits>::EMPTY)
            }
            /// Get a flags value with all known bits set.
            #[inline]
            pub const fn all() -> Self {
                let mut truncated = <u8 as ::bitflags::Bits>::EMPTY;
                let mut i = 0;
                {
                    {
                        let flag =
                            <UsageSummary as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <UsageSummary as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <UsageSummary as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <UsageSummary as
                                            ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                let _ = i;
                Self(truncated)
            }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u8 { self.0 }
            /// Convert from a bits value.
            ///
            /// This method will return `None` if any unknown bits are set.
            #[inline]
            pub const fn from_bits(bits: u8)
                -> ::bitflags::__private::core::option::Option<Self> {
                let truncated = Self::from_bits_truncate(bits).0;
                if truncated == bits {
                    ::bitflags::__private::core::option::Option::Some(Self(bits))
                } else { ::bitflags::__private::core::option::Option::None }
            }
            /// Convert from a bits value, unsetting any unknown bits.
            #[inline]
            pub const fn from_bits_truncate(bits: u8) -> Self {
                Self(bits & Self::all().0)
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u8) -> Self { Self(bits) }
            /// Get a flags value with the bits of a flag with the given name set.
            ///
            /// This method will return `None` if `name` is empty or doesn't
            /// correspond to any named flag.
            #[inline]
            pub fn from_name(name: &str)
                -> ::bitflags::__private::core::option::Option<Self> {
                {
                    if name == "DROP" {
                        return ::bitflags::__private::core::option::Option::Some(Self(UsageSummary::DROP.bits()));
                    }
                };
                ;
                {
                    if name == "SHARED_BORROW" {
                        return ::bitflags::__private::core::option::Option::Some(Self(UsageSummary::SHARED_BORROW.bits()));
                    }
                };
                ;
                {
                    if name == "MUTATE" {
                        return ::bitflags::__private::core::option::Option::Some(Self(UsageSummary::MUTATE.bits()));
                    }
                };
                ;
                {
                    if name == "CAPTURE" {
                        return ::bitflags::__private::core::option::Option::Some(Self(UsageSummary::CAPTURE.bits()));
                    }
                };
                ;
                let _ = name;
                ::bitflags::__private::core::option::Option::None
            }
            /// Whether all bits in this flags value are unset.
            #[inline]
            pub const fn is_empty(&self) -> bool {
                self.0 == <u8 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all known bits in this flags value are set.
            #[inline]
            pub const fn is_all(&self) -> bool {
                Self::all().0 | self.0 == self.0
            }
            /// Whether any set bits in a source flags value are also set in a target flags value.
            #[inline]
            pub const fn intersects(&self, other: Self) -> bool {
                self.0 & other.0 != <u8 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all set bits in a source flags value are also set in a target flags value.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                self.0 & other.0 == other.0
            }
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            pub fn insert(&mut self, other: Self) {
                *self = Self(self.0).union(other);
            }
            /// The intersection of a source flags value with the complement of a target flags
            /// value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `remove` won't truncate `other`, but the `!` operator will.
            #[inline]
            pub fn remove(&mut self, other: Self) {
                *self = Self(self.0).difference(other);
            }
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            pub fn toggle(&mut self, other: Self) {
                *self = Self(self.0).symmetric_difference(other);
            }
            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
            #[inline]
            pub fn set(&mut self, other: Self, value: bool) {
                if value { self.insert(other); } else { self.remove(other); }
            }
            /// The bitwise and (`&`) of the bits in two flags values.
            #[inline]
            #[must_use]
            pub const fn intersection(self, other: Self) -> Self {
                Self(self.0 & other.0)
            }
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            #[must_use]
            pub const fn union(self, other: Self) -> Self {
                Self(self.0 | other.0)
            }
            /// The intersection of a source flags value with the complement of a target flags
            /// value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            #[must_use]
            pub const fn difference(self, other: Self) -> Self {
                Self(self.0 & !other.0)
            }
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            #[must_use]
            pub const fn symmetric_difference(self, other: Self) -> Self {
                Self(self.0 ^ other.0)
            }
            /// The bitwise negation (`!`) of the bits in a flags value, truncating the result.
            #[inline]
            #[must_use]
            pub const fn complement(self) -> Self {
                Self::from_bits_truncate(!self.0)
            }
        }
        impl ::bitflags::__private::core::fmt::Binary for UsageSummary {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::Octal for UsageSummary {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::LowerHex for UsageSummary {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::UpperHex for UsageSummary {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::ops::BitOr for UsageSummary {
            type Output = Self;
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            fn bitor(self, other: UsageSummary) -> Self { self.union(other) }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for UsageSummary {
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            fn bitor_assign(&mut self, other: Self) { self.insert(other); }
        }
        impl ::bitflags::__private::core::ops::BitXor for UsageSummary {
            type Output = Self;
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            fn bitxor(self, other: Self) -> Self {
                self.symmetric_difference(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitXorAssign for UsageSummary {
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
        }
        impl ::bitflags::__private::core::ops::BitAnd for UsageSummary {
            type Output = Self;
            /// The bitwise and (`&`) of the bits in two flags values.
            #[inline]
            fn bitand(self, other: Self) -> Self { self.intersection(other) }
        }
        impl ::bitflags::__private::core::ops::BitAndAssign for UsageSummary {
            /// The bitwise and (`&`) of the bits in two flags values.
            #[inline]
            fn bitand_assign(&mut self, other: Self) {
                *self =
                    Self::from_bits_retain(self.bits()).intersection(other);
            }
        }
        impl ::bitflags::__private::core::ops::Sub for UsageSummary {
            type Output = Self;
            /// The intersection of a source flags value with the complement of a target flags value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub(self, other: Self) -> Self { self.difference(other) }
        }
        impl ::bitflags::__private::core::ops::SubAssign for UsageSummary {
            /// The intersection of a source flags value with the complement of a target flags value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub_assign(&mut self, other: Self) { self.remove(other); }
        }
        impl ::bitflags::__private::core::ops::Not for UsageSummary {
            type Output = Self;
            /// The bitwise negation (`!`) of the bits in a flags value, truncating the result.
            #[inline]
            fn not(self) -> Self { self.complement() }
        }
        impl ::bitflags::__private::core::iter::Extend<UsageSummary> for
            UsageSummary {
            /// The bitwise or (`|`) of the bits in each flags value.
            fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
                = Self>>(&mut self, iterator: T) {
                for item in iterator { self.insert(item) }
            }
        }
        impl ::bitflags::__private::core::iter::FromIterator<UsageSummary> for
            UsageSummary {
            /// The bitwise or (`|`) of the bits in each flags value.
            fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
                = Self>>(iterator: T) -> Self {
                use ::bitflags::__private::core::iter::Extend;
                let mut result = Self::empty();
                result.extend(iterator);
                result
            }
        }
        impl UsageSummary {
            /// Yield a set of contained flags values.
            ///
            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
            /// will be yielded together as a final flags value.
            #[inline]
            pub const fn iter(&self) -> ::bitflags::iter::Iter<UsageSummary> {
                ::bitflags::iter::Iter::__private_const_new(<UsageSummary as
                        ::bitflags::Flags>::FLAGS,
                    UsageSummary::from_bits_retain(self.bits()),
                    UsageSummary::from_bits_retain(self.bits()))
            }
            /// Yield a set of contained named flags values.
            ///
            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
            #[inline]
            pub const fn iter_names(&self)
                -> ::bitflags::iter::IterNames<UsageSummary> {
                ::bitflags::iter::IterNames::__private_const_new(<UsageSummary
                        as ::bitflags::Flags>::FLAGS,
                    UsageSummary::from_bits_retain(self.bits()),
                    UsageSummary::from_bits_retain(self.bits()))
            }
        }
        impl ::bitflags::__private::core::iter::IntoIterator for UsageSummary
            {
            type Item = UsageSummary;
            type IntoIter = ::bitflags::iter::Iter<UsageSummary>;
            fn into_iter(self) -> Self::IntoIter { self.iter() }
        }
    };bitflags::bitflags! {
10    impl UsageSummary: u8 {
11        /// This parameter is dropped when it `needs_drop`.
12        const DROP = 1 << 0;
13        /// There is a shared borrow to this parameter.
14        /// It allows for mutation unless parameter is `Freeze`.
15        const SHARED_BORROW = 1 << 1;
16        /// This parameter is mutated (excluding through a drop or a shared borrow).
17        const MUTATE = 1 << 2;
18        /// This parameter is captured (excluding through a drop).
19        const CAPTURE = 1 << 3;
20    }
21}
22
23/// Parameter attributes that can only be determined by examining the body of a function instead
24/// of just its signature.
25///
26/// These can be useful for optimization purposes when a function is directly called. We compute
27/// them and store them into the crate metadata so that downstream crates can make use of them.
28///
29/// Right now, we have `readonly` and `captures(none)`, but `no_alias` might be useful in the
30/// future.
31#[derive(#[automatically_derived]
impl ::core::clone::Clone for DeducedParamAttrs {
    #[inline]
    fn clone(&self) -> DeducedParamAttrs {
        let _: ::core::clone::AssertParamIsClone<UsageSummary>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for DeducedParamAttrs { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for DeducedParamAttrs {
    #[inline]
    fn eq(&self, other: &DeducedParamAttrs) -> bool {
        self.usage == other.usage
    }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for DeducedParamAttrs {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "DeducedParamAttrs", "usage", &&self.usage)
    }
}Debug, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for DeducedParamAttrs {
            fn decode(__decoder: &mut __D) -> Self {
                DeducedParamAttrs {
                    usage: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for DeducedParamAttrs {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    DeducedParamAttrs { usage: ref __binding_0 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<'__ctx>
            ::rustc_data_structures::stable_hasher::HashStable<::rustc_query_system::ich::StableHashingContext<'__ctx>>
            for DeducedParamAttrs {
            #[inline]
            fn hash_stable(&self,
                __hcx:
                    &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    DeducedParamAttrs { usage: ref __binding_0 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable)]
32pub struct DeducedParamAttrs {
33    pub usage: UsageSummary,
34}
35
36impl DeducedParamAttrs {
37    /// Returns true if no attributes have been deduced.
38    #[inline]
39    pub fn is_default(self) -> bool {
40        self.usage.contains(UsageSummary::MUTATE | UsageSummary::CAPTURE)
41    }
42
43    /// For parameters passed indirectly, returns true if pointer is never written through.
44    pub fn read_only<'tcx>(
45        &self,
46        tcx: TyCtxt<'tcx>,
47        typing_env: TypingEnv<'tcx>,
48        ty: Ty<'tcx>,
49    ) -> bool {
50        // Only if all checks pass is this truly read-only.
51        if self.usage.contains(UsageSummary::MUTATE) {
52            return false;
53        }
54        if self.usage.contains(UsageSummary::DROP) && ty.needs_drop(tcx, typing_env) {
55            return false;
56        }
57        if self.usage.contains(UsageSummary::SHARED_BORROW) && !ty.is_freeze(tcx, typing_env) {
58            return false;
59        }
60        true
61    }
62
63    /// For parameters passed indirectly, returns true if pointer is not captured, i.e., its
64    /// address is not captured, and pointer is used neither for reads nor writes after function
65    /// returns.
66    pub fn captures_none<'tcx>(
67        &self,
68        tcx: TyCtxt<'tcx>,
69        typing_env: TypingEnv<'tcx>,
70        ty: Ty<'tcx>,
71    ) -> bool {
72        if self.usage.contains(UsageSummary::CAPTURE) {
73            return false;
74        }
75        if self.usage.contains(UsageSummary::DROP) && ty.needs_drop(tcx, typing_env) {
76            return false;
77        }
78        true
79    }
80}