|
1 | 1 | use std::{collections::HashMap, sync::Arc}; |
2 | 2 |
|
3 | 3 | use crate::{ |
4 | | - LuaGenericType, LuaMemberOwner, LuaType, LuaTypeCache, RenderLevel, TypeSubstitutor, |
5 | | - humanize_type, |
| 4 | + LuaGenericType, LuaMemberOwner, LuaType, LuaTypeCache, LuaTypeDeclId, RenderLevel, |
| 5 | + TypeSubstitutor, humanize_type, |
6 | 6 | semantic::{ |
7 | 7 | member::find_members, |
8 | 8 | type_check::{is_sub_type_of, type_check_context::TypeCheckContext}, |
9 | 9 | }, |
10 | 10 | }; |
11 | 11 |
|
12 | 12 | use super::{ |
13 | | - TypeCheckResult, check_general_type_compact, check_ref_type_compact, |
14 | | - type_check_fail_reason::TypeCheckFailReason, type_check_guard::TypeCheckGuard, |
| 13 | + TypeCheckResult, check_general_type_compact, type_check_fail_reason::TypeCheckFailReason, |
| 14 | + type_check_guard::TypeCheckGuard, |
15 | 15 | }; |
16 | 16 |
|
17 | 17 | pub fn check_generic_type_compact( |
@@ -48,27 +48,50 @@ pub fn check_generic_type_compact( |
48 | 48 | if is_tpl { |
49 | 49 | return Ok(()); |
50 | 50 | } |
51 | | - check_generic_type_compact_generic( |
| 51 | + let first_result = check_generic_type_compact_generic( |
52 | 52 | context, |
53 | 53 | source_generic, |
54 | 54 | compact_generic, |
55 | 55 | check_guard.next_level()?, |
56 | | - ) |
| 56 | + ); |
| 57 | + if first_result.is_ok() { |
| 58 | + return Ok(()); |
| 59 | + } |
| 60 | + |
| 61 | + if let Some(supers) = context |
| 62 | + .db |
| 63 | + .get_type_index() |
| 64 | + .get_super_types(&compact_generic.get_base_type_id()) |
| 65 | + { |
| 66 | + for super_type in supers { |
| 67 | + let result = check_generic_type_compact( |
| 68 | + context, |
| 69 | + source_generic, |
| 70 | + &super_type, |
| 71 | + check_guard.next_level()?, |
| 72 | + ); |
| 73 | + if result.is_ok() { |
| 74 | + return Ok(()); |
| 75 | + } |
| 76 | + } |
| 77 | + } |
| 78 | + |
| 79 | + first_result |
57 | 80 | } |
58 | 81 | LuaType::TableConst(range) => check_generic_type_compact_table( |
59 | 82 | context, |
60 | 83 | source_generic, |
61 | 84 | LuaMemberOwner::Element(range.clone()), |
62 | 85 | check_guard.next_level()?, |
63 | 86 | ), |
64 | | - LuaType::Ref(_) | LuaType::Def(_) => { |
| 87 | + LuaType::Ref(ref_id) | LuaType::Def(ref_id) => { |
65 | 88 | if is_tpl { |
66 | 89 | return Ok(()); |
67 | 90 | } |
68 | | - check_ref_type_compact( |
| 91 | + check_generic_type_compact_ref_type( |
69 | 92 | context, |
70 | | - &source_generic.get_base_type_id(), |
71 | | - compact_type, |
| 93 | + source_generic, |
| 94 | + ref_id, |
72 | 95 | check_guard.next_level()?, |
73 | 96 | ) |
74 | 97 | } |
@@ -196,3 +219,47 @@ fn check_generic_type_compact_table( |
196 | 219 |
|
197 | 220 | Ok(()) |
198 | 221 | } |
| 222 | + |
| 223 | +fn check_generic_type_compact_ref_type( |
| 224 | + context: &TypeCheckContext, |
| 225 | + source_generic: &LuaGenericType, |
| 226 | + ref_id: &LuaTypeDeclId, |
| 227 | + check_guard: TypeCheckGuard, |
| 228 | +) -> TypeCheckResult { |
| 229 | + let type_decl = context |
| 230 | + .db |
| 231 | + .get_type_index() |
| 232 | + .get_type_decl(ref_id) |
| 233 | + .ok_or(TypeCheckFailReason::TypeNotMatch)?; |
| 234 | + |
| 235 | + if type_decl.is_alias() { |
| 236 | + if let Some(origin_type) = type_decl.get_alias_origin(context.db, None) { |
| 237 | + return check_general_type_compact( |
| 238 | + context, |
| 239 | + &LuaType::Generic(source_generic.clone().into()), |
| 240 | + &origin_type, |
| 241 | + check_guard.next_level()?, |
| 242 | + ); |
| 243 | + } |
| 244 | + } |
| 245 | + |
| 246 | + for super_type in context |
| 247 | + .db |
| 248 | + .get_type_index() |
| 249 | + .get_super_types(ref_id) |
| 250 | + .unwrap_or_default() |
| 251 | + { |
| 252 | + if check_generic_type_compact( |
| 253 | + context, |
| 254 | + source_generic, |
| 255 | + &super_type, |
| 256 | + check_guard.next_level()?, |
| 257 | + ) |
| 258 | + .is_ok() |
| 259 | + { |
| 260 | + return Ok(()); |
| 261 | + } |
| 262 | + } |
| 263 | + |
| 264 | + Err(TypeCheckFailReason::TypeNotMatch) |
| 265 | +} |
0 commit comments