From 4c68375057c25e99656bc996d3fa5c6b0b6a7e6a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 5 Apr 2020 21:38:23 +0200 Subject: patch 8.2.0517: Vim9: cannot separate "func" and "func(): void" Problem: Vim9: cannot separate "func" and "func(): void". Solution: Use VAR_ANY for "any" and VAR_UNKNOWN for "no type". --- src/eval.c | 14 +++++++++- src/evalfunc.c | 3 +++ src/evalvars.c | 1 + src/globals.h | 8 +++--- src/if_py_both.h | 1 + src/json.c | 1 + src/structs.h | 5 ++-- src/testdir/test_vim9_func.vim | 21 +++++++++++++++ src/testing.c | 1 + src/version.c | 2 ++ src/vim9compile.c | 58 +++++++++++++++++++++++++----------------- src/vim9execute.c | 1 + src/viminfo.c | 1 + 13 files changed, 88 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/eval.c b/src/eval.c index 6d666e6121..3b789dadc6 100644 --- a/src/eval.c +++ b/src/eval.c @@ -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; diff --git a/src/evalfunc.c b/src/evalfunc.c index 5a5daaa5af..3b8b319fde 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -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; diff --git a/src/evalvars.c b/src/evalvars.c index d434d58788..6b9c270a37 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -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: diff --git a/src/globals.h b/src/globals.h index 1a6a0d8d30..6f594e9132 100644 --- a/src/globals.h +++ b/src/globals.h @@ -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); diff --git a/src/if_py_both.h b/src/if_py_both.h index 0d70de2309..77ec4a9931 100644 --- a/src/if_py_both.h +++ b/src/if_py_both.h @@ -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: diff --git a/src/json.c b/src/json.c index f4a03e61ad..c1c6e85638 100644 --- a/src/json.c +++ b/src/json.c @@ -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; diff --git a/src/structs.h b/src/structs.h index 4a5128171b..46e27012c8 100644 --- a/src/structs.h +++ b/src/structs.h @@ -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 diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 6f61254f86..c122168628 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -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() diff --git a/src/testing.c b/src/testing.c index 81e17622dd..35c268349b 100644 --- a/src/testing.c +++ b/src/testing.c @@ -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: diff --git a/src/version.c b/src/version.c index fb736142d1..4c07cd2e78 100644 --- a/src/version.c +++ b/src/version.c @@ -738,6 +738,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 517, /**/ 516, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 526f25b80d..98936dd660 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -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; diff --git a/src/vim9execute.c b/src/vim9execute.c index 237b024eff..b7ec9798c3 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -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; } diff --git a/src/viminfo.c b/src/viminfo.c index c1339f08c6..b014d7f215 100644 --- a/src/viminfo.c +++ b/src/viminfo.c @@ -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: -- cgit v1.2.3