]> granicus.if.org Git - vim/commitdiff
patch 8.2.0517: Vim9: cannot separate "func" and "func(): void" v8.2.0517
authorBram Moolenaar <Bram@vim.org>
Sun, 5 Apr 2020 19:38:23 +0000 (21:38 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 5 Apr 2020 19:38:23 +0000 (21:38 +0200)
Problem:    Vim9: cannot separate "func" and "func(): void".
Solution:   Use VAR_ANY for "any" and VAR_UNKNOWN for "no type".

13 files changed:
src/eval.c
src/evalfunc.c
src/evalvars.c
src/globals.h
src/if_py_both.h
src/json.c
src/structs.h
src/testdir/test_vim9_func.vim
src/testing.c
src/version.c
src/vim9compile.c
src/vim9execute.c
src/viminfo.c

index 6d666e61212f22890dac69f60891fc7a5a81cde7..3b789dadc674ab6813ac5d349c6ea262311df3e0 100644 (file)
@@ -1272,6 +1272,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
        switch (tv1->v_type)
        {
            case VAR_UNKNOWN:
+           case VAR_ANY:
            case VAR_VOID:
            case VAR_DICT:
            case VAR_FUNC:
@@ -2967,6 +2968,7 @@ eval_index(
                emsg(_("E909: Cannot index a special variable"));
            return FAIL;
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
            if (evaluate)
                return FAIL;
@@ -3073,6 +3075,7 @@ eval_index(
        switch (rettv->v_type)
        {
            case VAR_UNKNOWN:
+           case VAR_ANY:
            case VAR_VOID:
            case VAR_FUNC:
            case VAR_PARTIAL:
@@ -3668,7 +3671,7 @@ get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate)
 }
 
 /*
- * Return the function name of the partial.
+ * Return the function name of partial "pt".
  */
     char_u *
 partial_name(partial_T *pt)
@@ -3856,6 +3859,7 @@ tv_equal(
            return tv1->vval.v_string == tv2->vval.v_string;
 
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
            break;
     }
@@ -4570,6 +4574,7 @@ echo_string_core(
 
        case VAR_NUMBER:
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
            *tofree = NULL;
            r = tv_get_string_buf(tv, numbuf);
@@ -5422,6 +5427,7 @@ free_tv(typval_T *varp)
 #endif
            case VAR_NUMBER:
            case VAR_FLOAT:
+           case VAR_ANY:
            case VAR_UNKNOWN:
            case VAR_VOID:
            case VAR_BOOL:
@@ -5486,6 +5492,7 @@ clear_tv(typval_T *varp)
                varp->vval.v_channel = NULL;
 #endif
            case VAR_UNKNOWN:
+           case VAR_ANY:
            case VAR_VOID:
                break;
        }
@@ -5565,6 +5572,7 @@ tv_get_number_chk(typval_T *varp, int *denote)
            emsg(_("E974: Using a Blob as a Number"));
            break;
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
            internal_error_no_abort("tv_get_number(UNKNOWN)");
            break;
@@ -5619,6 +5627,7 @@ tv_get_float(typval_T *varp)
            emsg(_("E975: Using a Blob as a Float"));
            break;
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
            internal_error_no_abort("tv_get_float(UNKNOWN)");
            break;
@@ -5742,6 +5751,7 @@ tv_get_string_buf_chk(typval_T *varp, char_u *buf)
 #endif
            break;
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
            emsg(_(e_inval_string));
            break;
@@ -5891,6 +5901,7 @@ copy_tv(typval_T *from, typval_T *to)
            }
            break;
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
            internal_error_no_abort("copy_tv(UNKNOWN)");
            break;
@@ -5970,6 +5981,7 @@ item_copy(
                ret = FAIL;
            break;
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
            internal_error_no_abort("item_copy(UNKNOWN)");
            ret = FAIL;
index 5a5daaa5af0cb731307257b29ccfafcdfa6eb829..3b8b319fde0d55b11442f62c1851f5f7e1b44fdf 100644 (file)
@@ -2042,6 +2042,7 @@ f_empty(typval_T *argvars, typval_T *rettv)
            break;
 #endif
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
            internal_error_no_abort("f_empty(UNKNOWN)");
            n = TRUE;
@@ -5217,6 +5218,7 @@ f_len(typval_T *argvars, typval_T *rettv)
            rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
            break;
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
        case VAR_BOOL:
        case VAR_SPECIAL:
@@ -8805,6 +8807,7 @@ f_type(typval_T *argvars, typval_T *rettv)
        case VAR_CHANNEL: n = VAR_TYPE_CHANNEL; break;
        case VAR_BLOB:    n = VAR_TYPE_BLOB; break;
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
             internal_error_no_abort("f_type(UNKNOWN)");
             n = -1;
index d434d58788e853ddd8738ca5edba7b491c6ede18..6b9c270a377199f0a996a25af310322f651d3289 100644 (file)
@@ -1668,6 +1668,7 @@ item_lock(typval_T *tv, int deep, int lock)
     switch (tv->v_type)
     {
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
        case VAR_NUMBER:
        case VAR_BOOL:
index 1a6a0d8d30cecc39d158ca8fd41819d6a328b14e..6f594e9132ba9ec9a167b26158a31a7af3df0a90 100644 (file)
@@ -379,7 +379,8 @@ EXTERN sctx_T       current_sctx INIT4(0, 0, 0, 0);
 
 
 // Commonly used types.
-EXTERN type_T t_any INIT6(VAR_UNKNOWN, 0, 0, 0, NULL, NULL);
+EXTERN type_T t_unknown INIT6(VAR_UNKNOWN, 0, 0, 0, NULL, NULL);
+EXTERN type_T t_any INIT6(VAR_ANY, 0, 0, 0, NULL, NULL);
 EXTERN type_T t_void INIT6(VAR_VOID, 0, 0, 0, NULL, NULL);
 EXTERN type_T t_bool INIT6(VAR_BOOL, 0, 0, 0, NULL, NULL);
 EXTERN type_T t_special INIT6(VAR_SPECIAL, 0, 0, 0, NULL, NULL);
@@ -390,6 +391,7 @@ EXTERN type_T t_blob INIT6(VAR_BLOB, 0, 0, 0, NULL, NULL);
 EXTERN type_T t_job INIT6(VAR_JOB, 0, 0, 0, NULL, NULL);
 EXTERN type_T t_channel INIT6(VAR_CHANNEL, 0, 0, 0, NULL, NULL);
 
+EXTERN type_T t_func_unknown INIT6(VAR_FUNC, -1, 0, 0, &t_unknown, NULL);
 EXTERN type_T t_func_void INIT6(VAR_FUNC, -1, 0, 0, &t_void, NULL);
 EXTERN type_T t_func_any INIT6(VAR_FUNC, -1, 0, 0, &t_any, NULL);
 EXTERN type_T t_func_number INIT6(VAR_FUNC, -1, 0, 0, &t_number, NULL);
@@ -401,8 +403,8 @@ EXTERN type_T t_func_0_string INIT6(VAR_FUNC, 0, 0, 0, &t_string, NULL);
 
 EXTERN type_T t_list_any INIT6(VAR_LIST, 0, 0, 0, &t_any, NULL);
 EXTERN type_T t_dict_any INIT6(VAR_DICT, 0, 0, 0, &t_any, NULL);
-EXTERN type_T t_list_empty INIT6(VAR_LIST, 0, 0, 0, &t_void, NULL);
-EXTERN type_T t_dict_empty INIT6(VAR_DICT, 0, 0, 0, &t_void, NULL);
+EXTERN type_T t_list_empty INIT6(VAR_LIST, 0, 0, 0, &t_unknown, NULL);
+EXTERN type_T t_dict_empty INIT6(VAR_DICT, 0, 0, 0, &t_unknown, NULL);
 
 EXTERN type_T t_list_bool INIT6(VAR_LIST, 0, 0, 0, &t_bool, NULL);
 EXTERN type_T t_list_number INIT6(VAR_LIST, 0, 0, 0, &t_number, NULL);
index 0d70de2309353c1396e7b4c79d391d5a7e88a26a..77ec4a99317aa7a6c4f4cc40f9dda410cd4e90e9 100644 (file)
@@ -6390,6 +6390,7 @@ ConvertToPyObject(typval_T *tv)
                (char*) tv->vval.v_blob->bv_ga.ga_data,
                (Py_ssize_t) tv->vval.v_blob->bv_ga.ga_len);
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
        case VAR_CHANNEL:
        case VAR_JOB:
index f4a03e61ad6771cb7690c1ac5f2adfb5426cf007..c1c6e85638846eedcb54fe2d1428b1c1836120e8 100644 (file)
@@ -351,6 +351,7 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
            break;
 #endif
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
            internal_error_no_abort("json_encode_item()");
            return FAIL;
index 4a5128171b26eb30b515745f9c9ad75ef92a147e..46e27012c89c5c3ad2b426edd541709025226dd5 100644 (file)
@@ -1321,8 +1321,9 @@ typedef struct cctx_S cctx_T;
 
 typedef enum
 {
-    VAR_UNKNOWN = 0,   // not set, also used for "any" type
-    VAR_VOID,          // no value
+    VAR_UNKNOWN = 0,   // not set, any type or "void" allowed
+    VAR_ANY,           // used for "any" type
+    VAR_VOID,          // no value (function not returning anything)
     VAR_BOOL,          // "v_number" is used: VVAL_TRUE or VVAL_FALSE
     VAR_SPECIAL,       // "v_number" is used: VVAL_NULL or VVAL_NONE
     VAR_NUMBER,                // "v_number" is used
index 6f61254f8646de7c7553cacc3733270c34208e08..c1221686283f4d9ee7057969b1c82da681654e21 100644 (file)
@@ -386,6 +386,27 @@ def Test_func_type()
   Ref1 = FuncNoArgNoRet
   Ref1()
   assert_equal(11, funcResult)
+
+  let Ref2: func
+  funcResult = 0
+  Ref2 = FuncNoArgNoRet
+  Ref2()
+  assert_equal(11, funcResult)
+
+  funcResult = 0
+  Ref2 = FuncOneArgNoRet
+  Ref2(12)
+  assert_equal(12, funcResult)
+
+  funcResult = 0
+  Ref2 = FuncNoArgRetNumber
+  assert_equal(1234, Ref2())
+  assert_equal(22, funcResult)
+
+  funcResult = 0
+  Ref2 = FuncOneArgRetNumber
+  assert_equal(13, Ref2(13))
+  assert_equal(13, funcResult)
 enddef
 
 def Test_func_type_fails()
index 81e17622dd6e2187e640facd8112d40e7f70c301..35c268349b81c4e1a4a7a054e252121e38d98d49 100644 (file)
@@ -764,6 +764,7 @@ f_test_refcount(typval_T *argvars, typval_T *rettv)
     switch (argvars[0].v_type)
     {
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
        case VAR_NUMBER:
        case VAR_BOOL:
index fb736142d175678e0efc43f4fe1246301c020283..4c07cd2e78cfc1e8aa99463e0f392710ee2695f8 100644 (file)
@@ -738,6 +738,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    517,
 /**/
     516,
 /**/
index 526f25b80dfb5ef0d6bcaa94b22805b87b186d71..98936dd66068954ac7b1c8d65e5c8b23fa002e8f 100644 (file)
@@ -249,9 +249,10 @@ get_list_type(type_T *member_type, garray_T *type_gap)
     type_T *type;
 
     // recognize commonly used types
-    if (member_type->tt_type == VAR_UNKNOWN)
+    if (member_type->tt_type == VAR_ANY)
        return &t_list_any;
-    if (member_type->tt_type == VAR_VOID)
+    if (member_type->tt_type == VAR_VOID
+           || member_type->tt_type == VAR_UNKNOWN)
        return &t_list_empty;
     if (member_type->tt_type == VAR_BOOL)
        return &t_list_bool;
@@ -277,9 +278,10 @@ get_dict_type(type_T *member_type, garray_T *type_gap)
     type_T *type;
 
     // recognize commonly used types
-    if (member_type->tt_type == VAR_UNKNOWN)
+    if (member_type->tt_type == VAR_ANY)
        return &t_dict_any;
-    if (member_type->tt_type == VAR_VOID)
+    if (member_type->tt_type == VAR_VOID
+           || member_type->tt_type == VAR_UNKNOWN)
        return &t_dict_empty;
     if (member_type->tt_type == VAR_BOOL)
        return &t_dict_bool;
@@ -482,9 +484,9 @@ may_generate_2STRING(int offset, cctx_T *cctx)
     static int
 check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
 {
-    if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_UNKNOWN)
+    if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
            && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
-                                                    || type2 == VAR_UNKNOWN)))
+                                                        || type2 == VAR_ANY)))
     {
        if (*op == '+')
            emsg(_("E1035: wrong argument type for +"));
@@ -515,7 +517,7 @@ generate_two_op(cctx_T *cctx, char_u *op)
     // checking.
     type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
     type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
-    vartype = VAR_UNKNOWN;
+    vartype = VAR_ANY;
     if (type1->tt_type == type2->tt_type
            && (type1->tt_type == VAR_NUMBER
                || type1->tt_type == VAR_LIST
@@ -528,8 +530,8 @@ generate_two_op(cctx_T *cctx, char_u *op)
     switch (*op)
     {
        case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
-                         && type1->tt_type != VAR_UNKNOWN
-                         && type2->tt_type != VAR_UNKNOWN
+                         && type1->tt_type != VAR_ANY
+                         && type2->tt_type != VAR_ANY
                          && check_number_or_float(
                                   type1->tt_type, type2->tt_type, op) == FAIL)
                      return FAIL;
@@ -563,9 +565,9 @@ generate_two_op(cctx_T *cctx, char_u *op)
                                 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
                  break;
 
-       case '%': if ((type1->tt_type != VAR_UNKNOWN
+       case '%': if ((type1->tt_type != VAR_ANY
                                               && type1->tt_type != VAR_NUMBER)
-                         || (type2->tt_type != VAR_UNKNOWN
+                         || (type2->tt_type != VAR_ANY
                                              && type2->tt_type != VAR_NUMBER))
                  {
                      emsg(_("E1035: % requires number arguments"));
@@ -579,7 +581,7 @@ generate_two_op(cctx_T *cctx, char_u *op)
     }
 
     // correct type of result
-    if (vartype == VAR_UNKNOWN)
+    if (vartype == VAR_ANY)
     {
        type_T *type = &t_any;
 
@@ -614,6 +616,11 @@ generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
     // checking.
     type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
     type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
+    if (type1 == VAR_UNKNOWN)
+       type1 = VAR_ANY;
+    if (type2 == VAR_UNKNOWN)
+       type2 = VAR_ANY;
+
     if (type1 == type2)
     {
        switch (type1)
@@ -631,7 +638,7 @@ generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
            default: isntype = ISN_COMPAREANY; break;
        }
     }
-    else if (type1 == VAR_UNKNOWN || type2 == VAR_UNKNOWN
+    else if (type1 == VAR_ANY || type2 == VAR_ANY
            || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
              && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
        isntype = ISN_COMPAREANY;
@@ -1723,8 +1730,9 @@ equal_type(type_T *type1, type_T *type2)
        return FALSE;
     switch (type1->tt_type)
     {
-       case VAR_VOID:
        case VAR_UNKNOWN:
+       case VAR_ANY:
+       case VAR_VOID:
        case VAR_SPECIAL:
        case VAR_BOOL:
        case VAR_NUMBER:
@@ -1785,6 +1793,7 @@ vartype_name(vartype_T type)
     switch (type)
     {
        case VAR_UNKNOWN: break;
+       case VAR_ANY: return "any";
        case VAR_VOID: return "void";
        case VAR_SPECIAL: return "special";
        case VAR_BOOL: return "bool";
@@ -1799,7 +1808,7 @@ vartype_name(vartype_T type)
        case VAR_FUNC: return "func";
        case VAR_PARTIAL: return "partial";
     }
-    return "any";
+    return "unknown";
 }
 
 /*
@@ -2396,7 +2405,7 @@ check_type(type_T *expected, type_T *actual, int give_msg)
 {
     int ret = OK;
 
-    if (expected->tt_type != VAR_UNKNOWN)
+    if (expected->tt_type != VAR_UNKNOWN && expected->tt_type != VAR_ANY)
     {
        if (expected->tt_type != actual->tt_type)
        {
@@ -2406,13 +2415,14 @@ check_type(type_T *expected, type_T *actual, int give_msg)
        }
        if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
        {
-           // void is used for an empty list or dict
-           if (actual->tt_member != &t_void)
+           // "unknown" is used for an empty list or dict
+           if (actual->tt_member != &t_unknown)
                ret = check_type(expected->tt_member, actual->tt_member, FALSE);
        }
        else if (expected->tt_type == VAR_FUNC)
        {
-           if (expected->tt_member != &t_any)
+           if (expected->tt_member != &t_any
+                                         && expected->tt_member != &t_unknown)
                ret = check_type(expected->tt_member, actual->tt_member, FALSE);
            if (ret == OK && expected->tt_argcount != -1
                    && (actual->tt_argcount < expected->tt_min_argcount
@@ -2436,7 +2446,7 @@ need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
 {
     if (check_type(expected, actual, FALSE))
        return OK;
-    if (actual->tt_type != VAR_UNKNOWN)
+    if (actual->tt_type != VAR_ANY && actual->tt_type != VAR_UNKNOWN)
     {
        type_mismatch(expected, actual);
        return FAIL;
@@ -3642,7 +3652,8 @@ compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
     {
        // "set_return_type" cannot be TRUE, only used for a lambda which
        // always has an argument.
-       if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID)
+       if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
+               && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
        {
            emsg(_("E1003: Missing return value"));
            return NULL;
@@ -3936,7 +3947,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
     }
 
     if (oplen == 3 && !heredoc && dest != dest_global
-           && type->tt_type != VAR_STRING && type->tt_type != VAR_UNKNOWN)
+                   && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
     {
        emsg(_("E1019: Can only concatenate to string"));
        goto theend;
@@ -4115,6 +4126,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
                break;
            case VAR_NUMBER:
            case VAR_UNKNOWN:
+           case VAR_ANY:
            case VAR_VOID:
            case VAR_SPECIAL:  // cannot happen
                generate_PUSHNR(cctx, 0);
@@ -4903,7 +4915,7 @@ compile_for(char_u *arg, cctx_T *cctx)
        drop_scope(cctx);
        return NULL;
     }
-    if (vartype->tt_member->tt_type != VAR_UNKNOWN)
+    if (vartype->tt_member->tt_type != VAR_ANY)
     {
        lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
 
index 237b024eff298857c672478b6f5387492bf7f2bf..b7ec9798c3c049a07b364ded8e42cdbbb804a82d 100644 (file)
@@ -2239,6 +2239,7 @@ tv2bool(typval_T *tv)
        case VAR_BLOB:
            return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0;
        case VAR_UNKNOWN:
+       case VAR_ANY:
        case VAR_VOID:
            break;
     }
index c1339f08c691b22f9f4f3acff4a9587516974a5c..b014d7f21562002897d288f650ebdfe731e48f03 100644 (file)
@@ -1344,6 +1344,7 @@ write_viminfo_varlist(FILE *fp)
                    case VAR_SPECIAL: s = "XPL"; break;
 
                    case VAR_UNKNOWN:
+                   case VAR_ANY:
                    case VAR_VOID:
                    case VAR_FUNC:
                    case VAR_PARTIAL: