]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1788: Vim9: can declare a void variable v9.1.1788
authorYegappan Lakshmanan <yegappan@yahoo.com>
Wed, 24 Sep 2025 17:51:17 +0000 (17:51 +0000)
committerChristian Brabandt <cb@256bit.org>
Wed, 24 Sep 2025 17:51:17 +0000 (17:51 +0000)
Problem:  Vim9: can declare a void variable (Ernie Rael)
Solution: Disallow such variable declaration (Yegappan Lakshmanan)

fixes: #13773
closes: #18382

Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
13 files changed:
src/errors.h
src/eval.c
src/po/vim.pot
src/testdir/test_vim9_assign.vim
src/testdir/test_vim9_class.vim
src/userfunc.c
src/version.c
src/vim9class.c
src/vim9cmds.c
src/vim9compile.c
src/vim9generics.c
src/vim9script.c
src/vim9type.c

index 91b1c944f3af2dc3f26f840342d159f85c407084..771f4976d4f364fa54645179db7a6ae4bb9f4edc 100644 (file)
@@ -3415,8 +3415,8 @@ EXTERN char e_constructor_default_value_must_be_vnone_str[]
        INIT(= N_("E1328: Constructor default value must be v:none: %s"));
 EXTERN char e_invalid_class_variable_declaration_str[]
        INIT(= N_("E1329: Invalid class variable declaration: %s"));
-EXTERN char e_invalid_type_for_object_variable_str[]
-       INIT(= N_("E1330: Invalid type for object variable: %s"));
+EXTERN char e_invalid_type_in_variable_declaration_str[]
+       INIT(= N_("E1330: Invalid type used in variable declaration: %s"));
 EXTERN char e_public_must_be_followed_by_var_static_final_or_const[]
        INIT(= N_("E1331: public must be followed by \"var\" or \"static\" or \"final\" or \"const\""));
 EXTERN char e_public_variable_name_cannot_start_with_underscore_str[]
index 503623491c14ed55067b1a2bcaec673b2f994522..4a55adac72b2515fae06d8489fb66bf24b07a279 100644 (file)
@@ -2223,7 +2223,8 @@ get_lval(
                lp->ll_type = parse_type(&tp,
                               &SCRIPT_ITEM(current_sctx.sc_sid)->sn_type_list,
                               NULL, NULL, !quiet);
-               if (lp->ll_type == NULL && !quiet)
+               if (!quiet && (lp->ll_type == NULL
+                           || !valid_declaration_type(lp->ll_type)))
                    return NULL;
                lp->ll_name_end = tp;
            }
index 20571200d1da47d07c0645e39edc1a45c38d1b99..fb369d7d196e1cf1d4e360e8ec2939d85e0ef3ff 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Vim\n"
 "Report-Msgid-Bugs-To: vim-dev@vim.org\n"
-"POT-Creation-Date: 2025-09-22 19:04+0000\n"
+"POT-Creation-Date: 2025-09-24 17:48+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -8228,7 +8228,7 @@ msgid "E1329: Invalid class variable declaration: %s"
 msgstr ""
 
 #, c-format
-msgid "E1330: Invalid type for object variable: %s"
+msgid "E1330: Invalid type used in variable declaration: %s"
 msgstr ""
 
 msgid ""
index 0872081902317045bd50ad9ab94d90f50a3e5756..6021148597e8c88c8fc2f4069eb29cee93bdabe4 100644 (file)
@@ -2339,6 +2339,97 @@ def Test_var_declaration_fails()
   endfor
 enddef
 
+" Test for using "void" as the type in a variable declaration
+def Test_var_declaration_void_type()
+  # Using void as the type of a local variable
+  var lines =<< trim END
+    var x: void
+  END
+  v9.CheckDefAndScriptFailure(lines, 'E1330: Invalid type used in variable declaration: void')
+
+  # Using void as the type of a function argument
+  lines =<< trim END
+    vim9script
+    def Foo(x: void)
+    enddef
+    defcompile
+  END
+  v9.CheckSourceFailure(lines, 'E1330: Invalid type used in variable declaration: void', 2)
+
+  # Using void as the type of a variable with a initializer
+  lines =<< trim END
+    var a: void = 10
+  END
+  v9.CheckDefAndScriptFailure(lines, 'E1330: Invalid type used in variable declaration: void')
+
+  # Using void as the list item type
+  lines =<< trim END
+    var l: list<void> = []
+  END
+  v9.CheckDefAndScriptFailure(lines, 'E1330: Invalid type used in variable declaration: void')
+
+  # Using void as the tuple item type
+  lines =<< trim END
+    var t: tuple<void> = ()
+  END
+  v9.CheckDefAndScriptFailure(lines, 'E1330: Invalid type used in variable declaration: void')
+
+  # Using void as the dict item type
+  lines =<< trim END
+    var l: dict<void> = {}
+  END
+  v9.CheckDefAndScriptFailure(lines, 'E1330: Invalid type used in variable declaration: void')
+
+  # Using void as the argument type in a lambda
+  lines =<< trim END
+    var Fn = (x: void) => x
+  END
+  v9.CheckDefAndScriptFailure(lines, 'E1330: Invalid type used in variable declaration: void')
+
+  # Using void as the type of an object member variable
+  lines =<< trim END
+    vim9script
+    class A
+      var x: void = 1
+    endclass
+    var a = A.new()
+  END
+  v9.CheckScriptFailure(lines, 'E1330: Invalid type used in variable declaration: void')
+
+  # Using void as the type of a loop index
+  lines =<< trim END
+    for [i: number, j: void] in ((1, 2), (3, 4))
+    endfor
+  END
+  v9.CheckDefFailure(lines, 'E1330: Invalid type used in variable declaration: void')
+
+  # Using void as the type of a generic parameter
+  lines =<< trim END
+    vim9script
+    def Fn<T, U>()
+    enddef
+    Fn<void, void>()
+  END
+  v9.CheckSourceFailure(lines, 'E1330: Invalid type used in variable declaration: void', 4)
+
+  # Using void as the type of a parameter in a function type
+  lines =<< trim END
+    vim9script
+    def Foo()
+    enddef
+    var Fn: func(void): void = Foo
+  END
+  v9.CheckSourceFailure(lines, 'E1330: Invalid type used in variable declaration: void', 4)
+
+  # Using void in a type alias
+  lines =<< trim END
+    vim9script
+    type MyType = void
+    var x: MyType
+  END
+  v9.CheckSourceFailure(lines, 'E1330: Invalid type used in variable declaration: void', 3)
+enddef
+
 def Test_var_declaration_inferred()
   # check that type is set on the list so that extend() fails
   var lines =<< trim END
index fc3889831723939f2dd7ae7b0cb39e9e48f9ae5b..467d0d1fcff5a5a8d0ef380bd0e3e4c987f2e2f5 100644 (file)
@@ -1258,7 +1258,7 @@ def Test_class_object_member_inits()
        var value: void
     endclass
   END
-  v9.CheckSourceFailure(lines, 'E1330: Invalid type for object variable: void', 3)
+  v9.CheckSourceFailure(lines, 'E1330: Invalid type used in variable declaration: void', 3)
 enddef
 
 " Test for instance variable access
index a4d01524ab493de0be6274a984d24ee9a7fb4c1a..1dead0430259f9702a6d9b4e01e01ebc4c578a49 100644 (file)
@@ -573,7 +573,7 @@ parse_argument_types(
                    else
                        type = parse_type(&p, &fp->uf_type_list, fp, cctx, TRUE);
                }
-               if (type == NULL)
+               if (type == NULL || !valid_declaration_type(type))
                    return FAIL;
                fp->uf_arg_types[i] = type;
                if (i < fp->uf_args.ga_len
index b43aa13283e3f5b3d8989e6a0e2d92f7e5b12f52..bad197898eec4a88084b5201f08b6846aa4e02a0 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1788,
 /**/
     1787,
 /**/
index 40b594af79f86306d9e49e55354cc20b312c327f..f6566e2ef1218f2cb187ad9567d140af011fa21e 100644 (file)
@@ -102,7 +102,7 @@ parse_member(
        }
        type_arg = skipwhite(colon + 1);
        type = parse_type(&type_arg, type_list, NULL, NULL, TRUE);
-       if (type == NULL)
+       if (type == NULL || !valid_declaration_type(type))
            return FAIL;
        *has_type = TRUE;
     }
index da57912ad710712f3c1cf1f8e63207ad371ca148..668c9a15524f6f9fb484180b45ab03b42145244e 100644 (file)
@@ -1132,7 +1132,7 @@ compile_for(char_u *arg_start, cctx_T *cctx)
                p = skipwhite(p + 1);
                lhs_type = parse_type(&p, cctx->ctx_type_list, cctx->ctx_ufunc,
                                                                cctx, TRUE);
-               if (lhs_type == NULL)
+               if (lhs_type == NULL || !valid_declaration_type(lhs_type))
                    goto failed;
            }
 
index 65e0ff194388373eb14037aa0ae02c86351edaf3..91c1c0c9ed2c5f783b5c0471b100726280f9313a 100644 (file)
@@ -2121,7 +2121,8 @@ compile_lhs_set_type(cctx_T *cctx, lhs_T *lhs, char_u *var_end, int is_decl)
 
        p = skipwhite(var_end + 1);
        lhs->lhs_type = parse_type(&p, cctx->ctx_type_list, cctx->ctx_ufunc, cctx, TRUE);
-       if (lhs->lhs_type == NULL)
+       if (lhs->lhs_type == NULL
+               || !valid_declaration_type(lhs->lhs_type))
            return FAIL;
 
        lhs->lhs_has_type = TRUE;
index 54400903e42dfcdb75d67d2d473ba4e2fa320c14..7afedad391af8baa3914ce9604f2ede364b313c2 100644 (file)
@@ -306,7 +306,7 @@ parse_generic_func_type_args(
 
        // parse the type
        type_arg = parse_type(&p, &gfatab->gfat_arg_types, NULL, cctx, TRUE);
-       if (type_arg == NULL)
+       if (type_arg == NULL || !valid_declaration_type(type_arg))
            return NULL;
 
        char    *ret_free = NULL;
index e526637e2785200caa4e9c2bb5be7185a1f0b98b..435ca2de86d5e5709993f324d540fd2ffdb3e827 100644 (file)
@@ -841,7 +841,9 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg)
     // parse type, check for reserved name
     p = skipwhite(p + 1);
     type = parse_type(&p, &si->sn_type_list, NULL, NULL, TRUE);
-    if (type == NULL || check_reserved_name(name, FALSE) == FAIL)
+    if (type == NULL
+           || check_reserved_name(name, FALSE) == FAIL
+           || !valid_declaration_type(type))
     {
        vim_free(name);
        return p;
index 28997ab37b65be4257483879cf1bddc4c6557a8a..e36f956690937a51a819bf86084c9f0d1f6c1bb9 100644 (file)
@@ -997,7 +997,7 @@ valid_declaration_type(type_T *type)
     {
        char *tofree = NULL;
        char *name = type_name(type, &tofree);
-       semsg(_(e_invalid_type_for_object_variable_str), name);
+       semsg(_(e_invalid_type_in_variable_declaration_str), name);
        vim_free(tofree);
        return FALSE;
     }
@@ -1629,7 +1629,7 @@ parse_type_member(
     *arg = skipwhite(*arg + 1);
 
     member_type = parse_type(arg, type_gap, ufunc, cctx, give_error);
-    if (member_type == NULL)
+    if (member_type == NULL || !valid_declaration_type(member_type))
        return NULL;
 
     *arg = skipwhite(*arg);
@@ -1699,7 +1699,7 @@ parse_type_func(
            }
 
            type = parse_type(&p, type_gap, ufunc, cctx, give_error);
-           if (type == NULL)
+           if (type == NULL || !valid_declaration_type(type))
                return NULL;
            if ((flags & TTFLAG_VARARGS) != 0 && type->tt_type != VAR_LIST)
            {
@@ -1831,7 +1831,7 @@ parse_type_tuple(
        }
 
        type = parse_type(&p, type_gap, ufunc, cctx, give_error);
-       if (type == NULL)
+       if (type == NULL || !valid_declaration_type(type))
            goto on_err;
 
        if ((flags & TTFLAG_VARARGS) != 0 && type->tt_type != VAR_LIST)