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(Clone, Copy, PartialEq, Debug, Decodable, Encodable, HashStable)]
7pub struct UsageSummary(u8);
8
9bitflags::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(Clone, Copy, PartialEq, Debug, Decodable, Encodable, 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}