luaur_analysis/methods/
magic_pack_handle_old_solver.rs1use crate::functions::flatten_type_pack::flatten_type_pack_id;
2use crate::functions::get_type_pack::get_type_pack_id;
3use crate::functions::reduce_union::reduce_union;
4use crate::records::module::Module;
5use crate::records::property_type::Property;
6use crate::records::scope::Scope;
7use crate::records::table_indexer::TableIndexer;
8use crate::records::table_type::TableType;
9use crate::records::type_checker::TypeChecker;
10use crate::records::type_pack::TypePack;
11use crate::records::union_type::UnionType;
12use crate::records::variadic_type_pack::VariadicTypePack;
13use crate::records::with_predicate::WithPredicate;
14use crate::type_aliases::props_type::Props;
15use crate::type_aliases::type_id::TypeId;
16use crate::type_aliases::type_pack_id::TypePackId;
17use alloc::string::ToString;
18use alloc::sync::Arc;
19use alloc::vec;
20use alloc::vec::Vec;
21use luaur_ast::records::ast_expr_call::AstExprCall;
22
23pub fn magic_pack_handle_old_solver(
24 typechecker: &mut TypeChecker,
25 scope: &Arc<Scope>,
26 _expr: &AstExprCall,
27 with_predicate: WithPredicate<TypePackId>,
28) -> Option<WithPredicate<TypePackId>> {
29 let param_pack = with_predicate.r#type;
30
31 let module = typechecker.current_module.as_ref()?;
32 let arena = unsafe { &mut (*(Arc::as_ptr(module) as *mut Module)).internal_types };
33
34 let (param_types, param_tail) = flatten_type_pack_id(param_pack);
35
36 let mut options: Vec<TypeId> = Vec::new();
37 options.reserve(param_types.len());
38 for ty in param_types {
39 options.push(ty);
40 }
41
42 if let Some(param_tail) = param_tail {
43 let vtp = unsafe { get_type_pack_id::<VariadicTypePack>(param_tail) };
44 if !vtp.is_null() {
45 options.push(unsafe { (*vtp).ty });
46 }
47 }
48
49 let options = reduce_union(&options);
50
51 let result = if options.is_empty() {
55 typechecker.nil_type
56 } else if options.len() == 1 {
57 options[0]
58 } else {
59 arena.add_type(UnionType { options })
60 };
61
62 let mut props = Props::default();
63 props.insert(
64 "n".to_string(),
65 Property::rw_type_id(typechecker.number_type),
66 );
67
68 let packed_table = arena.add_type(TableType {
69 props,
70 indexer: Some(TableIndexer {
71 index_type: typechecker.number_type,
72 index_result_type: result,
73 is_read_only: false,
74 }),
75 state: crate::enums::table_state::TableState::Sealed,
76 level: scope.level,
77 scope: core::ptr::null_mut(),
78 name: None,
79 synthetic_name: None,
80 instantiated_type_params: Vec::new(),
81 instantiated_type_pack_params: Vec::new(),
82 definition_module_name: Default::default(),
83 definition_location: Default::default(),
84 bound_to: None,
85 tags: Default::default(),
86 remaining_props: 0,
87 });
88
89 let result_pack = arena.add_type_pack_t(TypePack {
90 head: vec![packed_table],
91 tail: None,
92 });
93 Some(WithPredicate::with_predicate_t(result_pack))
94}