summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-04-15 21:48:32 +0200
committerBram Moolenaar <Bram@vim.org>2021-04-15 21:48:32 +0200
commitfe090eb58fad1aaf83267d0b4ace9f024a5ba2bc (patch)
treec9446376111c5970b61b74ff6b1ca1ed58848248 /src
parent6bc00699c5049c40761d212bef1b490e2af7944c (diff)
patch 8.2.2770: Vim9: type of loop variable is not usedv8.2.2770
Problem: Vim9: type of loop variable is not used. Solution: Parse and check the variable type. (closes #8107)
Diffstat (limited to 'src')
-rw-r--r--src/testdir/test_vim9_script.vim12
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c26
3 files changed, 35 insertions, 5 deletions
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 03da2fd86f..d9ae4ff670 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -2343,6 +2343,12 @@ def Test_for_loop()
endfor
assert_equal(6, total)
+ var chars = ''
+ for s: string in 'foobar'
+ chars ..= s
+ endfor
+ assert_equal('foobar', chars)
+
# unpack with type
var res = ''
for [n: number, s: string] in [[1, 'a'], [2, 'b']]
@@ -2408,6 +2414,12 @@ def Test_for_loop_fails()
endfor
END
CheckDefAndScriptFailure2(lines, 'E1018:', 'E46:', 3)
+
+ lines =<< trim END
+ for nr: number in ['foo']
+ endfor
+ END
+ CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected number but got string', 1)
enddef
def Test_for_loop_script_var()
diff --git a/src/version.c b/src/version.c
index 8c558b20e9..8cbe3d36d7 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 */
/**/
+ 2770,
+/**/
2769,
/**/
2768,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 78c387f429..4ae3b41aed 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -7514,12 +7514,16 @@ compile_for(char_u *arg_start, cctx_T *cctx)
return NULL;
}
- if (vartype->tt_type == VAR_LIST && vartype->tt_member->tt_type != VAR_ANY)
+ if (vartype->tt_type == VAR_STRING)
+ item_type = &t_string;
+ else if (vartype->tt_type == VAR_LIST
+ && vartype->tt_member->tt_type != VAR_ANY)
{
if (var_count == 1)
item_type = vartype->tt_member;
else if (vartype->tt_member->tt_type == VAR_LIST
&& vartype->tt_member->tt_member->tt_type != VAR_ANY)
+ // TODO: should get the type from
item_type = vartype->tt_member->tt_member;
}
@@ -7557,12 +7561,19 @@ compile_for(char_u *arg_start, cctx_T *cctx)
int opt_flags = 0;
int vimvaridx = -1;
type_T *type = &t_any;
+ type_T *lhs_type = &t_any;
+ where_T where;
p = skip_var_one(arg, FALSE);
varlen = p - arg;
name = vim_strnsave(arg, varlen);
if (name == NULL)
goto failed;
+ if (*p == ':')
+ {
+ p = skipwhite(p + 1);
+ lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
+ }
// TODO: script var not supported?
if (get_var_dest(name, &dest, CMD_for, &opt_flags,
@@ -7589,8 +7600,15 @@ compile_for(char_u *arg_start, cctx_T *cctx)
}
// Reserve a variable to store "var".
- // TODO: check for type
- var_lvar = reserve_local(cctx, arg, varlen, TRUE, &t_any);
+ where.wt_index = var_count > 1 ? idx + 1 : 0;
+ where.wt_variable = TRUE;
+ if (lhs_type == &t_any)
+ lhs_type = item_type;
+ else if (item_type != &t_unknown
+ && !(var_count > 1 && item_type == &t_any)
+ && check_type(lhs_type, item_type, TRUE, where) == FAIL)
+ goto failed;
+ var_lvar = reserve_local(cctx, arg, varlen, TRUE, lhs_type);
if (var_lvar == NULL)
// out of memory or used as an argument
goto failed;
@@ -7602,8 +7620,6 @@ compile_for(char_u *arg_start, cctx_T *cctx)
generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
}
- if (*p == ':')
- p = skip_type(skipwhite(p + 1), FALSE);
if (*p == ',' || *p == ';')
++p;
arg = skipwhite(p);