0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

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 <errael@raelity.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Ernie Rael
2023-12-14 20:06:39 +01:00
committed by Christian Brabandt
parent 2a71b54d35
commit fa831102c3
8 changed files with 120 additions and 12 deletions

View File

@@ -1015,6 +1015,15 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal)
clear_tv(&tvkey); clear_tv(&tvkey);
goto failret; goto failret;
} }
if (check_typval_is_value(&tv) == FAIL)
{
if (evaluate)
{
clear_tv(&tvkey);
clear_tv(&tv);
}
goto failret;
}
if (evaluate) if (evaluate)
{ {
item = dict_find(d, key, -1); item = dict_find(d, key, -1);

View File

@@ -1576,6 +1576,12 @@ eval_list(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error)
{ {
if (eval1(arg, &tv, evalarg) == FAIL) // recursive! if (eval1(arg, &tv, evalarg) == FAIL) // recursive!
goto failret; goto failret;
if (check_typval_is_value(&tv) == FAIL)
{
if (evaluate)
clear_tv(&tv);
goto failret;
}
if (evaluate) if (evaluate)
{ {
item = listitem_alloc(); item = listitem_alloc();

View File

@@ -3361,4 +3361,94 @@ def Test_assign_to_any()
endfor endfor
enddef 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 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker

View File

@@ -190,7 +190,7 @@ def Test_class_basic()
endclass endclass
sort([1.1, A], 'f') sort([1.1, A], 'f')
END 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 # Test for using object as a float
lines =<< trim END lines =<< trim END

View File

@@ -277,7 +277,7 @@ def Test_typealias()
type B = number type B = number
sort([1.1, B], 'f') sort([1.1, B], 'f')
END 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 # Creating a typealias in a def function
lines =<< trim END lines =<< trim END

View File

@@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2163,
/**/ /**/
2162, 2162,
/**/ /**/

View File

@@ -1333,7 +1333,8 @@ generate_NEWLIST(cctx_T *cctx, int count, int use_null)
// Get the member type and the declared member type from all the items on // Get the member type and the declared member type from all the items on
// the stack. // 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); type = get_list_type(member_type, cctx->ctx_type_list);
decl_type = get_list_type(&t_any, 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, int use_null)
return FAIL; return FAIL;
isn->isn_arg.number = use_null ? -1 : count; 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); type = get_dict_type(member_type, cctx->ctx_type_list);
decl_type = get_dict_type(&t_any, cctx->ctx_type_list); decl_type = get_dict_type(&t_any, cctx->ctx_type_list);

View File

@@ -1660,16 +1660,15 @@ get_member_type_from_stack(
// Use "unknown" for an empty list or dict. // Use "unknown" for an empty list or dict.
if (count == 0) if (count == 0)
return &t_unknown; return &t_unknown;
// Find the common type from following items.
// Use the first value type for the list member type, then find the common
// type from following items.
typep = ((type2_T *)stack->ga_data) + stack->ga_len; typep = ((type2_T *)stack->ga_data) + stack->ga_len;
result = (typep -(count * skip) + skip - 1)->type_curr; result = &t_unknown;
for (i = 1; i < count; ++i) 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; type = (typep -((count - i) * skip) + skip - 1)->type_curr;
if (check_type_is_value(type) == FAIL)
return NULL;
if (result != &t_any)
common_type(type, result, &result, type_gap); common_type(type, result, &result, type_gap);
} }