1- use crate :: { DbIndex , LuaGenericType , LuaType , TypeSubstitutor } ;
1+ use std:: { collections:: HashMap , sync:: Arc } ;
2+
3+ use crate :: {
4+ humanize_type, semantic:: member:: find_members, DbIndex , LuaGenericType , LuaMemberOwner ,
5+ LuaType , LuaTypeCache , RenderLevel , TypeSubstitutor ,
6+ } ;
27
38use super :: {
49 check_general_type_compact, type_check_fail_reason:: TypeCheckFailReason ,
@@ -11,7 +16,7 @@ pub fn check_generic_type_compact(
1116 compact_type : & LuaType ,
1217 check_guard : TypeCheckGuard ,
1318) -> TypeCheckResult {
14- // Do not check generic classes that have not been instantiated yet
19+ // 不检查尚未实例化的泛型类
1520 if source_generic. contain_tpl ( ) {
1621 return Ok ( ( ) ) ;
1722 }
@@ -22,9 +27,8 @@ pub fn check_generic_type_compact(
2227 . get_type_decl ( & source_base_id)
2328 . ok_or ( TypeCheckFailReason :: TypeNotMatch ) ?;
2429
25- let type_params = source_generic. get_params ( ) ;
26-
2730 if type_decl. is_alias ( ) {
31+ let type_params = source_generic. get_params ( ) ;
2832 let substitutor = TypeSubstitutor :: from_alias ( type_params. clone ( ) , source_base_id) ;
2933 if let Some ( origin_type) = type_decl. get_alias_origin ( db, Some ( & substitutor) ) {
3034 return check_general_type_compact (
@@ -37,17 +41,19 @@ pub fn check_generic_type_compact(
3741 }
3842
3943 match compact_type {
40- LuaType :: Generic ( compact_generic) => {
41- return check_generic_type_compact_generic (
42- db,
43- source_generic,
44- compact_generic,
45- check_guard. next_level ( ) ?,
46- )
47- }
48- _ => {
49- return Err ( TypeCheckFailReason :: TypeNotMatch ) ;
50- }
44+ LuaType :: Generic ( compact_generic) => check_generic_type_compact_generic (
45+ db,
46+ source_generic,
47+ compact_generic,
48+ check_guard. next_level ( ) ?,
49+ ) ,
50+ LuaType :: TableConst ( range) => check_generic_type_compact_table (
51+ db,
52+ source_generic,
53+ LuaMemberOwner :: Element ( range. clone ( ) ) ,
54+ check_guard. next_level ( ) ?,
55+ ) ,
56+ _ => Err ( TypeCheckFailReason :: TypeNotMatch ) ,
5157 }
5258}
5359
@@ -69,10 +75,94 @@ fn check_generic_type_compact_generic(
6975 return Err ( TypeCheckFailReason :: TypeNotMatch ) ;
7076 }
7177
72- for i in 0 ..source_params. len ( ) {
73- let source_param = & source_params[ i] ;
74- let compact_param = & compact_params[ i] ;
75- check_general_type_compact ( db, source_param, compact_param, check_guard. next_level ( ) ?) ?;
78+ let next_guard = check_guard. next_level ( ) ?;
79+ for ( source_param, compact_param) in source_params. iter ( ) . zip ( compact_params. iter ( ) ) {
80+ check_general_type_compact ( db, source_param, compact_param, next_guard) ?;
81+ }
82+
83+ Ok ( ( ) )
84+ }
85+
86+ fn check_generic_type_compact_table (
87+ db : & DbIndex ,
88+ source_generic : & LuaGenericType ,
89+ table_owner : LuaMemberOwner ,
90+ check_guard : TypeCheckGuard ,
91+ ) -> TypeCheckResult {
92+ let member_index = db. get_member_index ( ) ;
93+
94+ // 构建表成员映射
95+ let table_member_map: HashMap < _ , _ > = member_index
96+ . get_members ( & table_owner)
97+ . map ( |members| {
98+ members
99+ . iter ( )
100+ . map ( |m| ( m. get_key ( ) . clone ( ) , m. get_id ( ) . clone ( ) ) )
101+ . collect ( )
102+ } )
103+ . unwrap_or_default ( ) ;
104+
105+ // 获取泛型类型的成员,使用 find_members 来获取包括继承的所有成员
106+ let source_type = LuaType :: Generic ( Arc :: new ( source_generic. clone ( ) ) ) ;
107+ let Some ( source_type_members) = find_members ( db, & source_type) else {
108+ return Ok ( ( ) ) ; // 空成员无需检查
109+ } ;
110+
111+ // 提前计算下一级检查守卫
112+ let next_guard = check_guard. next_level ( ) ?;
113+
114+ for source_member in source_type_members {
115+ let source_member_type = source_member. typ ;
116+ let key = source_member. key ;
117+
118+ match table_member_map. get ( & key) {
119+ Some ( table_member_id) => {
120+ let table_member = member_index
121+ . get_member ( table_member_id)
122+ . ok_or ( TypeCheckFailReason :: TypeNotMatch ) ?;
123+ let table_member_type = db
124+ . get_type_index ( )
125+ . get_type_cache ( & table_member. get_id ( ) . into ( ) )
126+ . unwrap_or ( & LuaTypeCache :: InferType ( LuaType :: Any ) )
127+ . as_type ( ) ;
128+
129+ if let Err ( TypeCheckFailReason :: TypeNotMatch ) = check_general_type_compact (
130+ db,
131+ & source_member_type,
132+ & table_member_type,
133+ next_guard,
134+ ) {
135+ return Err ( TypeCheckFailReason :: TypeNotMatchWithReason (
136+ t ! (
137+ "member %{name} type not match, expect %{expect}, got %{got}" ,
138+ name = key. to_path( ) ,
139+ expect = humanize_type( db, & source_member_type, RenderLevel :: Simple ) ,
140+ got = humanize_type( db, & table_member_type, RenderLevel :: Simple )
141+ )
142+ . to_string ( ) ,
143+ ) ) ;
144+ }
145+ }
146+ None if !source_member_type. is_optional ( ) => {
147+ return Err ( TypeCheckFailReason :: TypeNotMatchWithReason (
148+ t ! ( "missing member %{name}, in table" , name = key. to_path( ) ) . to_string ( ) ,
149+ ) ) ;
150+ }
151+ _ => { } // 可选成员未找到,继续检查
152+ }
153+ }
154+
155+ // 检查超类型
156+ let source_base_id = source_generic. get_base_type_id ( ) ;
157+ if let Some ( supers) = db. get_type_index ( ) . get_super_types ( & source_base_id) {
158+ let element_range = table_owner
159+ . get_element_range ( )
160+ . ok_or ( TypeCheckFailReason :: TypeNotMatch ) ?;
161+ let table_type = LuaType :: TableConst ( element_range. clone ( ) ) ;
162+
163+ for super_type in supers {
164+ check_general_type_compact ( db, & super_type, & table_type, next_guard) ?;
165+ }
76166 }
77167
78168 Ok ( ( ) )
0 commit comments