Skip to main content

luaur_analysis/methods/
txn_log_commit.rs

1use crate::functions::as_mutable_type::as_mutable_type_id;
2use crate::functions::as_mutable_type_pack::as_mutable_type_pack_id;
3use crate::functions::occurs_txn_log::occurs_txn_log_type_id_type_id;
4use crate::records::pending_type::PendingType;
5use crate::records::pending_type_pack::PendingTypePack;
6use crate::records::txn_log::TxnLog;
7use crate::type_aliases::type_id::TypeId;
8use crate::type_aliases::type_pack_id::TypePackId;
9use alloc::vec::Vec;
10use luaur_common::macros::luau_assert::LUAU_ASSERT;
11
12impl TxnLog {
13    pub fn commit(&mut self) {
14        LUAU_ASSERT!(!self.radioactive);
15
16        // The change maps are not mutated by occurs()/followOnce() (those only read
17        // pending state), and Box gives stable addresses, so we snapshot the raw
18        // pointers up front. This mirrors C++ iterating the map while passing
19        // `*this` to occurs().
20        let type_var_entries: Vec<(TypeId, *const PendingType, bool)> = self
21            .type_var_changes
22            .iter()
23            .map(|(ty, rep)| (*ty, rep.as_ref() as *const PendingType, rep.dead))
24            .collect();
25
26        for (ty, rep, dead) in type_var_entries {
27            if !dead {
28                let unfollowed: TypeId = unsafe { &(*rep).pending as *const _ };
29
30                if !occurs_txn_log_type_id_type_id(self, unfollowed, ty) {
31                    unsafe {
32                        (*as_mutable_type_id(ty)).reassign(&*unfollowed);
33                    }
34                }
35            }
36        }
37
38        let type_pack_entries: Vec<(TypePackId, *const PendingTypePack)> = self
39            .type_pack_changes
40            .iter()
41            .map(|(tp, rep)| (*tp, rep.as_ref() as *const PendingTypePack))
42            .collect();
43
44        for (tp, rep) in type_pack_entries {
45            unsafe {
46                (*as_mutable_type_pack_id(tp)).reassign(&(*rep).pending);
47            }
48        }
49
50        self.clear();
51    }
52}