mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.4390: Vim9: list from declaration with inferred type not set
Problem: Vim9: list from declaration with inferred type does not set the type on the value. Solution: When inferring the type in a variable declaration also set the type of the list or dictionary. (closes #9705) Do not set the type when the member is "any".
This commit is contained in:
parent
4556a2e868
commit
e88c6b7a5d
@ -1885,6 +1885,19 @@ def Test_var_declaration_fails()
|
|||||||
v9.CheckDefFailure(['const foo: number'], 'E1021:')
|
v9.CheckDefFailure(['const foo: number'], 'E1021:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_var_declaration_inferred()
|
||||||
|
# check that type is set on the list so that extend() fails
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def GetList(): list<number>
|
||||||
|
var l = [1, 2, 3]
|
||||||
|
return l
|
||||||
|
enddef
|
||||||
|
echo GetList()->extend(['x'])
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E1013:', 6)
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_script_local_in_legacy()
|
def Test_script_local_in_legacy()
|
||||||
# OK to define script-local later but before compiling
|
# OK to define script-local later but before compiling
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
|
@ -1129,6 +1129,7 @@ def Test_extend_with_error_function()
|
|||||||
def Test()
|
def Test()
|
||||||
var d: dict<any> = {}
|
var d: dict<any> = {}
|
||||||
d->extend({A: 10, Func: function('F', [])})
|
d->extend({A: 10, Func: function('F', [])})
|
||||||
|
d.Func()
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
Test()
|
Test()
|
||||||
|
@ -427,6 +427,7 @@ def Test_disassemble_store_index()
|
|||||||
'\d PUSHS "dd"\_s*' ..
|
'\d PUSHS "dd"\_s*' ..
|
||||||
'\d NEWDICT size 0\_s*' ..
|
'\d NEWDICT size 0\_s*' ..
|
||||||
'\d NEWDICT size 1\_s*' ..
|
'\d NEWDICT size 1\_s*' ..
|
||||||
|
'\d SETTYPE dict<dict<unknown>>\_s*' ..
|
||||||
'\d STORE $0\_s*' ..
|
'\d STORE $0\_s*' ..
|
||||||
'd.dd\[0\] = 0\_s*' ..
|
'd.dd\[0\] = 0\_s*' ..
|
||||||
'\d PUSHNR 0\_s*' ..
|
'\d PUSHNR 0\_s*' ..
|
||||||
@ -457,7 +458,6 @@ def Test_disassemble_list_assign()
|
|||||||
'\d STORE $1\_s*' ..
|
'\d STORE $1\_s*' ..
|
||||||
'var l: list<any>\_s*' ..
|
'var l: list<any>\_s*' ..
|
||||||
'\d NEWLIST size 0\_s*' ..
|
'\d NEWLIST size 0\_s*' ..
|
||||||
'\d SETTYPE list<any>\_s*' ..
|
|
||||||
'\d STORE $2\_s*' ..
|
'\d STORE $2\_s*' ..
|
||||||
'\[x, y; l\] = g:stringlist\_s*' ..
|
'\[x, y; l\] = g:stringlist\_s*' ..
|
||||||
'\d LOADG g:stringlist\_s*' ..
|
'\d LOADG g:stringlist\_s*' ..
|
||||||
@ -470,7 +470,6 @@ def Test_disassemble_list_assign()
|
|||||||
'\d\+ CHECKTYPE string stack\[-1\] arg 2\_s*' ..
|
'\d\+ CHECKTYPE string stack\[-1\] arg 2\_s*' ..
|
||||||
'\d\+ STORE $1\_s*' ..
|
'\d\+ STORE $1\_s*' ..
|
||||||
'\d\+ SLICE 2\_s*' ..
|
'\d\+ SLICE 2\_s*' ..
|
||||||
'\d\+ SETTYPE list<any>\_s*' ..
|
|
||||||
'\d\+ STORE $2\_s*' ..
|
'\d\+ STORE $2\_s*' ..
|
||||||
'\d\+ RETURN void',
|
'\d\+ RETURN void',
|
||||||
res)
|
res)
|
||||||
@ -615,13 +614,14 @@ def s:LockLocal()
|
|||||||
lockvar d.a
|
lockvar d.a
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_disassemble_locl_local()
|
def Test_disassemble_lock_local()
|
||||||
var res = execute('disass s:LockLocal')
|
var res = execute('disass s:LockLocal')
|
||||||
assert_match('<SNR>\d*_LockLocal\_s*' ..
|
assert_match('<SNR>\d*_LockLocal\_s*' ..
|
||||||
'var d = {a: 1}\_s*' ..
|
'var d = {a: 1}\_s*' ..
|
||||||
'\d PUSHS "a"\_s*' ..
|
'\d PUSHS "a"\_s*' ..
|
||||||
'\d PUSHNR 1\_s*' ..
|
'\d PUSHNR 1\_s*' ..
|
||||||
'\d NEWDICT size 1\_s*' ..
|
'\d NEWDICT size 1\_s*' ..
|
||||||
|
'\d SETTYPE dict<number>\_s*' ..
|
||||||
'\d STORE $0\_s*' ..
|
'\d STORE $0\_s*' ..
|
||||||
'lockvar d.a\_s*' ..
|
'lockvar d.a\_s*' ..
|
||||||
'\d LOAD $0\_s*' ..
|
'\d LOAD $0\_s*' ..
|
||||||
@ -1626,6 +1626,7 @@ def Test_disassemble_list_index()
|
|||||||
'\d PUSHNR 2\_s*' ..
|
'\d PUSHNR 2\_s*' ..
|
||||||
'\d PUSHNR 3\_s*' ..
|
'\d PUSHNR 3\_s*' ..
|
||||||
'\d NEWLIST size 3\_s*' ..
|
'\d NEWLIST size 3\_s*' ..
|
||||||
|
'\d SETTYPE list<number>\_s*' ..
|
||||||
'\d STORE $0\_s*' ..
|
'\d STORE $0\_s*' ..
|
||||||
'var res = l\[1]\_s*' ..
|
'var res = l\[1]\_s*' ..
|
||||||
'\d LOAD $0\_s*' ..
|
'\d LOAD $0\_s*' ..
|
||||||
@ -1650,13 +1651,15 @@ def Test_disassemble_list_slice()
|
|||||||
'\d PUSHNR 2\_s*' ..
|
'\d PUSHNR 2\_s*' ..
|
||||||
'\d PUSHNR 3\_s*' ..
|
'\d PUSHNR 3\_s*' ..
|
||||||
'\d NEWLIST size 3\_s*' ..
|
'\d NEWLIST size 3\_s*' ..
|
||||||
|
'\d SETTYPE list<number>\_s*' ..
|
||||||
'\d STORE $0\_s*' ..
|
'\d STORE $0\_s*' ..
|
||||||
'var res = l\[1 : 8]\_s*' ..
|
'var res = l\[1 : 8]\_s*' ..
|
||||||
'\d LOAD $0\_s*' ..
|
'\d LOAD $0\_s*' ..
|
||||||
'\d PUSHNR 1\_s*' ..
|
'\d PUSHNR 1\_s*' ..
|
||||||
'\d PUSHNR 8\_s*' ..
|
'\d PUSHNR 8\_s*' ..
|
||||||
'\d LISTSLICE\_s*' ..
|
'\d\+ LISTSLICE\_s*' ..
|
||||||
'\d STORE $1\_s*',
|
'\d\+ SETTYPE list<number>\_s*' ..
|
||||||
|
'\d\+ STORE $1\_s*',
|
||||||
instr)
|
instr)
|
||||||
assert_equal([2, 3], ListSlice())
|
assert_equal([2, 3], ListSlice())
|
||||||
enddef
|
enddef
|
||||||
@ -1675,6 +1678,7 @@ def Test_disassemble_dict_member()
|
|||||||
'\d PUSHS "item"\_s*' ..
|
'\d PUSHS "item"\_s*' ..
|
||||||
'\d PUSHNR 1\_s*' ..
|
'\d PUSHNR 1\_s*' ..
|
||||||
'\d NEWDICT size 1\_s*' ..
|
'\d NEWDICT size 1\_s*' ..
|
||||||
|
'\d SETTYPE dict<number>\_s*' ..
|
||||||
'\d STORE $0\_s*' ..
|
'\d STORE $0\_s*' ..
|
||||||
'var res = d.item\_s*' ..
|
'var res = d.item\_s*' ..
|
||||||
'\d\+ LOAD $0\_s*' ..
|
'\d\+ LOAD $0\_s*' ..
|
||||||
@ -2541,6 +2545,7 @@ def Test_disassemble_dict_stack()
|
|||||||
'\d PUSHS "func"\_s*' ..
|
'\d PUSHS "func"\_s*' ..
|
||||||
'\d PUSHFUNC "<80><fd>R\d\+_Legacy"\_s*' ..
|
'\d PUSHFUNC "<80><fd>R\d\+_Legacy"\_s*' ..
|
||||||
'\d NEWDICT size 1\_s*' ..
|
'\d NEWDICT size 1\_s*' ..
|
||||||
|
'\d SETTYPE dict<func(...): any>\_s*' ..
|
||||||
'\d STORE $0\_s*' ..
|
'\d STORE $0\_s*' ..
|
||||||
|
|
||||||
'var v = d.func()\_s*' ..
|
'var v = d.func()\_s*' ..
|
||||||
|
@ -750,6 +750,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 */
|
||||||
|
/**/
|
||||||
|
4390,
|
||||||
/**/
|
/**/
|
||||||
4389,
|
4389,
|
||||||
/**/
|
/**/
|
||||||
|
@ -2002,6 +2002,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
int instr_count = -1;
|
int instr_count = -1;
|
||||||
int save_lnum;
|
int save_lnum;
|
||||||
int skip_store = FALSE;
|
int skip_store = FALSE;
|
||||||
|
type_T *inferred_type = NULL;
|
||||||
|
|
||||||
if (var_start[0] == '_' && !eval_isnamec(var_start[1]))
|
if (var_start[0] == '_' && !eval_isnamec(var_start[1]))
|
||||||
{
|
{
|
||||||
@ -2126,7 +2127,10 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
else if (rhs_type == &t_unknown)
|
else if (rhs_type == &t_unknown)
|
||||||
lhs.lhs_lvar->lv_type = &t_any;
|
lhs.lhs_lvar->lv_type = &t_any;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
lhs.lhs_lvar->lv_type = rhs_type;
|
lhs.lhs_lvar->lv_type = rhs_type;
|
||||||
|
inferred_type = rhs_type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (*op == '=')
|
else if (*op == '=')
|
||||||
@ -2146,7 +2150,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
cctx))
|
cctx))
|
||||||
use_type = lhs.lhs_member_type;
|
use_type = lhs.lhs_member_type;
|
||||||
if (need_type_where(rhs_type, use_type, -1, where,
|
if (need_type_where(rhs_type, use_type, -1, where,
|
||||||
cctx, FALSE, is_const) == FAIL)
|
cctx, FALSE, is_const) == FAIL)
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2315,10 +2319,20 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
if ((lhs.lhs_type->tt_type == VAR_DICT
|
if ((lhs.lhs_type->tt_type == VAR_DICT
|
||||||
|| lhs.lhs_type->tt_type == VAR_LIST)
|
|| lhs.lhs_type->tt_type == VAR_LIST)
|
||||||
&& lhs.lhs_type->tt_member != NULL
|
&& lhs.lhs_type->tt_member != NULL
|
||||||
|
&& lhs.lhs_type->tt_member != &t_any
|
||||||
&& lhs.lhs_type->tt_member != &t_unknown)
|
&& lhs.lhs_type->tt_member != &t_unknown)
|
||||||
// Set the type in the list or dict, so that it can be checked,
|
// Set the type in the list or dict, so that it can be checked,
|
||||||
// also in legacy script.
|
// also in legacy script.
|
||||||
generate_SETTYPE(cctx, lhs.lhs_type);
|
generate_SETTYPE(cctx, lhs.lhs_type);
|
||||||
|
else if (inferred_type != NULL
|
||||||
|
&& (inferred_type->tt_type == VAR_DICT
|
||||||
|
|| inferred_type->tt_type == VAR_LIST)
|
||||||
|
&& inferred_type->tt_member != NULL
|
||||||
|
&& inferred_type->tt_member != &t_unknown
|
||||||
|
&& inferred_type->tt_member != &t_any)
|
||||||
|
// Set the type in the list or dict, so that it can be checked,
|
||||||
|
// also in legacy script.
|
||||||
|
generate_SETTYPE(cctx, inferred_type);
|
||||||
|
|
||||||
if (!skip_store && generate_store_lhs(cctx, &lhs,
|
if (!skip_store && generate_store_lhs(cctx, &lhs,
|
||||||
instr_count, is_decl) == FAIL)
|
instr_count, is_decl) == FAIL)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user