Patch 8.2.3866
Problem: Vim9: type checking global variables is inconsistent.
Solution: Use the "unknown" type in more places.
Files: src/globals.h, src/vim9expr.c, src/vim9instr.c, src/vim9cmds.c,
src/evalfunc.c, src/testdir/test_vim9_func.vim
*** ../vim-8.2.3865/src/globals.h 2021-12-17 20:15:30.448830724 +0000
--- src/globals.h 2021-12-21 10:24:45.896882818 +0000
***************
*** 404,412 ****
--- 404,419 ----
// Commonly used types.
+ // "unknown" is used for when the type is really unknown, e.g. global
+ // variables. Also for when a function may or may not return something.
EXTERN type_T t_unknown INIT6(VAR_UNKNOWN, 0, 0, TTFLAG_STATIC, NULL, NULL);
+
+ // "any" is used for when the type is mixed. Excludes "void".
EXTERN type_T t_any INIT6(VAR_ANY, 0, 0, TTFLAG_STATIC, NULL, NULL);
+
+ // "void" is used for a function not returning anything.
EXTERN type_T t_void INIT6(VAR_VOID, 0, 0, TTFLAG_STATIC, NULL, NULL);
+
EXTERN type_T t_bool INIT6(VAR_BOOL, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_special INIT6(VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_number INIT6(VAR_NUMBER, 0, 0, TTFLAG_STATIC, NULL, NULL);
*** ../vim-8.2.3865/src/vim9expr.c 2021-12-20 15:03:23.247346527 +0000
--- src/vim9expr.c 2021-12-21 12:23:36.524687742 +0000
***************
*** 90,96 ****
vartype = (*typep)->tt_type;
idxtype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
// If the index is a string, the variable must be a Dict.
! if (*typep == &t_any && idxtype == &t_string)
vartype = VAR_DICT;
if (vartype == VAR_STRING || vartype == VAR_LIST || vartype == VAR_BLOB)
{
--- 90,96 ----
vartype = (*typep)->tt_type;
idxtype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
// If the index is a string, the variable must be a Dict.
! if ((*typep == &t_any || *typep == &t_unknown) && idxtype == &t_string)
vartype = VAR_DICT;
if (vartype == VAR_STRING || vartype == VAR_LIST || vartype == VAR_BLOB)
{
***************
*** 156,162 ****
return FAIL;
}
}
! else if (vartype == VAR_LIST || *typep == &t_any)
{
if (is_slice)
{
--- 156,162 ----
return FAIL;
}
}
! else if (vartype == VAR_LIST || *typep == &t_any || *typep == &t_unknown)
{
if (is_slice)
{
***************
*** 415,421 ****
// Global, Buffer-local, Window-local and Tabpage-local
// variables can be defined later, thus we don't check if it
// exists, give an error at runtime.
! res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
}
}
}
--- 415,421 ----
// Global, Buffer-local, Window-local and Tabpage-local
// variables can be defined later, thus we don't check if it
// exists, give an error at runtime.
! res = generate_LOAD(cctx, isn_type, 0, name, &t_unknown);
}
}
}
***************
*** 1428,1434 ****
if (type == &t_bool)
return OK;
! if (type == &t_any || type == &t_number || type == &t_number_bool)
// Number 0 and 1 are OK to use as a bool. "any" could also be a bool.
// This requires a runtime type check.
return generate_COND2BOOL(cctx);
--- 1428,1437 ----
if (type == &t_bool)
return OK;
! if (type == &t_any
! || type == &t_unknown
! || type == &t_number
! || type == &t_number_bool)
// Number 0 and 1 are OK to use as a bool. "any" could also be a bool.
// This requires a runtime type check.
return generate_COND2BOOL(cctx);
***************
*** 2155,2163 ****
generate_ppconst(cctx, ppconst);
actual = ((type_T **)stack->ga_data)[stack->ga_len - 1];
! if (check_type(want_type, actual, FALSE, where) == FAIL)
{
! if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL;
}
}
--- 2158,2167 ----
generate_ppconst(cctx, ppconst);
actual = ((type_T **)stack->ga_data)[stack->ga_len - 1];
! if (check_type_maybe(want_type, actual, FALSE, where) != OK)
{
! if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE)
! == FAIL)
return FAIL;
}
}
*** ../vim-8.2.3865/src/vim9instr.c 2021-12-21 09:42:05.626265159 +0000
--- src/vim9instr.c 2021-12-21 11:17:05.112606053 +0000
***************
*** 168,176 ****
static int
check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
{
! if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
&& (type2 == VAR_NUMBER || type2 == VAR_FLOAT
! || type2 == VAR_ANY)))
{
if (*op == '+')
emsg(_(e_wrong_argument_type_for_plus));
--- 168,177 ----
static int
check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
{
! if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT
! || type1 == VAR_ANY || type1 == VAR_UNKNOWN)
&& (type2 == VAR_NUMBER || type2 == VAR_FLOAT
! || type2 == VAR_ANY || type2 == VAR_UNKNOWN)))
{
if (*op == '+')
emsg(_(e_wrong_argument_type_for_plus));
***************
*** 204,210 ****
--- 205,213 ----
if (vartype != VAR_LIST && vartype != VAR_BLOB
&& type1->tt_type != VAR_ANY
+ && type1->tt_type != VAR_UNKNOWN
&& type2->tt_type != VAR_ANY
+ && type2->tt_type != VAR_UNKNOWN
&& check_number_or_float(
type1->tt_type, type2->tt_type, (char_u *)"+") == FAIL)
return FAIL;
***************
*** 293,300 ****
--- 296,305 ----
break;
case '%': if ((type1->tt_type != VAR_ANY
+ && type1->tt_type != VAR_UNKNOWN
&& type1->tt_type != VAR_NUMBER)
|| (type2->tt_type != VAR_ANY
+ && type2->tt_type != VAR_UNKNOWN
&& type2->tt_type != VAR_NUMBER))
{
emsg(_(e_percent_requires_number_arguments));
***************
*** 1528,1534 ****
RETURN_OK_IF_SKIP(cctx);
! if (type->tt_type == VAR_ANY)
ret_type = &t_any;
else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
{
--- 1533,1539 ----
RETURN_OK_IF_SKIP(cctx);
! if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN)
ret_type = &t_any;
else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
{
***************
*** 1620,1626 ****
// check for dict type
type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
! if (type->tt_type != VAR_DICT && type != &t_any)
{
char *tofree;
--- 1625,1631 ----
// check for dict type
type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
! if (type->tt_type != VAR_DICT && type != &t_any && type != &t_unknown)
{
char *tofree;
*** ../vim-8.2.3865/src/vim9cmds.c 2021-12-21 09:42:05.626265159 +0000
--- src/vim9cmds.c 2021-12-21 11:20:32.837049712 +0000
***************
*** 843,850 ****
// If we know the type of "var" and it is a not a supported type we can
// give an error now.
vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
! if (vartype->tt_type != VAR_LIST && vartype->tt_type != VAR_STRING
! && vartype->tt_type != VAR_BLOB && vartype->tt_type != VAR_ANY)
{
semsg(_(e_for_loop_on_str_not_supported),
vartype_name(vartype->tt_type));
--- 843,853 ----
// If we know the type of "var" and it is a not a supported type we can
// give an error now.
vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
! if (vartype->tt_type != VAR_LIST
! && vartype->tt_type != VAR_STRING
! && vartype->tt_type != VAR_BLOB
! && vartype->tt_type != VAR_ANY
! && vartype->tt_type != VAR_UNKNOWN)
{
semsg(_(e_for_loop_on_str_not_supported),
vartype_name(vartype->tt_type));
*** ../vim-8.2.3865/src/evalfunc.c 2021-12-20 09:36:20.101548272 +0000
--- src/evalfunc.c 2021-12-21 10:46:29.346624953 +0000
***************
*** 228,234 ****
arg_float_or_nr(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_FLOAT || type->tt_type == VAR_NUMBER)
return OK;
arg_type_mismatch(&t_number, type, context->arg_idx + 1);
return FAIL;
--- 228,236 ----
arg_float_or_nr(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_FLOAT
! || type->tt_type == VAR_NUMBER)
return OK;
arg_type_mismatch(&t_number, type, context->arg_idx + 1);
return FAIL;
***************
*** 313,319 ****
arg_list_or_blob(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_LIST || type->tt_type == VAR_BLOB)
return OK;
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
--- 315,323 ----
arg_list_or_blob(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_LIST
! || type->tt_type == VAR_BLOB)
return OK;
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
***************
*** 326,332 ****
arg_string_or_nr(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_STRING || type->tt_type == VAR_NUMBER)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
--- 330,338 ----
arg_string_or_nr(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_STRING
! || type->tt_type == VAR_NUMBER)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
***************
*** 339,345 ****
arg_buffer(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_STRING || type->tt_type == VAR_NUMBER)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
--- 345,353 ----
arg_buffer(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_STRING
! || type->tt_type == VAR_NUMBER)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
***************
*** 352,357 ****
--- 360,366 ----
arg_buffer_or_dict_any(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
+ || type->tt_type == VAR_UNKNOWN
|| type->tt_type == VAR_STRING
|| type->tt_type == VAR_NUMBER
|| type->tt_type == VAR_DICT)
***************
*** 367,373 ****
arg_lnum(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_STRING || type->tt_type == VAR_NUMBER)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
--- 376,384 ----
arg_lnum(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_STRING
! || type->tt_type == VAR_NUMBER)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
***************
*** 379,385 ****
static int
arg_string_or_list_string(type_T *type, argcontext_T *context)
{
! if (type->tt_type == VAR_ANY || type->tt_type == VAR_STRING)
return OK;
if (type->tt_type != VAR_LIST)
{
--- 390,398 ----
static int
arg_string_or_list_string(type_T *type, argcontext_T *context)
{
! if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_STRING)
return OK;
if (type->tt_type != VAR_LIST)
{
***************
*** 401,407 ****
arg_string_or_list_any(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_STRING || type->tt_type == VAR_LIST)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
--- 414,422 ----
arg_string_or_list_any(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_STRING
! || type->tt_type == VAR_LIST)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
***************
*** 414,420 ****
arg_string_or_blob(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_STRING || type->tt_type == VAR_BLOB)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
--- 429,437 ----
arg_string_or_blob(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_STRING
! || type->tt_type == VAR_BLOB)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
***************
*** 427,433 ****
arg_list_or_dict(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
return OK;
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
--- 444,452 ----
arg_list_or_dict(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_LIST
! || type->tt_type == VAR_DICT)
return OK;
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
***************
*** 440,448 ****
arg_list_or_dict_or_blob(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_LIST
! || type->tt_type == VAR_DICT
! || type->tt_type == VAR_BLOB)
return OK;
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
--- 459,468 ----
arg_list_or_dict_or_blob(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_LIST
! || type->tt_type == VAR_DICT
! || type->tt_type == VAR_BLOB)
return OK;
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
***************
*** 455,464 ****
arg_list_or_dict_or_blob_or_string(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_LIST
! || type->tt_type == VAR_DICT
! || type->tt_type == VAR_BLOB
! || type->tt_type == VAR_STRING)
return OK;
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
--- 475,485 ----
arg_list_or_dict_or_blob_or_string(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_LIST
! || type->tt_type == VAR_DICT
! || type->tt_type == VAR_BLOB
! || type->tt_type == VAR_STRING)
return OK;
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
***************
*** 471,479 ****
arg_string_list_or_blob(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_LIST
! || type->tt_type == VAR_BLOB
! || type->tt_type == VAR_STRING)
return OK;
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
--- 492,501 ----
arg_string_list_or_blob(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_LIST
! || type->tt_type == VAR_BLOB
! || type->tt_type == VAR_STRING)
return OK;
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
***************
*** 495,500 ****
--- 517,523 ----
arg_chan_or_job(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
+ || type->tt_type == VAR_UNKNOWN
|| type->tt_type == VAR_CHANNEL
|| type->tt_type == VAR_JOB)
return OK;
***************
*** 557,565 ****
arg_str_or_nr_or_list(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_STRING
! || type->tt_type == VAR_NUMBER
! || type->tt_type == VAR_LIST)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
--- 580,589 ----
arg_str_or_nr_or_list(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_STRING
! || type->tt_type == VAR_NUMBER
! || type->tt_type == VAR_LIST)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
***************
*** 572,579 ****
arg_dict_any_or_string(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_DICT
! || type->tt_type == VAR_STRING)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
--- 596,604 ----
arg_dict_any_or_string(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
! || type->tt_type == VAR_UNKNOWN
! || type->tt_type == VAR_DICT
! || type->tt_type == VAR_STRING)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
***************
*** 603,608 ****
--- 628,634 ----
arg_get1(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
+ || type->tt_type == VAR_UNKNOWN
|| type->tt_type == VAR_BLOB
|| type->tt_type == VAR_LIST
|| type->tt_type == VAR_DICT
***************
*** 622,627 ****
--- 648,654 ----
arg_len1(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
+ || type->tt_type == VAR_UNKNOWN
|| type->tt_type == VAR_STRING
|| type->tt_type == VAR_NUMBER
|| type->tt_type == VAR_BLOB
***************
*** 657,662 ****
--- 684,690 ----
arg_repeat1(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
+ || type->tt_type == VAR_UNKNOWN
|| type->tt_type == VAR_STRING
|| type->tt_type == VAR_NUMBER
|| type->tt_type == VAR_LIST)
***************
*** 674,679 ****
--- 702,708 ----
arg_slice1(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
+ || type->tt_type == VAR_UNKNOWN
|| type->tt_type == VAR_LIST
|| type->tt_type == VAR_BLOB
|| type->tt_type == VAR_STRING)
***************
*** 691,696 ****
--- 720,726 ----
arg_count1(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
+ || type->tt_type == VAR_UNKNOWN
|| type->tt_type == VAR_STRING
|| type->tt_type == VAR_LIST
|| type->tt_type == VAR_DICT)
***************
*** 708,713 ****
--- 738,744 ----
arg_cursor1(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
+ || type->tt_type == VAR_UNKNOWN
|| type->tt_type == VAR_NUMBER
|| type->tt_type == VAR_STRING
|| type->tt_type == VAR_LIST)
*** ../vim-8.2.3865/src/testdir/test_vim9_func.vim 2021-12-19
18:33:17.325954806 +0000
--- src/testdir/test_vim9_func.vim 2021-12-21 11:29:00.517302071 +0000
***************
*** 547,552 ****
--- 547,585 ----
defcompile
END
CheckScriptFailure(lines, 'E1001: Variable not found: b')
+
+ # using script variable requires matching type or type cast
+ lines =<< trim END
+ vim9script
+ var a: any
+ def Func(arg: string = a)
+ echo arg
+ enddef
+ defcompile
+ END
+ CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected
string but got any')
+
+ lines =<< trim END
+ vim9script
+ var a: any
+ def Func(arg: string = <string>a)
+ echo arg
+ enddef
+ a = 'works'
+ Func()
+ END
+ CheckScriptSuccess(lines)
+
+ # using global variable does not require type cast
+ lines =<< trim END
+ vim9script
+ def Func(arg: string = g:str)
+ echo arg
+ enddef
+ g:str = 'works'
+ Func()
+ END
+ CheckScriptSuccess(lines)
enddef
def FuncWithComment( # comment
*** ../vim-8.2.3865/src/version.c 2021-12-21 09:42:05.626265159 +0000
--- src/version.c 2021-12-21 10:28:53.488316227 +0000
***************
*** 751,752 ****
--- 751,754 ----
{ /* Add new patch number below this line */
+ /**/
+ 3866,
/**/
--
>From "know your smileys":
:-O>-o Smiley American tourist (note big mouth and camera)
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/20211221123252.A38661C0DCA%40moolenaar.net.