summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-02-15 15:37:11 +0000
committerBram Moolenaar <Bram@vim.org>2022-02-15 15:37:11 +0000
commite88c6b7a5d8b24f8aa9a3e976b78654bae293ae4 (patch)
tree465389083108b640db744bf4c06673695f7497a9
parent4556a2e8681c5c98fb4c7ca0a016924a69b4452a (diff)
downloadvim-git-e88c6b7a5d8b24f8aa9a3e976b78654bae293ae4.tar.gz
patch 8.2.4390: Vim9: list from declaration with inferred type not setv8.2.4390
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".
-rw-r--r--src/testdir/test_vim9_assign.vim13
-rw-r--r--src/testdir/test_vim9_builtin.vim1
-rw-r--r--src/testdir/test_vim9_disassemble.vim15
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c16
5 files changed, 41 insertions, 6 deletions
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index 8a00cebab..9c988c96f 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -1885,6 +1885,19 @@ def Test_var_declaration_fails()
v9.CheckDefFailure(['const foo: number'], 'E1021:')
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()
# OK to define script-local later but before compiling
var lines =<< trim END
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index 23b9c4936..09cfd707d 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -1129,6 +1129,7 @@ def Test_extend_with_error_function()
def Test()
var d: dict<any> = {}
d->extend({A: 10, Func: function('F', [])})
+ d.Func()
enddef
Test()
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index ec7183660..91464a768 100644
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -427,6 +427,7 @@ def Test_disassemble_store_index()
'\d PUSHS "dd"\_s*' ..
'\d NEWDICT size 0\_s*' ..
'\d NEWDICT size 1\_s*' ..
+ '\d SETTYPE dict<dict<unknown>>\_s*' ..
'\d STORE $0\_s*' ..
'd.dd\[0\] = 0\_s*' ..
'\d PUSHNR 0\_s*' ..
@@ -457,7 +458,6 @@ def Test_disassemble_list_assign()
'\d STORE $1\_s*' ..
'var l: list<any>\_s*' ..
'\d NEWLIST size 0\_s*' ..
- '\d SETTYPE list<any>\_s*' ..
'\d STORE $2\_s*' ..
'\[x, y; l\] = 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\+ STORE $1\_s*' ..
'\d\+ SLICE 2\_s*' ..
- '\d\+ SETTYPE list<any>\_s*' ..
'\d\+ STORE $2\_s*' ..
'\d\+ RETURN void',
res)
@@ -615,13 +614,14 @@ def s:LockLocal()
lockvar d.a
enddef
-def Test_disassemble_locl_local()
+def Test_disassemble_lock_local()
var res = execute('disass s:LockLocal')
assert_match('<SNR>\d*_LockLocal\_s*' ..
'var d = {a: 1}\_s*' ..
'\d PUSHS "a"\_s*' ..
'\d PUSHNR 1\_s*' ..
'\d NEWDICT size 1\_s*' ..
+ '\d SETTYPE dict<number>\_s*' ..
'\d STORE $0\_s*' ..
'lockvar d.a\_s*' ..
'\d LOAD $0\_s*' ..
@@ -1626,6 +1626,7 @@ def Test_disassemble_list_index()
'\d PUSHNR 2\_s*' ..
'\d PUSHNR 3\_s*' ..
'\d NEWLIST size 3\_s*' ..
+ '\d SETTYPE list<number>\_s*' ..
'\d STORE $0\_s*' ..
'var res = l\[1]\_s*' ..
'\d LOAD $0\_s*' ..
@@ -1650,13 +1651,15 @@ def Test_disassemble_list_slice()
'\d PUSHNR 2\_s*' ..
'\d PUSHNR 3\_s*' ..
'\d NEWLIST size 3\_s*' ..
+ '\d SETTYPE list<number>\_s*' ..
'\d STORE $0\_s*' ..
'var res = l\[1 : 8]\_s*' ..
'\d LOAD $0\_s*' ..
'\d PUSHNR 1\_s*' ..
'\d PUSHNR 8\_s*' ..
- '\d LISTSLICE\_s*' ..
- '\d STORE $1\_s*',
+ '\d\+ LISTSLICE\_s*' ..
+ '\d\+ SETTYPE list<number>\_s*' ..
+ '\d\+ STORE $1\_s*',
instr)
assert_equal([2, 3], ListSlice())
enddef
@@ -1675,6 +1678,7 @@ def Test_disassemble_dict_member()
'\d PUSHS "item"\_s*' ..
'\d PUSHNR 1\_s*' ..
'\d NEWDICT size 1\_s*' ..
+ '\d SETTYPE dict<number>\_s*' ..
'\d STORE $0\_s*' ..
'var res = d.item\_s*' ..
'\d\+ LOAD $0\_s*' ..
@@ -2541,6 +2545,7 @@ def Test_disassemble_dict_stack()
'\d PUSHS "func"\_s*' ..
'\d PUSHFUNC "<80><fd>R\d\+_Legacy"\_s*' ..
'\d NEWDICT size 1\_s*' ..
+ '\d SETTYPE dict<func(...): any>\_s*' ..
'\d STORE $0\_s*' ..
'var v = d.func()\_s*' ..
diff --git a/src/version.c b/src/version.c
index 7bf2ddb9a..8edb112be 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4390,
+/**/
4389,
/**/
4388,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index a0efafc1e..0eb41e4c1 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2002,6 +2002,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
int instr_count = -1;
int save_lnum;
int skip_store = FALSE;
+ type_T *inferred_type = NULL;
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)
lhs.lhs_lvar->lv_type = &t_any;
else
+ {
lhs.lhs_lvar->lv_type = rhs_type;
+ inferred_type = rhs_type;
+ }
}
}
else if (*op == '=')
@@ -2146,7 +2150,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
cctx))
use_type = lhs.lhs_member_type;
if (need_type_where(rhs_type, use_type, -1, where,
- cctx, FALSE, is_const) == FAIL)
+ cctx, FALSE, is_const) == FAIL)
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
|| lhs.lhs_type->tt_type == VAR_LIST)
&& lhs.lhs_type->tt_member != NULL
+ && lhs.lhs_type->tt_member != &t_any
&& lhs.lhs_type->tt_member != &t_unknown)
// Set the type in the list or dict, so that it can be checked,
// also in legacy script.
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,
instr_count, is_decl) == FAIL)