rustc_middle/middle/
deduced_param_attrs.rs

1use rustc_macros::{Decodable, Encodable, HashStable};
2
3use crate::ty::{Ty, TyCtxt, TypingEnv};
4
5/// Flags that dictate how a parameter is mutated. If the flags are empty, the param is
6/// read-only. If non-empty, it is read-only if *all* flags' conditions are met.
7#[derive(Clone, Copy, PartialEq, Debug, Decodable, Encodable, HashStable)]
8pub struct DeducedReadOnlyParam(u8);
9
10bitflags::bitflags! {
11    impl DeducedReadOnlyParam: u8 {
12        /// This parameter is dropped. It is read-only if `!needs_drop`.
13        const IF_NO_DROP = 1 << 0;
14        /// This parameter is borrowed. It is read-only if `Freeze`.
15        const IF_FREEZE   = 1 << 1;
16        /// This parameter is mutated. It is never read-only.
17        const MUTATED     = 1 << 2;
18    }
19}
20
21/// Parameter attributes that can only be determined by examining the body of a function instead
22/// of just its signature.
23///
24/// These can be useful for optimization purposes when a function is directly called. We compute
25/// them and store them into the crate metadata so that downstream crates can make use of them.
26///
27/// Right now, we only have `read_only`, but `no_capture` and `no_alias` might be useful in the
28/// future.
29#[derive(Clone, Copy, PartialEq, Debug, Decodable, Encodable, HashStable)]
30pub struct DeducedParamAttrs {
31    /// The parameter is marked immutable in the function.
32    pub read_only: DeducedReadOnlyParam,
33}
34
35// By default, consider the parameters to be mutated.
36impl Default for DeducedParamAttrs {
37    #[inline]
38    fn default() -> DeducedParamAttrs {
39        DeducedParamAttrs { read_only: DeducedReadOnlyParam::MUTATED }
40    }
41}
42
43impl DeducedParamAttrs {
44    #[inline]
45    pub fn is_default(self) -> bool {
46        self.read_only.contains(DeducedReadOnlyParam::MUTATED)
47    }
48
49    pub fn read_only<'tcx>(
50        &self,
51        tcx: TyCtxt<'tcx>,
52        typing_env: TypingEnv<'tcx>,
53        ty: Ty<'tcx>,
54    ) -> bool {
55        let read_only = self.read_only;
56        // We have to check *all* set bits; only if all checks pass is this truly read-only.
57        if read_only.contains(DeducedReadOnlyParam::MUTATED) {
58            return false;
59        }
60        if read_only.contains(DeducedReadOnlyParam::IF_NO_DROP) && ty.needs_drop(tcx, typing_env) {
61            return false;
62        }
63        if read_only.contains(DeducedReadOnlyParam::IF_FREEZE) && !ty.is_freeze(tcx, typing_env) {
64            return false;
65        }
66        true
67    }
68}