sway_core/language/
purity.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/// The purity of a function is related to its access of contract storage. If a function accesses
/// or could potentially access contract storage, it is [Purity::Impure]. If a function does not utilize any
/// any accesses (reads _or_ writes) of storage, then it is [Purity::Pure].
#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Default)]
pub enum Purity {
    #[default]
    Pure,
    Reads,
    Writes,
    ReadsWrites,
}

impl Purity {
    pub fn can_call(&self, other: Purity) -> bool {
        match self {
            Purity::Pure => other == Purity::Pure,
            Purity::Reads => other == Purity::Pure || other == Purity::Reads,
            Purity::Writes => true, // storage(write) allows reading as well
            Purity::ReadsWrites => true,
        }
    }

    // Useful for error messages, show the syntax needed in the #[storage(...)] attribute.
    pub fn to_attribute_syntax(&self) -> String {
        use sway_types::constants::*;
        match self {
            Purity::Pure => "".to_owned(),
            Purity::Reads => STORAGE_PURITY_READ_NAME.to_owned(),
            Purity::Writes => STORAGE_PURITY_WRITE_NAME.to_owned(),
            Purity::ReadsWrites => {
                format!("{STORAGE_PURITY_READ_NAME}, {STORAGE_PURITY_WRITE_NAME}")
            }
        }
    }
}

/// Utility to find the union of purities.  To 'promote' Reads to Writes we want ReadsWrites, and
/// the same for Writes to Reads.
pub fn promote_purity(from: Purity, to: Purity) -> Purity {
    match (from, to) {
        (Purity::Reads, Purity::Writes)
        | (Purity::Writes, Purity::Reads)
        | (Purity::ReadsWrites, _) => Purity::ReadsWrites,
        _otherwise => to,
    }
}