luaur_analysis/functions/
quantify.rs1use crate::functions::get_mutable_type::getMutable;
2use crate::records::free_type::FreeType;
3use crate::records::free_type_pack::FreeTypePack;
4use crate::records::function_type::FunctionType;
5use crate::records::generic_type_visitor::{GenericTypeVisitor, GenericTypeVisitorTrait};
6use crate::records::quantifier::Quantifier;
7use crate::records::table_type::TableType;
8use crate::records::type_level::TypeLevel;
9use crate::type_aliases::type_id::TypeId;
10use crate::type_aliases::type_pack_id::TypePackId;
11use core::ffi::c_void;
12use luaur_common::macros::luau_assert::LUAU_ASSERT;
13use luaur_common::records::dense_hash_set::DenseHashSet;
14
15impl GenericTypeVisitorTrait for Quantifier {
21 type Seen = DenseHashSet<*mut c_void>;
22
23 fn visitor_base(&mut self) -> &mut GenericTypeVisitor<Self::Seen> {
24 &mut self.base.base
25 }
26
27 fn visit_type_id_free_type(&mut self, ty: TypeId, ftv: &FreeType) -> bool {
28 Quantifier::visit_type_id_free_type(self, ty, ftv)
29 }
30
31 fn visit_type_id_table_type(&mut self, ty: TypeId, ttv: &TableType) -> bool {
32 Quantifier::visit_type_id_table_type(self, ty, ttv)
33 }
34
35 fn visit_type_pack_id_free_type_pack(&mut self, tp: TypePackId, ftp: &FreeTypePack) -> bool {
36 Quantifier::visit_type_pack_id_free_type_pack(self, tp, ftp)
37 }
38}
39
40pub fn quantify(ty: TypeId, level: TypeLevel) {
41 let mut q = Quantifier::quantifier(level);
42 q.traverse_type_id(ty);
43
44 let ftv = unsafe { getMutable::<FunctionType>(ty) };
45 LUAU_ASSERT!(!ftv.is_null());
46 unsafe {
47 (*ftv).generics.extend(q.generics.iter().copied());
48 (*ftv).generic_packs.extend(q.generic_packs.iter().copied());
49 }
50}