@@ -5,34 +5,57 @@ use emmylua_parser::{LuaAstNode, LuaCallExpr, LuaExpr};
55use crate :: {
66 db_index:: { DbIndex , LuaType } ,
77 semantic:: {
8- generic:: tpl_context:: TplContext , infer:: InferFailReason , infer_expr, LuaInferCache ,
8+ generic:: {
9+ tpl_context:: TplContext ,
10+ tpl_pattern:: {
11+ multi_param_tpl_pattern_match_multi_return, tpl_pattern_match,
12+ variadic_tpl_pattern_match,
13+ } ,
14+ } ,
15+ infer:: InferFailReason ,
16+ infer_expr, LuaInferCache ,
917 } ,
10- LuaFunctionType ,
18+ LuaFunctionType , TypeVisitTrait ,
1119} ;
1220
13- use super :: {
14- instantiate_type_generic:: instantiate_doc_function, tpl_pattern:: tpl_pattern_match_args,
15- TypeSubstitutor ,
16- } ;
21+ use super :: { instantiate_type_generic:: instantiate_doc_function, TypeSubstitutor } ;
1722
1823pub fn instantiate_func_generic (
1924 db : & DbIndex ,
2025 cache : & mut LuaInferCache ,
2126 func : & LuaFunctionType ,
2227 call_expr : LuaCallExpr ,
2328) -> Result < LuaFunctionType , InferFailReason > {
29+ let mut generic_tpls = HashSet :: new ( ) ;
30+ func. visit_type ( & mut |t| match t {
31+ LuaType :: TplRef ( generic_tpl) | LuaType :: ConstTplRef ( generic_tpl) => {
32+ let tpl_id = generic_tpl. get_tpl_id ( ) ;
33+ if tpl_id. is_func ( ) {
34+ generic_tpls. insert ( tpl_id) ;
35+ }
36+ }
37+ LuaType :: StrTplRef ( str_tpl) => {
38+ generic_tpls. insert ( str_tpl. get_tpl_id ( ) ) ;
39+ }
40+ _ => { }
41+ } ) ;
42+ if generic_tpls. is_empty ( ) {
43+ return Ok ( func. clone ( ) ) ;
44+ }
45+
2446 let origin_params = func. get_params ( ) ;
25- let func_param_types: Vec < _ > = origin_params
47+ let mut func_param_types: Vec < _ > = origin_params
2648 . iter ( )
2749 . map ( |( _, t) | t. clone ( ) . unwrap_or ( LuaType :: Unknown ) )
2850 . collect ( ) ;
29- let func_return_type = func. get_ret ( ) ;
3051
31- let mut generic_tpls = HashSet :: new ( ) ;
32- func. collect_generic_tpls ( & mut generic_tpls) ;
33-
34- let mut arg_types = collect_arg_types ( db, cache, & call_expr) ?;
52+ let arg_exprs = call_expr
53+ . get_args_list ( )
54+ . ok_or ( InferFailReason :: None ) ?
55+ . get_args ( )
56+ . collect :: < Vec < _ > > ( ) ;
3557 let mut substitutor = TypeSubstitutor :: new ( ) ;
58+ substitutor. add_need_infer_tpls ( generic_tpls) ;
3659 let mut context = TplContext {
3760 db,
3861 cache,
@@ -44,17 +67,81 @@ pub fn instantiate_func_generic(
4467 let colon_define = func. is_colon_define ( ) ;
4568 match ( colon_define, colon_call) {
4669 ( true , false ) => {
47- if !arg_types. is_empty ( ) {
48- arg_types. remove ( 0 ) ;
49- }
70+ func_param_types. insert ( 0 , LuaType :: Any ) ;
5071 }
5172 ( false , true ) => {
52- arg_types. insert ( 0 , LuaType :: Any ) ;
73+ if !func_param_types. is_empty ( ) {
74+ func_param_types. remove ( 0 ) ;
75+ }
5376 }
5477 _ => { }
5578 }
5679
57- tpl_pattern_match_args ( & mut context, & func_param_types, & arg_types) ?;
80+ let mut unresolve_tpls = vec ! [ ] ;
81+ for i in 0 ..func_param_types. len ( ) {
82+ if i >= arg_exprs. len ( ) {
83+ break ;
84+ }
85+
86+ if context. substitutor . is_infer_all_tpl ( ) {
87+ break ;
88+ }
89+
90+ let func_param_type = & func_param_types[ i] ;
91+ let call_arg_expr = & arg_exprs[ i] ;
92+ if !func_param_type. contain_tpl ( ) {
93+ continue ;
94+ }
95+
96+ if !func_param_type. is_variadic ( ) {
97+ if let LuaExpr :: ClosureExpr ( _) = call_arg_expr {
98+ // If the argument is a closure, we cannot infer the type from it.
99+ // We will handle this case later.
100+ unresolve_tpls. push ( ( func_param_type. clone ( ) , call_arg_expr. clone ( ) ) ) ;
101+ continue ;
102+ }
103+ }
104+
105+ let arg_type = infer_expr ( db, context. cache , call_arg_expr. clone ( ) ) ?;
106+
107+ match ( func_param_type, & arg_type) {
108+ ( LuaType :: Variadic ( variadic) , _) => {
109+ let mut arg_types = vec ! [ ] ;
110+ for arg_expr in & arg_exprs[ i..] {
111+ let arg_type = infer_expr ( db, context. cache , arg_expr. clone ( ) ) ?;
112+ arg_types. push ( arg_type) ;
113+ }
114+
115+ variadic_tpl_pattern_match ( & mut context, variadic, & arg_types) ?;
116+ break ;
117+ }
118+ ( _, LuaType :: Variadic ( variadic) ) => {
119+ multi_param_tpl_pattern_match_multi_return (
120+ & mut context,
121+ & func_param_types[ i..] ,
122+ variadic,
123+ ) ?;
124+ break ;
125+ }
126+ _ => {
127+ tpl_pattern_match ( & mut context, func_param_type, & arg_type) ?;
128+ }
129+ }
130+ }
131+
132+ if !context. substitutor . is_infer_all_tpl ( ) {
133+ for ( func_param_type, call_arg_expr) in unresolve_tpls {
134+ if let LuaExpr :: ClosureExpr ( _) = call_arg_expr {
135+ // If the argument is a closure, we cannot infer the type from it.
136+ // We will handle this case later.
137+ continue ;
138+ }
139+
140+ let closure_type = infer_expr ( db, context. cache , call_arg_expr) ?;
141+
142+ tpl_pattern_match ( & mut context, & func_param_type, & closure_type) ?;
143+ }
144+ }
58145
59146 if func. contain_self ( ) {
60147 infer_self_type ( db, cache, & call_expr, & mut substitutor) ?;
@@ -67,21 +154,6 @@ pub fn instantiate_func_generic(
67154 }
68155}
69156
70- fn collect_arg_types (
71- db : & DbIndex ,
72- cache : & mut LuaInferCache ,
73- call_expr : & LuaCallExpr ,
74- ) -> Result < Vec < LuaType > , InferFailReason > {
75- let arg_list = call_expr. get_args_list ( ) . ok_or ( InferFailReason :: None ) ?;
76- let mut arg_types = Vec :: new ( ) ;
77- for arg in arg_list. get_args ( ) {
78- let arg_type = infer_expr ( db, cache, arg. clone ( ) ) ?;
79- arg_types. push ( arg_type) ;
80- }
81-
82- Ok ( arg_types)
83- }
84-
85157fn infer_self_type (
86158 db : & DbIndex ,
87159 cache : & mut LuaInferCache ,
0 commit comments