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}