Skip to main content

sway_core/
has_changes.rs

1/// Reports whether an operation that mutates declarations ([`crate::language::ty::TyDecl`]),
2/// type ids ([`crate::TypeId`]), or other entities in place actually changed anything.
3///
4/// It is used to propagate "did anything change" information across various
5/// in-place transformations, e.g., [`crate::SubstTypes`], declaration replacement,
6/// monomorphization, etc.
7#[derive(Default)]
8pub enum HasChanges {
9    Yes,
10    #[default]
11    No,
12}
13
14impl HasChanges {
15    pub fn has_changes(&self) -> bool {
16        matches!(self, HasChanges::Yes)
17    }
18}
19
20impl std::ops::BitOr for HasChanges {
21    type Output = HasChanges;
22
23    fn bitor(self, rhs: Self) -> Self::Output {
24        match (self, rhs) {
25            (HasChanges::No, HasChanges::No) => HasChanges::No,
26            _ => HasChanges::Yes,
27        }
28    }
29}
30
31impl std::ops::BitOrAssign for HasChanges {
32    fn bitor_assign(&mut self, rhs: Self) {
33        if rhs.has_changes() {
34            *self = HasChanges::Yes;
35        }
36    }
37}
38
39impl From<bool> for HasChanges {
40    fn from(value: bool) -> Self {
41        if value {
42            HasChanges::Yes
43        } else {
44            HasChanges::No
45        }
46    }
47}
48
49#[macro_export]
50macro_rules! has_changes {
51    ($($stmt:expr);* ;) => {{
52        let mut has_changes = $crate::HasChanges::No;
53        $(
54            has_changes |= $stmt;
55        )*
56        has_changes
57    }};
58}
59
60/// Like [`has_changes!`], but for use inside a [`sway_error::handler::Handler::scope`].
61///
62/// Each statement must evaluate to a `Result<HasChanges, ErrorEmitted>`. Errors are
63/// swallowed instead of short-circuiting: they remain captured by the enclosing scope,
64/// which will still report them, so every statement runs and independent sub-operations
65/// each get to emit their diagnostics.
66///
67/// Use this only inside a `Handler::scope` (or with a scope up the call stack). Outside a
68/// scope, a swallowed error would be lost from the returned `Result` even though it was
69/// emitted.
70#[macro_export]
71macro_rules! has_changes_scoped {
72    ($($stmt:expr);* ;) => {{
73        let mut has_changes = $crate::HasChanges::No;
74        $(
75            if let Ok(r) = $stmt {
76                has_changes |= r;
77            }
78        )*
79        has_changes
80    }};
81}