]> granicus.if.org Git - vim/commitdiff
patch 8.2.2770: Vim9: type of loop variable is not used v8.2.2770
authorBram Moolenaar <Bram@vim.org>
Thu, 15 Apr 2021 19:48:32 +0000 (21:48 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 15 Apr 2021 19:48:32 +0000 (21:48 +0200)
Problem:    Vim9: type of loop variable is not used.
Solution:   Parse and check the variable type. (closes #8107)

src/testdir/test_vim9_script.vim
src/version.c
src/vim9compile.c

index 03da2fd86f925af8da41f040359a3f0639e238f3..d9ae4ff670856241026527ed9ba6a257734f627c 100644 (file)
@@ -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()
index 8c558b20e9e87be456675dbb7cfaf784e0817d2d..8cbe3d36d7b2b90c9f7e87392846550b480fcd56 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2770,
 /**/
     2769,
 /**/
index 78c387f4297913f0f9360fecef149fb9280ab45d..4ae3b41aed1981a12cc63e802e771d0ff656b282 100644 (file)
@@ -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);