1+ use std:: ops:: Deref ;
2+
13use emmylua_parser:: {
24 LuaAssignStat , LuaAst , LuaAstNode , LuaCallArgList , LuaCallExpr , LuaExpr , LuaIndexMemberExpr ,
35 LuaLiteralToken , LuaLocalStat , LuaTableExpr , LuaTableField ,
@@ -6,7 +8,7 @@ use emmylua_parser::{
68use crate :: {
79 db_index:: { DbIndex , LuaType } ,
810 infer_call_expr_func, infer_expr, InferGuard , LuaDeclId , LuaInferCache , LuaMemberId ,
9- LuaTupleType ,
11+ LuaMultiReturn , LuaTupleType ,
1012} ;
1113
1214use super :: {
@@ -44,29 +46,65 @@ fn infer_table_tuple_or_array(
4446 return Ok ( LuaType :: Array ( first_type. into ( ) ) ) ;
4547 }
4648
47- if let Some ( last_field) = fields. last ( ) {
48- let last_value_expr = last_field. get_value_expr ( ) . ok_or ( InferFailReason :: None ) ?;
49- if is_dots_expr ( & last_value_expr) . unwrap_or ( false ) {
50- let dots_type = infer_expr ( db, cache, last_value_expr) ?;
51- let typ = match & dots_type {
52- LuaType :: MuliReturn ( multi) => multi. get_type ( 0 ) . unwrap_or ( & LuaType :: Unknown ) ,
53- _ => & dots_type,
54- } ;
49+ if let Some ( first_field) = fields. first ( ) {
50+ let first_value_expr = first_field. get_value_expr ( ) . ok_or ( InferFailReason :: None ) ?;
5551
56- return Ok ( LuaType :: Array ( typ. clone ( ) . into ( ) ) ) ;
52+ if is_dots_expr ( & first_value_expr) . unwrap_or ( false ) {
53+ let first_expr_type = infer_expr ( db, cache, first_value_expr) ?;
54+ match & first_expr_type {
55+ LuaType :: MuliReturn ( multi) => match & multi. deref ( ) {
56+ LuaMultiReturn :: Base ( base) => {
57+ return Ok ( LuaType :: Array ( base. clone ( ) . into ( ) ) ) ;
58+ }
59+ LuaMultiReturn :: Multi ( tuple) => {
60+ return Ok ( LuaType :: Tuple ( LuaTupleType :: new ( tuple. clone ( ) ) . into ( ) ) ) ;
61+ }
62+ } ,
63+ LuaType :: Variadic ( base) => {
64+ return Ok ( LuaType :: Array ( base. clone ( ) . into ( ) ) ) ;
65+ }
66+ _ => {
67+ return Ok ( LuaType :: Array ( first_expr_type. into ( ) ) ) ;
68+ }
69+ } ;
5770 }
5871 }
5972
6073 let mut types = Vec :: new ( ) ;
6174 for field in fields {
6275 let value_expr = field. get_value_expr ( ) . ok_or ( InferFailReason :: None ) ?;
6376 let typ = infer_expr ( db, cache, value_expr) ?;
64- types. push ( typ) ;
77+ match typ {
78+ LuaType :: MuliReturn ( multi) => flatten_multi_into_tuple ( & mut types, & multi) ,
79+ _ => {
80+ types. push ( typ) ;
81+ }
82+ }
6583 }
6684
6785 Ok ( LuaType :: Tuple ( LuaTupleType :: new ( types) . into ( ) ) )
6886}
6987
88+ fn flatten_multi_into_tuple ( tuple_list : & mut Vec < LuaType > , multi : & LuaMultiReturn ) {
89+ match multi {
90+ LuaMultiReturn :: Base ( base) => {
91+ tuple_list. push ( LuaType :: Variadic ( base. clone ( ) . into ( ) ) ) ;
92+ }
93+ LuaMultiReturn :: Multi ( multi) => {
94+ for typ in multi {
95+ match typ {
96+ LuaType :: MuliReturn ( multi) => {
97+ flatten_multi_into_tuple ( tuple_list, multi. deref ( ) ) ;
98+ }
99+ _ => {
100+ tuple_list. push ( typ. clone ( ) ) ;
101+ }
102+ }
103+ }
104+ }
105+ }
106+ }
107+
70108fn is_dots_expr ( expr : & LuaExpr ) -> Option < bool > {
71109 if let LuaExpr :: LiteralExpr ( literal) = expr {
72110 match literal. get_literal ( ) ? {
0 commit comments