summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-02-02 16:20:26 +0000
committerBram Moolenaar <Bram@vim.org>2022-02-02 16:20:26 +0000
commita1c519518050383e7d319514a3ff6c42a9154c48 (patch)
treeb2263814d4ed499842a1a1f381a7d1930720e26b
parentab8f7c50cf7d5c0c72dfa5067e5b1f57585db4d8 (diff)
patch 8.2.4285: Vim9: type of item in for loop not checked properlyv8.2.4285
Problem: Vim9: type of item in for loop not checked properly. Solution: Adjust the type checking. (closes #9683)
-rw-r--r--src/proto/vim9compile.pro1
-rw-r--r--src/testdir/test_vim9_script.vim18
-rw-r--r--src/version.c2
-rw-r--r--src/vim9cmds.c9
-rw-r--r--src/vim9compile.c2
5 files changed, 23 insertions, 9 deletions
diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro
index cb95fdfb6b..b7f7539215 100644
--- a/src/proto/vim9compile.pro
+++ b/src/proto/vim9compile.pro
@@ -4,6 +4,7 @@ int arg_exists(char_u *name, size_t len, int *idxp, type_T **type, int *gen_load
int script_is_vim9(void);
int script_var_exists(char_u *name, size_t len, cctx_T *cctx);
int check_defined(char_u *p, size_t len, cctx_T *cctx, int is_arg);
+int need_type_where(type_T *actual, type_T *expected, int offset, where_T where, cctx_T *cctx, int silent, int actual_is_const);
int need_type(type_T *actual, type_T *expected, int offset, int arg_idx, cctx_T *cctx, int silent, int actual_is_const);
lvar_T *reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type);
int get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx);
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index a3f28f1e72..767abd4855 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -2011,7 +2011,7 @@ def Test_for_loop_fails()
echo k v
endfor
END
- v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected job but got string', 2)
+ v9.CheckDefExecAndScriptFailure(lines, ['E1013: Argument 1: type mismatch, expected job but got string', 'E1012: Type mismatch; expected job but got string'], 2)
lines =<< trim END
var i = 0
@@ -2036,6 +2036,22 @@ def Test_for_loop_fails()
endfor
END
v9.CheckDefExecAndScriptFailure(lines, ['E461:', 'E1017:'])
+
+ lines =<< trim END
+ var l: list<dict<any>> = [{a: 1, b: 'x'}]
+ for item: dict<number> in l
+ echo item
+ endfor
+ END
+ v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected dict<number> but got dict<any>')
+
+ lines =<< trim END
+ var l: list<dict<any>> = [{n: 1}]
+ for item: dict<number> in l
+ item->extend({s: ''})
+ endfor
+ END
+ v9.CheckDefExecAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string>')
enddef
def Test_for_loop_script_var()
diff --git a/src/version.c b/src/version.c
index 7417143c67..2c623671c7 100644
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4285,
+/**/
4284,
/**/
4283,
diff --git a/src/vim9cmds.c b/src/vim9cmds.c
index 716a404111..90b61dbb34 100644
--- a/src/vim9cmds.c
+++ b/src/vim9cmds.c
@@ -990,11 +990,8 @@ compile_for(char_u *arg_start, cctx_T *cctx)
if (lhs_type == &t_any)
lhs_type = item_type;
else if (item_type != &t_unknown
- && (item_type == &t_any
- ? need_type(item_type, lhs_type,
- -1, 0, cctx, FALSE, FALSE)
- : check_type(lhs_type, item_type, TRUE, where))
- == FAIL)
+ && need_type_where(item_type, lhs_type, -1,
+ where, cctx, FALSE, FALSE) == FAIL)
goto failed;
var_lvar = reserve_local(cctx, arg, varlen, TRUE, lhs_type);
if (var_lvar == NULL)
@@ -1003,8 +1000,6 @@ compile_for(char_u *arg_start, cctx_T *cctx)
if (semicolon && idx == var_count - 1)
var_lvar->lv_type = vartype;
- else
- var_lvar->lv_type = item_type;
generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
}
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 9ad1e7ddc9..9dbd1198dd 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -386,7 +386,7 @@ use_typecheck(type_T *actual, type_T *expected)
* If "actual_is_const" is TRUE then the type won't change at runtime, do not
* generate a TYPECHECK.
*/
- static int
+ int
need_type_where(
type_T *actual,
type_T *expected,