luaur_analysis/functions/
set_table_metatable.rs1use crate::functions::get_mutable_type_function_runtime_alt_g::get_mutable_type_function_type_id;
2use crate::functions::get_tag::get_tag;
3use crate::functions::get_type_function_runtime_alt_o::get_type_function_type_id;
4use crate::functions::get_type_user_data::get_type_user_data;
5use crate::records::type_function_table_type::TypeFunctionTableType;
6use crate::type_aliases::lua_state::lua_State;
7use luaur_vm::functions::lua_gettop::lua_gettop;
8use luaur_vm::functions::lua_l_error_l::lua_l_error_l;
9
10pub unsafe fn set_table_metatable(l: *mut lua_State) -> i32 {
11 let vm_l = l as *mut luaur_vm::records::lua_state::lua_State;
12 let argument_count = lua_gettop(vm_l);
13 if argument_count != 2 {
14 lua_l_error_l(
15 vm_l,
16 c"%s".as_ptr(),
17 core::format_args!(
18 "type.setmetatable: expected 2 arguments, but got {}",
19 argument_count
20 ),
21 );
22 }
23
24 let self_ty = get_type_user_data(l, 1);
25
26 let tftt = get_mutable_type_function_type_id::<TypeFunctionTableType>(self_ty);
27 if tftt.is_null() {
28 lua_l_error_l(
29 vm_l,
30 c"%s".as_ptr(),
31 core::format_args!(
32 "type.setmetatable: expected self to be a table, but got {} instead",
33 get_tag(l, self_ty)
34 ),
35 );
36 }
37
38 if luaur_common::FFlag::LuauTypeFunctionSupportsFrozen.get() && (*self_ty).frozen {
39 lua_l_error_l(
40 vm_l,
41 c"%s".as_ptr(),
42 core::format_args!(
43 "type.setmetatable: cannot be called to mutate a frozen type, use `types.copy` to make a copy"
44 ),
45 );
46 }
47
48 let arg = get_type_user_data(l, 2);
49 if get_type_function_type_id::<TypeFunctionTableType>(arg).is_null() {
50 let tag_ty = if luaur_common::FFlag::LuauTypeFunctionRobustness.get() {
51 arg
52 } else {
53 self_ty
54 };
55 lua_l_error_l(
56 vm_l,
57 c"%s".as_ptr(),
58 core::format_args!(
59 "type.setmetatable: expected the argument to be a table, but got {} instead",
60 get_tag(l, tag_ty)
61 ),
62 );
63 }
64
65 (*tftt).metatable = Some(arg);
66
67 0
68}