Skip to main content

luaur_analysis/methods/
quantifier_visit_quantify_alt_b.rs

1use crate::enums::table_state::TableState;
2use crate::functions::get_mutable_type::get_mutable_type_id;
3use crate::records::quantifier::Quantifier;
4use crate::records::table_type::TableType;
5use crate::type_aliases::type_id::TypeId;
6use luaur_common::macros::luau_assert::LUAU_ASSERT;
7
8impl Quantifier {
9    pub fn visit_type_id_table_type(&mut self, ty: TypeId, ttv: &TableType) -> bool {
10        unsafe {
11            LUAU_ASSERT!(!get_mutable_type_id::<TableType>(ty).is_null());
12            let ttv_mut = &mut *get_mutable_type_id::<TableType>(ty);
13
14            if ttv_mut.state == TableState::Generic {
15                self.seen_generic_type = true;
16            }
17
18            if ttv_mut.state == TableState::Free {
19                self.seen_mutable_type = true;
20            }
21
22            // C++ `Quantifier::visit(TypeId, const TableType&)` (Quantify.cpp:68)
23            // gates on `level.subsumes(ttv.level)` — TypeLevel subsumption, the
24            // same gate the free-type/free-pack overloads use. The
25            // `subsumes(Scope*, Scope*)` member exists on the C++ struct but is
26            // vestigial; porting the gate to it left `scope` null, so the gate
27            // was always false and free tables were never quantified.
28            if !self.level.subsumes(&ttv_mut.level) {
29                if ttv_mut.state == TableState::Unsealed {
30                    self.seen_mutable_type = true;
31                }
32                return false;
33            }
34
35            if ttv_mut.state == TableState::Free {
36                ttv_mut.state = TableState::Generic;
37                self.seen_generic_type = true;
38            } else if ttv_mut.state == TableState::Unsealed {
39                ttv_mut.state = TableState::Sealed;
40            }
41
42            ttv_mut.level = self.level;
43
44            true
45        }
46    }
47}