# HG changeset patch # User Christian Brabandt # Date 1702581308 -3600 # Node ID aceaf677dd928e41a3b6ca18dae727c2495b667f # Parent 4d9213d8ba2327f7f78b04ff56bf47d22b1791b4 patch 9.0.2163: Vim9: type can be assigned to list/dict Commit: https://github.com/vim/vim/commit/fa831102c38c9192edf3aaf0cbcaff9ee5e006ac Author: Ernie Rael Date: Thu Dec 14 20:06:39 2023 +0100 patch 9.0.2163: Vim9: type can be assigned to list/dict Problem: Vim9: type can be assigned to list/dict Solution: Prevent assigning a `type` to a `list` or `dict` closes: #13683 Signed-off-by: Ernie Rael Signed-off-by: Christian Brabandt diff --git a/src/dict.c b/src/dict.c --- a/src/dict.c +++ b/src/dict.c @@ -1015,6 +1015,15 @@ eval_dict(char_u **arg, typval_T *rettv, clear_tv(&tvkey); goto failret; } + if (check_typval_is_value(&tv) == FAIL) + { + if (evaluate) + { + clear_tv(&tvkey); + clear_tv(&tv); + } + goto failret; + } if (evaluate) { item = dict_find(d, key, -1); diff --git a/src/list.c b/src/list.c --- a/src/list.c +++ b/src/list.c @@ -1576,6 +1576,12 @@ eval_list(char_u **arg, typval_T *rettv, { if (eval1(arg, &tv, evalarg) == FAIL) // recursive! goto failret; + if (check_typval_is_value(&tv) == FAIL) + { + if (evaluate) + clear_tv(&tv); + goto failret; + } if (evaluate) { item = listitem_alloc(); diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -3361,4 +3361,94 @@ def Test_assign_to_any() endfor enddef +def Test_assign_type_to_list_dict() + var lines =<< trim END + vim9script + class C + endclass + + var x = [C] + END + v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + + lines =<< trim END + vim9script + class C + endclass + type T = C + + def F() + var x = [3, T, C] + enddef + F() + END + v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + + lines =<< trim END + vim9script + type T = number + + def F() + var x = [3, T] + enddef + F() + END + v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value') + + lines =<< trim END + vim9script + class C + endclass + + var x = {e: C} + END + v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + + lines =<< trim END + vim9script + class C + endclass + + def F() + var x = {e: C} + enddef + F() + END + v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + + lines =<< trim END + vim9script + type T = number + + def F() + var x = {e: T} + enddef + F() + END + v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value') + + lines =<< trim END + vim9script + class C + endclass + + def F() + var x = {e: [C]} + enddef + F() + END + v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + + lines =<< trim END + vim9script + type T = number + + def F() + var x = {e: [T]} + enddef + F() + END + v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value') +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -190,7 +190,7 @@ def Test_class_basic() endclass sort([1.1, A], 'f') END - v9.CheckSourceFailure(lines, 'E1321: Using a Class as a Float', 4) + v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4) # Test for using object as a float lines =<< trim END diff --git a/src/testdir/test_vim9_typealias.vim b/src/testdir/test_vim9_typealias.vim --- a/src/testdir/test_vim9_typealias.vim +++ b/src/testdir/test_vim9_typealias.vim @@ -277,7 +277,7 @@ def Test_typealias() type B = number sort([1.1, B], 'f') END - v9.CheckSourceFailure(lines, 'E1401: Using type alias "B" as a Float', 3) + v9.CheckSourceFailure(lines, 'E1403: Type alias "B" cannot be used as a value', 3) # Creating a typealias in a def function lines =<< trim END diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2163, +/**/ 2162, /**/ 2161, diff --git a/src/vim9instr.c b/src/vim9instr.c --- a/src/vim9instr.c +++ b/src/vim9instr.c @@ -1333,7 +1333,8 @@ generate_NEWLIST(cctx_T *cctx, int count // Get the member type and the declared member type from all the items on // the stack. - member_type = get_member_type_from_stack(count, 1, cctx); + if ((member_type = get_member_type_from_stack(count, 1, cctx)) == NULL) + return FAIL; type = get_list_type(member_type, cctx->ctx_type_list); decl_type = get_list_type(&t_any, cctx->ctx_type_list); @@ -1361,7 +1362,8 @@ generate_NEWDICT(cctx_T *cctx, int count return FAIL; isn->isn_arg.number = use_null ? -1 : count; - member_type = get_member_type_from_stack(count, 2, cctx); + if ((member_type = get_member_type_from_stack(count, 2, cctx)) == NULL) + return FAIL; type = get_dict_type(member_type, cctx->ctx_type_list); decl_type = get_dict_type(&t_any, cctx->ctx_type_list); diff --git a/src/vim9type.c b/src/vim9type.c --- a/src/vim9type.c +++ b/src/vim9type.c @@ -1660,17 +1660,16 @@ get_member_type_from_stack( // Use "unknown" for an empty list or dict. if (count == 0) return &t_unknown; - - // Use the first value type for the list member type, then find the common - // type from following items. + // Find the common type from following items. typep = ((type2_T *)stack->ga_data) + stack->ga_len; - result = (typep -(count * skip) + skip - 1)->type_curr; - for (i = 1; i < count; ++i) + result = &t_unknown; + for (i = 0; i < count; ++i) { - if (result == &t_any) - break; // won't get more common type = (typep -((count - i) * skip) + skip - 1)->type_curr; - common_type(type, result, &result, type_gap); + if (check_type_is_value(type) == FAIL) + return NULL; + if (result != &t_any) + common_type(type, result, &result, type_gap); } return result;