# HG changeset patch # User Bram Moolenaar # Date 1582236005 -3600 # Node ID f41e46f02c8c14113b7f63e41471e226ba8a79e1 # Parent f4820960d7e8e9d0e9358f2cc387bc0eba9f5a9f patch 8.2.0291: Vim9: assigning [] to list doesn't work Commit: https://github.com/vim/vim/commit/436472f5e0328dc4a635b1c344c04a62d64132ea Author: Bram Moolenaar Date: Thu Feb 20 22:54:43 2020 +0100 patch 8.2.0291: Vim9: assigning [] to list doesn't work Problem: Vim9: assigning [] to list doesn't work. Solution: Use void for empty list and dict. (Ken Takata, closes https://github.com/vim/vim/issues/5669) diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -400,6 +400,8 @@ EXTERN type_T t_partial_any INIT4(VAR_PA EXTERN type_T t_list_any INIT4(VAR_LIST, 0, &t_any, NULL); EXTERN type_T t_dict_any INIT4(VAR_DICT, 0, &t_any, NULL); +EXTERN type_T t_list_empty INIT4(VAR_LIST, 0, &t_void, NULL); +EXTERN type_T t_dict_empty INIT4(VAR_DICT, 0, &t_void, NULL); EXTERN type_T t_list_number INIT4(VAR_LIST, 0, &t_number, NULL); EXTERN type_T t_list_string INIT4(VAR_LIST, 0, &t_string, NULL); @@ -1496,7 +1498,7 @@ EXTERN int netbeansSuppressNoLines INIT( * Excluded are errors that are only used once and debugging messages. */ EXTERN char e_abort[] INIT(= N_("E470: Command aborted")); -EXTERN char e_argreq[] INIT(= N_("E471: Argument required")); +EXTERN char e_argreq[] INIT(= N_("E471: Argument required")); EXTERN char e_backslash[] INIT(= N_("E10: \\ should be followed by /, ? or &")); #ifdef FEAT_CMDWIN EXTERN char e_cmdwin[] INIT(= N_("E11: Invalid in command-line window; executes, CTRL-C quits")); @@ -1639,7 +1641,7 @@ EXTERN char e_invalblob[] INIT(= N_("E97 EXTERN char e_toomanyarg[] INIT(= N_("E118: Too many arguments for function: %s")); EXTERN char e_toofewarg[] INIT(= N_("E119: Not enough arguments for function: %s")); EXTERN char e_func_deleted[] INIT(= N_("E933: Function was deleted: %s")); -EXTERN char e_dictkey[] INIT(= N_("E716: Key not present in Dictionary: %s")); +EXTERN char e_dictkey[] INIT(= N_("E716: Key not present in Dictionary: %s")); EXTERN char e_listreq[] INIT(= N_("E714: List required")); EXTERN char e_listblobreq[] INIT(= N_("E897: List or Blob required")); EXTERN char e_listdictarg[] INIT(= N_("E712: Argument of %s must be a List or Dictionary")); diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -40,9 +40,8 @@ def Test_assignment() let list1: list = ['sdf', 'asdf'] let list2: list = [1, 2, 3] - " TODO: does not work yet - " let listS: list = [] - " let listN: list = [] + let listS: list = [] + let listN: list = [] let dict1: dict = #{key: 'value'} let dict2: dict = #{one: 1, two: 2} diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -739,6 +739,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 291, +/**/ 290, /**/ 289, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -211,6 +211,8 @@ get_list_type(type_T *member_type, garra // recognize commonly used types if (member_type->tt_type == VAR_UNKNOWN) return &t_list_any; + if (member_type->tt_type == VAR_VOID) + return &t_list_empty; if (member_type->tt_type == VAR_NUMBER) return &t_list_number; if (member_type->tt_type == VAR_STRING) @@ -234,6 +236,8 @@ get_dict_type(type_T *member_type, garra // recognize commonly used types if (member_type->tt_type == VAR_UNKNOWN) return &t_dict_any; + if (member_type->tt_type == VAR_VOID) + return &t_dict_empty; if (member_type->tt_type == VAR_NUMBER) return &t_dict_number; if (member_type->tt_type == VAR_STRING) @@ -813,11 +817,12 @@ generate_NEWLIST(cctx_T *cctx, int count // drop the value types stack->ga_len -= count; - // use the first value type for the list member type + // Use the first value type for the list member type. Use "void" for an + // empty list. if (count > 0) member = ((type_T **)stack->ga_data)[stack->ga_len]; else - member = &t_any; + member = &t_void; type = get_list_type(member, type_list); // add the list type to the type stack @@ -848,11 +853,12 @@ generate_NEWDICT(cctx_T *cctx, int count // drop the key and value types stack->ga_len -= 2 * count; - // use the first value type for the list member type + // Use the first value type for the list member type. Use "void" for an + // empty dict. if (count > 0) member = ((type_T **)stack->ga_data)[stack->ga_len + 1]; else - member = &t_any; + member = &t_void; type = get_dict_type(member, type_list); // add the dict type to the type stack @@ -1854,8 +1860,13 @@ check_type(type_T *expected, type_T *act } if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST) { - int ret = check_type(expected->tt_member, actual->tt_member, - FALSE); + int ret; + + // void is used for an empty list or dict + if (actual->tt_member == &t_void) + ret = OK; + else + ret = check_type(expected->tt_member, actual->tt_member, FALSE); if (ret == FAIL && give_msg) type_mismatch(expected, actual); return ret; @@ -1873,7 +1884,7 @@ check_type(type_T *expected, type_T *act static int need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx) { - if (equal_type(actual, expected) || expected->tt_type == VAR_UNKNOWN) + if (check_type(expected, actual, FALSE)) return OK; if (actual->tt_type != VAR_UNKNOWN) {