Patch 8.2.1691
Problem: Vim9: list<any> is not accepted where list<number> is expected.
Solution: Add functions to allocate and free a type_T, use it in
ISN_CHECKTYPE. (closes #6959)
Files: src/vim9.h, src/globals.h, src/vim9compile.c, src/vim9execute.c,
src/vim9type.c, src/proto/vim9type.pro, src/errors.h,
src/evalfunc.c, src/testdir/test_vim9_disassemble.vim,
src/testdir/test_vim9_expr.vim, src/testdir/test_vim9_func.vim,
src/testdir/test_vim9_script.vim
*** ../vim-8.2.1690/src/vim9.h 2020-09-14 21:38:47.756976285 +0200
--- src/vim9.h 2020-09-16 12:28:45.638357945 +0200
***************
*** 207,213 ****
// arguments to ISN_CHECKTYPE
typedef struct {
! vartype_T ct_type;
int ct_off; // offset in stack, -1 is bottom
} checktype_T;
--- 207,213 ----
// arguments to ISN_CHECKTYPE
typedef struct {
! type_T *ct_type;
int ct_off; // offset in stack, -1 is bottom
} checktype_T;
*** ../vim-8.2.1690/src/globals.h 2020-09-06 21:47:39.323041533 +0200
--- src/globals.h 2020-09-16 12:17:44.684511692 +0200
***************
*** 391,432 ****
// Commonly used types.
! 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);
! EXTERN type_T t_number INIT6(VAR_NUMBER, 0, 0, 0, NULL, NULL);
! EXTERN type_T t_float INIT6(VAR_FLOAT, 0, 0, 0, NULL, NULL);
! EXTERN type_T t_string INIT6(VAR_STRING, 0, 0, 0, NULL, NULL);
! 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);
! EXTERN type_T t_func_string INIT6(VAR_FUNC, -1, 0, 0, &t_string, NULL);
! EXTERN type_T t_func_0_void INIT6(VAR_FUNC, 0, 0, 0, &t_void, NULL);
! EXTERN type_T t_func_0_any INIT6(VAR_FUNC, 0, 0, 0, &t_any, NULL);
! EXTERN type_T t_func_0_number INIT6(VAR_FUNC, 0, 0, 0, &t_number, NULL);
! 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_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);
! EXTERN type_T t_list_string INIT6(VAR_LIST, 0, 0, 0, &t_string, NULL);
! EXTERN type_T t_list_dict_any INIT6(VAR_LIST, 0, 0, 0, &t_dict_any, NULL);
!
! EXTERN type_T t_dict_bool INIT6(VAR_DICT, 0, 0, 0, &t_bool, NULL);
! EXTERN type_T t_dict_number INIT6(VAR_DICT, 0, 0, 0, &t_number, NULL);
! EXTERN type_T t_dict_string INIT6(VAR_DICT, 0, 0, 0, &t_string, NULL);
!
#endif
--- 391,431 ----
// Commonly used types.
! EXTERN type_T t_unknown INIT6(VAR_UNKNOWN, 0, 0, TTFLAG_STATIC, NULL, NULL);
! EXTERN type_T t_any INIT6(VAR_ANY, 0, 0, TTFLAG_STATIC, NULL, NULL);
! 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);
! EXTERN type_T t_float INIT6(VAR_FLOAT, 0, 0, TTFLAG_STATIC, NULL, NULL);
! EXTERN type_T t_string INIT6(VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL);
! EXTERN type_T t_blob INIT6(VAR_BLOB, 0, 0, TTFLAG_STATIC, NULL, NULL);
! EXTERN type_T t_job INIT6(VAR_JOB, 0, 0, TTFLAG_STATIC, NULL, NULL);
! EXTERN type_T t_channel INIT6(VAR_CHANNEL, 0, 0, TTFLAG_STATIC, NULL, NULL);
!
! EXTERN type_T t_func_unknown INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC,
&t_unknown, NULL);
! EXTERN type_T t_func_void INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_void,
NULL);
! EXTERN type_T t_func_any INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_any, NULL);
! EXTERN type_T t_func_number INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_number,
NULL);
! EXTERN type_T t_func_string INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_string,
NULL);
! EXTERN type_T t_func_0_void INIT6(VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_void,
NULL);
! EXTERN type_T t_func_0_any INIT6(VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_any, NULL);
! EXTERN type_T t_func_0_number INIT6(VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_number,
NULL);
! EXTERN type_T t_func_0_string INIT6(VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_string,
NULL);
!
! EXTERN type_T t_list_any INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_any, NULL);
! EXTERN type_T t_dict_any INIT6(VAR_DICT, 0, 0, TTFLAG_STATIC, &t_any, NULL);
! EXTERN type_T t_list_empty INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_unknown,
NULL);
! EXTERN type_T t_dict_empty INIT6(VAR_DICT, 0, 0, TTFLAG_STATIC, &t_unknown,
NULL);
!
! EXTERN type_T t_list_bool INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_bool, NULL);
! EXTERN type_T t_list_number INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_number,
NULL);
! EXTERN type_T t_list_string INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_string,
NULL);
! EXTERN type_T t_list_dict_any INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC,
&t_dict_any, NULL);
!
! EXTERN type_T t_dict_bool INIT6(VAR_DICT, 0, 0, TTFLAG_STATIC, &t_bool, NULL);
! EXTERN type_T t_dict_number INIT6(VAR_DICT, 0, 0, TTFLAG_STATIC, &t_number,
NULL);
! EXTERN type_T t_dict_string INIT6(VAR_DICT, 0, 0, TTFLAG_STATIC, &t_string,
NULL);
#endif
*** ../vim-8.2.1690/src/vim9compile.c 2020-09-14 22:39:05.969192788 +0200
--- src/vim9compile.c 2020-09-16 13:49:48.699234854 +0200
***************
*** 704,710 ****
}
static int
! generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
{
isn_T *isn;
garray_T *stack = &cctx->ctx_type_stack;
--- 704,713 ----
}
static int
! generate_TYPECHECK(
! cctx_T *cctx,
! type_T *expected,
! int offset)
{
isn_T *isn;
garray_T *stack = &cctx->ctx_type_stack;
***************
*** 712,730 ****
RETURN_OK_IF_SKIP(cctx);
if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
return FAIL;
! // TODO: whole type, e.g. for a function also arg and return types
! isn->isn_arg.type.ct_type = vartype->tt_type;
isn->isn_arg.type.ct_off = offset;
! // type becomes vartype
! ((type_T **)stack->ga_data)[stack->ga_len + offset] = vartype;
return OK;
}
/*
* Check that
! * - "actual" is "expected" type or
* - "actual" is a type that can be "expected" type: add a runtime check; or
* - return FAIL.
*/
--- 715,732 ----
RETURN_OK_IF_SKIP(cctx);
if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
return FAIL;
! isn->isn_arg.type.ct_type = alloc_type(expected);
isn->isn_arg.type.ct_off = offset;
! // type becomes expected
! ((type_T **)stack->ga_data)[stack->ga_len + offset] = expected;
return OK;
}
/*
* Check that
! * - "actual" matches "expected" type or
* - "actual" is a type that can be "expected" type: add a runtime check; or
* - return FAIL.
*/
***************
*** 747,763 ****
if (check_type(expected, actual, FALSE, 0) == OK)
return OK;
! if (actual->tt_type != VAR_ANY
! && actual->tt_type != VAR_UNKNOWN
! && !(actual->tt_type == VAR_FUNC
! && (actual->tt_member == &t_any || actual->tt_argcount < 0)))
{
! if (!silent)
! type_mismatch(expected, actual);
! return FAIL;
}
! generate_TYPECHECK(cctx, expected, offset);
! return OK;
}
/*
--- 749,777 ----
if (check_type(expected, actual, FALSE, 0) == OK)
return OK;
!
! // If the actual type can be the expected type add a runtime check.
! // TODO: if it's a constant a runtime check makes no sense.
! if (actual->tt_type == VAR_ANY
! || actual->tt_type == VAR_UNKNOWN
! || (actual->tt_type == VAR_FUNC
! && (expected->tt_type == VAR_FUNC
! || expected->tt_type == VAR_PARTIAL)
! && (actual->tt_member == &t_any || actual->tt_argcount < 0))
! || (actual->tt_type == VAR_LIST
! && expected->tt_type == VAR_LIST
! && actual->tt_member == &t_any)
! || (actual->tt_type == VAR_DICT
! && expected->tt_type == VAR_DICT
! && actual->tt_member == &t_any))
{
! generate_TYPECHECK(cctx, expected, offset);
! return OK;
}
!
! if (!silent)
! type_mismatch(expected, actual);
! return FAIL;
}
/*
***************
*** 776,782 ****
if (number == 0 || number == 1)
{
! type_T *type = alloc_type(cctx->ctx_type_list);
// A 0 or 1 number can also be used as a bool.
if (type != NULL)
--- 790,796 ----
if (number == 0 || number == 1)
{
! type_T *type = get_type_ptr(cctx->ctx_type_list);
// A 0 or 1 number can also be used as a bool.
if (type != NULL)
***************
*** 4037,4043 ****
typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
if (*typep != &t_bool)
{
! type_T *type = alloc_type(cctx->ctx_type_list);
if (type != NULL)
{
--- 4051,4057 ----
typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
if (*typep != &t_bool)
{
! type_T *type = get_type_ptr(cctx->ctx_type_list);
if (type != NULL)
{
***************
*** 7290,7295 ****
--- 7304,7313 ----
}
break;
+ case ISN_CHECKTYPE:
+ free_type(isn->isn_arg.type.ct_type);
+ break;
+
case ISN_2BOOL:
case ISN_2STRING:
case ISN_2STRING_ANY:
***************
*** 7301,7307 ****
case ISN_CATCH:
case ISN_CHECKLEN:
case ISN_CHECKNR:
- case ISN_CHECKTYPE:
case ISN_COMPAREANY:
case ISN_COMPAREBLOB:
case ISN_COMPAREBOOL:
--- 7319,7324 ----
*** ../vim-8.2.1690/src/vim9execute.c 2020-09-14 21:38:47.756976285 +0200
--- src/vim9execute.c 2020-09-16 13:57:42.669334121 +0200
***************
*** 2535,2564 ****
checktype_T *ct = &iptr->isn_arg.type;
tv = STACK_TV_BOT(ct->ct_off);
! // TODO: better type comparison
! if (tv->v_type != ct->ct_type
! && !((tv->v_type == VAR_PARTIAL
! && ct->ct_type == VAR_FUNC)
! || (tv->v_type == VAR_FUNC
! && ct->ct_type == VAR_PARTIAL)))
{
! if (tv->v_type == VAR_NUMBER && ct->ct_type == VAR_BOOL
! && (tv->vval.v_number == 0
! || tv->vval.v_number == 1))
! {
! // number 0 is FALSE, number 1 is TRUE
! tv->v_type = VAR_BOOL;
! tv->vval.v_number = tv->vval.v_number
? VVAL_TRUE : VVAL_FALSE;
- }
- else
- {
- SOURCING_LNUM = iptr->isn_lnum;
- semsg(_(e_expected_str_but_got_str),
- vartype_name(ct->ct_type),
- vartype_name(tv->v_type));
- goto on_error;
- }
}
}
break;
--- 2535,2553 ----
checktype_T *ct = &iptr->isn_arg.type;
tv = STACK_TV_BOT(ct->ct_off);
! SOURCING_LNUM = iptr->isn_lnum;
! if (check_typval_type(ct->ct_type, tv, 0) == FAIL)
! goto on_error;
!
! // number 0 is FALSE, number 1 is TRUE
! if (tv->v_type == VAR_NUMBER
! && ct->ct_type->tt_type == VAR_BOOL
! && (tv->vval.v_number == 0
! || tv->vval.v_number == 1))
{
! tv->v_type = VAR_BOOL;
! tv->vval.v_number = tv->vval.v_number
? VVAL_TRUE : VVAL_FALSE;
}
}
break;
***************
*** 3286,3295 ****
case ISN_NEGATENR: smsg("%4d NEGATENR", current); break;
case ISN_CHECKNR: smsg("%4d CHECKNR", current); break;
! case ISN_CHECKTYPE: smsg("%4d CHECKTYPE %s stack[%d]", current,
! vartype_name(iptr->isn_arg.type.ct_type),
! iptr->isn_arg.type.ct_off);
! break;
case ISN_CHECKLEN: smsg("%4d CHECKLEN %s%d", current,
iptr->isn_arg.checklen.cl_more_OK ? ">= " : "",
iptr->isn_arg.checklen.cl_min_len);
--- 3275,3290 ----
case ISN_NEGATENR: smsg("%4d NEGATENR", current); break;
case ISN_CHECKNR: smsg("%4d CHECKNR", current); break;
! case ISN_CHECKTYPE:
! {
! char *tofree;
!
! smsg("%4d CHECKTYPE %s stack[%d]", current,
! type_name(iptr->isn_arg.type.ct_type, &tofree),
! iptr->isn_arg.type.ct_off);
! vim_free(tofree);
! break;
! }
case ISN_CHECKLEN: smsg("%4d CHECKLEN %s%d", current,
iptr->isn_arg.checklen.cl_more_OK ? ">= " : "",
iptr->isn_arg.checklen.cl_min_len);
*** ../vim-8.2.1690/src/vim9type.c 2020-09-09 22:27:55.425537078 +0200
--- src/vim9type.c 2020-09-16 15:19:29.363276116 +0200
***************
*** 22,31 ****
/*
* Allocate memory for a type_T and add the pointer to type_gap, so that it
can
! * be freed later.
*/
type_T *
! alloc_type(garray_T *type_gap)
{
type_T *type;
--- 22,31 ----
/*
* Allocate memory for a type_T and add the pointer to type_gap, so that it
can
! * be easily freed later.
*/
type_T *
! get_type_ptr(garray_T *type_gap)
{
type_T *type;
***************
*** 48,53 ****
--- 48,107 ----
ga_clear(gap);
}
+ /*
+ * Take a type that is using entries in a growarray and turn it into a type
+ * with allocated entries.
+ */
+ type_T *
+ alloc_type(type_T *type)
+ {
+ type_T *ret;
+
+ if (type == NULL)
+ return NULL;
+
+ // A fixed type never contains allocated types, return as-is.
+ if (type->tt_flags & TTFLAG_STATIC)
+ return type;
+
+ ret = ALLOC_ONE(type_T);
+ *ret = *type;
+
+ if (ret->tt_member != NULL)
+ ret->tt_member = alloc_type(ret->tt_member);
+ if (type->tt_args != NULL)
+ {
+ int i;
+
+ ret->tt_args = ALLOC_MULT(type_T *, type->tt_argcount);
+ if (ret->tt_args != NULL)
+ for (i = 0; i < type->tt_argcount; ++i)
+ ret->tt_args[i] = alloc_type(type->tt_args[i]);
+ }
+
+ return ret;
+ }
+
+ /*
+ * Free a type that was created with alloc_type().
+ */
+ void
+ free_type(type_T *type)
+ {
+ int i;
+
+ if (type == NULL || (type->tt_flags & TTFLAG_STATIC))
+ return;
+ if (type->tt_args != NULL)
+ {
+ for (i = 0; i < type->tt_argcount; ++i)
+ free_type(type->tt_args[i]);
+ vim_free(type->tt_args);
+ }
+ free_type(type->tt_member);
+ vim_free(type);
+ }
+
type_T *
get_list_type(type_T *member_type, garray_T *type_gap)
{
***************
*** 67,73 ****
return &t_list_string;
// Not a common type, create a new entry.
! type = alloc_type(type_gap);
if (type == NULL)
return &t_any;
type->tt_type = VAR_LIST;
--- 121,127 ----
return &t_list_string;
// Not a common type, create a new entry.
! type = get_type_ptr(type_gap);
if (type == NULL)
return &t_any;
type->tt_type = VAR_LIST;
***************
*** 96,102 ****
return &t_dict_string;
// Not a common type, create a new entry.
! type = alloc_type(type_gap);
if (type == NULL)
return &t_any;
type->tt_type = VAR_DICT;
--- 150,156 ----
return &t_dict_string;
// Not a common type, create a new entry.
! type = get_type_ptr(type_gap);
if (type == NULL)
return &t_any;
type->tt_type = VAR_DICT;
***************
*** 112,118 ****
type_T *
alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
{
! type_T *type = alloc_type(type_gap);
if (type == NULL)
return &t_any;
--- 166,172 ----
type_T *
alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
{
! type_T *type = get_type_ptr(type_gap);
if (type == NULL)
return &t_any;
***************
*** 197,209 ****
/*
* Get a type_T for a typval_T.
! * "type_list" is used to temporarily create types in.
*/
static type_T *
typval2type_int(typval_T *tv, garray_T *type_gap)
{
type_T *type;
! type_T *member_type;
if (tv->v_type == VAR_NUMBER)
return &t_number;
--- 251,264 ----
/*
* Get a type_T for a typval_T.
! * "type_gap" is used to temporarily create types in.
*/
static type_T *
typval2type_int(typval_T *tv, garray_T *type_gap)
{
type_T *type;
! type_T *member_type = &t_any;
! int argcount = 0;
if (tv->v_type == VAR_NUMBER)
return &t_number;
***************
*** 262,269 ****
else
name = tv->vval.v_string;
if (name != NULL)
! // TODO: how about a builtin function?
! ufunc = find_func(name, FALSE, NULL);
if (ufunc != NULL)
{
// May need to get the argument types from default values by
--- 317,334 ----
else
name = tv->vval.v_string;
if (name != NULL)
! {
! int idx = find_internal_func(name);
!
! if (idx >= 0)
! {
! // TODO: get actual arg count and types
! argcount = -1;
! member_type = internal_func_ret_type(idx, 0, NULL);
! }
! else
! ufunc = find_func(name, FALSE, NULL);
! }
if (ufunc != NULL)
{
// May need to get the argument types from default values by
***************
*** 276,286 ****
}
}
! type = alloc_type(type_gap);
if (type == NULL)
return NULL;
type->tt_type = tv->v_type;
! type->tt_member = &t_any;
return type;
}
--- 341,352 ----
}
}
! type = get_type_ptr(type_gap);
if (type == NULL)
return NULL;
type->tt_type = tv->v_type;
! type->tt_argcount = argcount;
! type->tt_member = member_type;
return type;
}
***************
*** 311,317 ****
&& (tv->vval.v_number == 0 || tv->vval.v_number == 1))
|| (tv->v_lock & VAR_BOOL_OK)))
{
! type_T *newtype = alloc_type(type_gap);
// Number 0 and 1 and expression with "&&" or "||" can also be used
// for bool.
--- 377,383 ----
&& (tv->vval.v_number == 0 || tv->vval.v_number == 1))
|| (tv->v_lock & VAR_BOOL_OK)))
{
! type_T *newtype = get_type_ptr(type_gap);
// Number 0 and 1 and expression with "&&" or "||" can also be used
// for bool.
***************
*** 420,425 ****
--- 486,492 ----
ret = check_type(expected->tt_member, actual->tt_member,
FALSE, 0);
if (ret == OK && expected->tt_argcount != -1
+ && actual->tt_argcount != -1
&& (actual->tt_argcount < expected->tt_min_argcount
|| actual->tt_argcount > expected->tt_argcount))
ret = FAIL;
***************
*** 940,946 ****
ga_init2(&ga, 1, 100);
if (ga_grow(&ga, 20) == FAIL)
return "[unknown]";
- *tofree = ga.ga_data;
STRCPY(ga.ga_data, "func(");
ga.ga_len += 5;
--- 1007,1012 ----
***************
*** 963,982 ****
if (ga_grow(&ga, len + 8) == FAIL)
{
vim_free(arg_free);
return "[unknown]";
}
- *tofree = ga.ga_data;
if (varargs && i == type->tt_argcount - 1)
! {
! STRCPY((char *)ga.ga_data + ga.ga_len, "...");
! ga.ga_len += 3;
! }
else if (i >= type->tt_min_argcount)
*((char *)ga.ga_data + ga.ga_len++) = '?';
! STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
! ga.ga_len += len;
vim_free(arg_free);
}
if (type->tt_member == &t_void)
STRCPY((char *)ga.ga_data + ga.ga_len, ")");
--- 1029,1047 ----
if (ga_grow(&ga, len + 8) == FAIL)
{
vim_free(arg_free);
+ ga_clear(&ga);
return "[unknown]";
}
if (varargs && i == type->tt_argcount - 1)
! ga_concat(&ga, (char_u *)"...");
else if (i >= type->tt_min_argcount)
*((char *)ga.ga_data + ga.ga_len++) = '?';
! ga_concat(&ga, (char_u *)arg_type);
vim_free(arg_free);
}
+ if (type->tt_argcount < 0)
+ // any number of arguments
+ ga_concat(&ga, (char_u *)"...");
if (type->tt_member == &t_void)
STRCPY((char *)ga.ga_data + ga.ga_len, ")");
***************
*** 990,1007 ****
if (ga_grow(&ga, len) == FAIL)
{
vim_free(ret_free);
return "[unknown]";
}
- *tofree = ga.ga_data;
STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
vim_free(ret_free);
}
return ga.ga_data;
}
return name;
}
-
#endif // FEAT_EVAL
--- 1055,1072 ----
if (ga_grow(&ga, len) == FAIL)
{
vim_free(ret_free);
+ ga_clear(&ga);
return "[unknown]";
}
STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
vim_free(ret_free);
}
+ *tofree = ga.ga_data;
return ga.ga_data;
}
return name;
}
#endif // FEAT_EVAL
*** ../vim-8.2.1690/src/proto/vim9type.pro 2020-09-09 22:27:55.425537078
+0200
--- src/proto/vim9type.pro 2020-09-16 13:02:56.784516124 +0200
***************
*** 1,6 ****
/* vim9type.c */
! type_T *alloc_type(garray_T *type_gap);
void clear_type_list(garray_T *gap);
type_T *get_list_type(type_T *member_type, garray_T *type_gap);
type_T *get_dict_type(type_T *member_type, garray_T *type_gap);
type_T *alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap);
--- 1,8 ----
/* vim9type.c */
! type_T *get_type_ptr(garray_T *type_gap);
void clear_type_list(garray_T *gap);
+ type_T *alloc_type(type_T *type);
+ void free_type(type_T *type);
type_T *get_list_type(type_T *member_type, garray_T *type_gap);
type_T *get_dict_type(type_T *member_type, garray_T *type_gap);
type_T *alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap);
*** ../vim-8.2.1690/src/errors.h 2020-09-14 21:38:47.756976285 +0200
--- src/errors.h 2020-09-16 12:42:28.068175429 +0200
***************
*** 52,58 ****
EXTERN char e_name_too_long_str[]
INIT(= N_("E1011: name too long: %s"));
EXTERN char e_type_mismatch_expected_str_but_got_str[]
! INIT(= N_("E1012: type mismatch, expected %s but got %s"));
EXTERN char e_argument_nr_type_mismatch_expected_str_but_got_str[]
INIT(= N_("E1013: argument %d: type mismatch, expected %s but got %s"));
EXTERN char e_invalid_key_str[]
--- 52,58 ----
EXTERN char e_name_too_long_str[]
INIT(= N_("E1011: name too long: %s"));
EXTERN char e_type_mismatch_expected_str_but_got_str[]
! INIT(= N_("E1012: Type mismatch; expected %s but got %s"));
EXTERN char e_argument_nr_type_mismatch_expected_str_but_got_str[]
INIT(= N_("E1013: argument %d: type mismatch, expected %s but got %s"));
EXTERN char e_invalid_key_str[]
*** ../vim-8.2.1690/src/evalfunc.c 2020-09-11 22:25:11.298775020 +0200
--- src/evalfunc.c 2020-09-16 15:04:27.991180534 +0200
***************
*** 386,396 ****
static type_T *
ret_remove(int argcount UNUSED, type_T **argtypes)
{
! if (argtypes[0]->tt_type == VAR_LIST
! || argtypes[0]->tt_type == VAR_DICT)
! return argtypes[0]->tt_member;
! if (argtypes[0]->tt_type == VAR_BLOB)
! return &t_number;
return &t_any;
}
--- 386,399 ----
static type_T *
ret_remove(int argcount UNUSED, type_T **argtypes)
{
! if (argtypes != NULL)
! {
! if (argtypes[0]->tt_type == VAR_LIST
! || argtypes[0]->tt_type == VAR_DICT)
! return argtypes[0]->tt_member;
! if (argtypes[0]->tt_type == VAR_BLOB)
! return &t_number;
! }
return &t_any;
}
***************
*** 2915,2921 ****
{
if (argcount == 1 && argtypes[0]->tt_type == VAR_STRING)
return &t_func_any;
! return &t_func_void;
}
/*
--- 2918,2924 ----
{
if (argcount == 1 && argtypes[0]->tt_type == VAR_STRING)
return &t_func_any;
! return &t_func_unknown;
}
/*
*** ../vim-8.2.1690/src/testdir/test_vim9_disassemble.vim 2020-09-09
20:03:42.908661678 +0200
--- src/testdir/test_vim9_disassemble.vim 2020-09-16 13:08:31.918312336
+0200
***************
*** 258,264 ****
'\d STORE $2\_s*' ..
'\[x, y; l\] = g:stringlist\_s*' ..
'\d LOADG g:stringlist\_s*' ..
! '\d CHECKTYPE list stack\[-1\]\_s*' ..
'\d CHECKLEN >= 2\_s*' ..
'\d\+ ITEM 0\_s*' ..
'\d\+ CHECKTYPE string stack\[-1\]\_s*' ..
--- 258,264 ----
'\d STORE $2\_s*' ..
'\[x, y; l\] = g:stringlist\_s*' ..
'\d LOADG g:stringlist\_s*' ..
! '\d CHECKTYPE list<any> stack\[-1\]\_s*' ..
'\d CHECKLEN >= 2\_s*' ..
'\d\+ ITEM 0\_s*' ..
'\d\+ CHECKTYPE string stack\[-1\]\_s*' ..
***************
*** 829,835 ****
'\d STORE -1 in $1\_s*' ..
'\d PUSHS "\["one", "two"\]"\_s*' ..
'\d BCALL eval(argc 1)\_s*' ..
! '\d CHECKTYPE list stack\[-1\]\_s*' ..
'\d FOR $1 -> \d\+\_s*' ..
'\d STORE $2\_s*' ..
'res ..= str\_s*' ..
--- 829,835 ----
'\d STORE -1 in $1\_s*' ..
'\d PUSHS "\["one", "two"\]"\_s*' ..
'\d BCALL eval(argc 1)\_s*' ..
! '\d CHECKTYPE list<any> stack\[-1\]\_s*' ..
'\d FOR $1 -> \d\+\_s*' ..
'\d STORE $2\_s*' ..
'res ..= str\_s*' ..
***************
*** 1144,1150 ****
'\d STORE $0\_s*' ..
'return res\_s*' ..
'\d LOAD $0\_s*' ..
! '\d CHECKTYPE list stack\[-1\]\_s*' ..
'\d RETURN',
instr)
assert_equal([2, 3, 4], AnySlice())
--- 1144,1150 ----
'\d STORE $0\_s*' ..
'return res\_s*' ..
'\d LOAD $0\_s*' ..
! '\d CHECKTYPE list<number> stack\[-1\]\_s*' ..
'\d RETURN',
instr)
assert_equal([2, 3, 4], AnySlice())
*** ../vim-8.2.1690/src/testdir/test_vim9_expr.vim 2020-09-14
16:50:01.751887481 +0200
--- src/testdir/test_vim9_expr.vim 2020-09-16 14:07:37.855022314 +0200
***************
*** 1438,1445 ****
let old: list<string> = v:oldfiles
let compl: dict<any> = v:completed_item
! CheckDefFailure(["let old: list<number> = v:oldfiles"], 'E1012: type
mismatch, expected list<number> but got list<string>', 1)
! CheckDefFailure(["let old: dict<number> = v:completed_item"], 'E1012: type
mismatch, expected dict<number> but got dict<any>', 1)
enddef
def Test_expr7_special()
--- 1438,1448 ----
let old: list<string> = v:oldfiles
let compl: dict<any> = v:completed_item
! CheckDefFailure(["let old: list<number> = v:oldfiles"], 'E1012: Type
mismatch; expected list<number> but got list<string>', 1)
! new
! exec "normal! afoo fo\<C-N>\<Esc>"
! CheckDefExecFailure(["let old: dict<number> = v:completed_item"], 'E1012:
Type mismatch; expected dict<number> but got dict<string>', 1)
! bwipe!
enddef
def Test_expr7_special()
***************
*** 1520,1533 ****
CheckDefExecFailure(["echo 1", "let x = [][0]", "echo 3"], 'E684:', 2)
! CheckDefExecFailure(["let x = g:list_mixed['xx']"], 'E1029:', 1)
CheckDefFailure(["let x = g:list_mixed["], 'E1097:', 2)
CheckDefFailure(["let x = g:list_mixed[0"], 'E1097:', 2)
CheckDefExecFailure(["let x = g:list_empty[3]"], 'E684:', 1)
! CheckDefFailure(["let l: list<number> = [234, 'x']"], 'E1012:', 1)
! CheckDefFailure(["let l: list<number> = ['x', 234]"], 'E1012:', 1)
! CheckDefFailure(["let l: list<string> = [234, 'x']"], 'E1012:', 1)
! CheckDefFailure(["let l: list<string> = ['x', 123]"], 'E1012:', 1)
enddef
def Test_expr7_list_vim9script()
--- 1523,1536 ----
CheckDefExecFailure(["echo 1", "let x = [][0]", "echo 3"], 'E684:', 2)
! CheckDefExecFailure(["let x = g:list_mixed['xx']"], 'E1012:', 1)
CheckDefFailure(["let x = g:list_mixed["], 'E1097:', 2)
CheckDefFailure(["let x = g:list_mixed[0"], 'E1097:', 2)
CheckDefExecFailure(["let x = g:list_empty[3]"], 'E684:', 1)
! CheckDefExecFailure(["let l: list<number> = [234, 'x']"], 'E1012:', 1)
! CheckDefExecFailure(["let l: list<number> = ['x', 234]"], 'E1012:', 1)
! CheckDefExecFailure(["let l: list<string> = [234, 'x']"], 'E1012:', 1)
! CheckDefExecFailure(["let l: list<string> = ['x', 123]"], 'E1012:', 1)
enddef
def Test_expr7_list_vim9script()
***************
*** 1731,1740 ****
CheckDefExecFailure(["let x = g:anint.member"], 'E715:', 1)
CheckDefExecFailure(["let x = g:dict_empty.member"], 'E716:', 1)
! CheckDefFailure(['let x: dict<number> = #{a: 234, b: "1"}'], 'E1012:', 1)
! CheckDefFailure(['let x: dict<number> = #{a: "x", b: 134}'], 'E1012:', 1)
! CheckDefFailure(['let x: dict<string> = #{a: 234, b: "1"}'], 'E1012:', 1)
! CheckDefFailure(['let x: dict<string> = #{a: "x", b: 134}'], 'E1012:', 1)
enddef
def Test_expr7_dict_vim9script()
--- 1734,1743 ----
CheckDefExecFailure(["let x = g:anint.member"], 'E715:', 1)
CheckDefExecFailure(["let x = g:dict_empty.member"], 'E716:', 1)
! CheckDefExecFailure(['let x: dict<number> = #{a: 234, b: "1"}'], 'E1012:',
1)
! CheckDefExecFailure(['let x: dict<number> = #{a: "x", b: 134}'], 'E1012:',
1)
! CheckDefExecFailure(['let x: dict<string> = #{a: 234, b: "1"}'], 'E1012:',
1)
! CheckDefExecFailure(['let x: dict<string> = #{a: "x", b: 134}'], 'E1012:',
1)
enddef
def Test_expr7_dict_vim9script()
***************
*** 1840,1846 ****
CheckDefFailure(["let x = g:dict_one.#$!"], 'E1002:', 1)
CheckDefExecFailure(["let d: dict<any>", "echo d['a']"], 'E716:', 2)
! CheckDefExecFailure(["let d: dict<number>", "d = g:list_empty"], 'E1029:
Expected dict but got list', 2)
enddef
def Test_expr7_any_index_slice()
--- 1843,1849 ----
CheckDefFailure(["let x = g:dict_one.#$!"], 'E1002:', 1)
CheckDefExecFailure(["let d: dict<any>", "echo d['a']"], 'E716:', 2)
! CheckDefExecFailure(["let d: dict<number>", "d = g:list_empty"], 'E1012:
Type mismatch; expected dict<number> but got list<unknown>', 2)
enddef
def Test_expr7_any_index_slice()
***************
*** 2311,2317 ****
CheckScriptSuccess(['vim9script'] + lines)
lines = ['let l = [0, 1, 2]', 'echo l[g:astring : g:theone]']
! CheckDefExecFailure(lines, 'E1029:')
CheckScriptFailure(['vim9script'] + lines, 'E1030:', 3)
enddef
--- 2314,2320 ----
CheckScriptSuccess(['vim9script'] + lines)
lines = ['let l = [0, 1, 2]', 'echo l[g:astring : g:theone]']
! CheckDefExecFailure(lines, 'E1012:')
CheckScriptFailure(['vim9script'] + lines, 'E1030:', 3)
enddef
*** ../vim-8.2.1690/src/testdir/test_vim9_func.vim 2020-09-14
17:04:27.652663882 +0200
--- src/testdir/test_vim9_func.vim 2020-09-16 15:06:45.854577887 +0200
***************
*** 30,36 ****
def Test_return_something()
ReturnString()->assert_equal('string')
ReturnNumber()->assert_equal(123)
! assert_fails('ReturnGlobal()', 'E1029: Expected number but got string', '',
1, 'ReturnGlobal')
enddef
def Test_missing_return()
--- 30,36 ----
def Test_return_something()
ReturnString()->assert_equal('string')
ReturnNumber()->assert_equal(123)
! assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but
got string', '', 1, 'ReturnGlobal')
enddef
def Test_missing_return()
***************
*** 487,493 ****
enddef
let Funcref: func(string) = function('UseNumber')
END
! CheckScriptFailure(lines, 'E1012: type mismatch, expected func(string) but
got func(number)')
lines =<< trim END
vim9script
--- 487,493 ----
enddef
let Funcref: func(string) = function('UseNumber')
END
! CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(string) but
got func(number)')
lines =<< trim END
vim9script
***************
*** 976,1012 ****
let RefVoid: func: void
RefVoid = FuncNoArgNoRet
RefVoid = FuncOneArgNoRet
! CheckDefFailure(['let RefVoid: func: void', 'RefVoid =
FuncNoArgRetNumber'], 'E1012: type mismatch, expected func() but got func():
number')
! CheckDefFailure(['let RefVoid: func: void', 'RefVoid =
FuncNoArgRetString'], 'E1012: type mismatch, expected func() but got func():
string')
let RefAny: func(): any
RefAny = FuncNoArgRetNumber
RefAny = FuncNoArgRetString
! CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'],
'E1012: type mismatch, expected func(): any but got func()')
! CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'],
'E1012: type mismatch, expected func(): any but got func(number)')
let RefNr: func: number
RefNr = FuncNoArgRetNumber
RefNr = FuncOneArgRetNumber
! CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'],
'E1012: type mismatch, expected func(): number but got func()')
! CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'],
'E1012: type mismatch, expected func(): number but got func(): string')
let RefStr: func: string
RefStr = FuncNoArgRetString
RefStr = FuncOneArgRetString
! CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'],
'E1012: type mismatch, expected func(): string but got func()')
! CheckDefFailure(['let RefStr: func: string', 'RefStr =
FuncNoArgRetNumber'], 'E1012: type mismatch, expected func(): string but got
func(): number')
enddef
def Test_func_type_fails()
CheckDefFailure(['let ref1: func()'], 'E704:')
! CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012:
type mismatch, expected func() but got func(): number')
! CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012:
type mismatch, expected func() but got func(number)')
! CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012:
type mismatch, expected func() but got func(number): number')
! CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012:
type mismatch, expected func(bool) but got func(bool, number)')
! CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'],
'E1012: type mismatch, expected func(?bool) but got func(bool, number)')
! CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'],
'E1012: type mismatch, expected func(...bool) but got func(bool, number)')
CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:')
CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:')
--- 976,1012 ----
let RefVoid: func: void
RefVoid = FuncNoArgNoRet
RefVoid = FuncOneArgNoRet
! CheckDefFailure(['let RefVoid: func: void', 'RefVoid =
FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func():
number')
! CheckDefFailure(['let RefVoid: func: void', 'RefVoid =
FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func():
string')
let RefAny: func(): any
RefAny = FuncNoArgRetNumber
RefAny = FuncNoArgRetString
! CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'],
'E1012: Type mismatch; expected func(): any but got func()')
! CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'],
'E1012: Type mismatch; expected func(): any but got func(number)')
let RefNr: func: number
RefNr = FuncNoArgRetNumber
RefNr = FuncOneArgRetNumber
! CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'],
'E1012: Type mismatch; expected func(...): number but got func()')
! CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'],
'E1012: Type mismatch; expected func(...): number but got func(): string')
let RefStr: func: string
RefStr = FuncNoArgRetString
RefStr = FuncOneArgRetString
! CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'],
'E1012: Type mismatch; expected func(...): string but got func()')
! CheckDefFailure(['let RefStr: func: string', 'RefStr =
FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got
func(): number')
enddef
def Test_func_type_fails()
CheckDefFailure(['let ref1: func()'], 'E704:')
! CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012:
Type mismatch; expected func() but got func(): number')
! CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012:
Type mismatch; expected func() but got func(number)')
! CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012:
Type mismatch; expected func() but got func(number): number')
! CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012:
Type mismatch; expected func(bool) but got func(bool, number)')
! CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'],
'E1012: Type mismatch; expected func(?bool) but got func(bool, number)')
! CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'],
'E1012: Type mismatch; expected func(...bool) but got func(bool, number)')
CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:')
CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:')
***************
*** 1026,1032 ****
str = FuncOneArgRetAny('yes')
str->assert_equal('yes')
! CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1012:
type mismatch, expected string but got number')
enddef
def MultiLine(
--- 1026,1032 ----
str = FuncOneArgRetAny('yes')
str->assert_equal('yes')
! CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1012:
Type mismatch; expected string but got number')
enddef
def MultiLine(
***************
*** 1204,1210 ****
return join(Ref(), ' ')
enddef
! def ExtendRef(Ref: func(string), add: string)
Ref(add)
enddef
--- 1204,1210 ----
return join(Ref(), ' ')
enddef
! def ExtendRef(Ref: func(string): list<string>, add: string)
Ref(add)
enddef
***************
*** 1408,1414 ****
enddef
def Test_wrong_dict_key_type()
! assert_fails('Wrong_dict_key_type([1, 2, 3])', 'E1029:')
enddef
def Line_continuation_in_def(dir: string = ''): string
--- 1408,1414 ----
enddef
def Test_wrong_dict_key_type()
! assert_fails('Wrong_dict_key_type([1, 2, 3])', 'E1012:')
enddef
def Line_continuation_in_def(dir: string = ''): string
***************
*** 1422,1428 ****
Line_continuation_in_def('.')->assert_equal('full')
enddef
! def Line_continuation_in_lambda(): list<number>
let x = range(97, 100)
->map({_, v -> nr2char(v)
->toupper()})
--- 1422,1428 ----
Line_continuation_in_def('.')->assert_equal('full')
enddef
! def Line_continuation_in_lambda(): list<string>
let x = range(97, 100)
->map({_, v -> nr2char(v)
->toupper()})
*** ../vim-8.2.1690/src/testdir/test_vim9_script.vim 2020-09-14
22:23:50.641827118 +0200
--- src/testdir/test_vim9_script.vim 2020-09-16 13:06:36.507113488 +0200
***************
*** 180,188 ****
CheckDefFailure(['¬ex += 3'], 'E113:')
CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
CheckDefFailure(['&ts = [7]'], 'E1012:')
! CheckDefExecFailure(['&ts = g:alist'], 'E1029: Expected number but got
list')
CheckDefFailure(['&ts = "xx"'], 'E1012:')
! CheckDefExecFailure(['&ts = g:astring'], 'E1029: Expected number but got
string')
CheckDefFailure(['&path += 3'], 'E1012:')
CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
# test freeing ISN_STOREOPT
--- 180,188 ----
CheckDefFailure(['¬ex += 3'], 'E113:')
CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
CheckDefFailure(['&ts = [7]'], 'E1012:')
! CheckDefExecFailure(['&ts = g:alist'], 'E1012: Type mismatch; expected
number but got list<number>')
CheckDefFailure(['&ts = "xx"'], 'E1012:')
! CheckDefExecFailure(['&ts = g:astring'], 'E1012: Type mismatch; expected
number but got string')
CheckDefFailure(['&path += 3'], 'E1012:')
CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
# test freeing ISN_STOREOPT
***************
*** 958,971 ****
try
# string slice returns a string, not a number
n = g:astring[3]
! catch /E1029:/
n = 77
endtry
assert_equal(77, n)
try
n = l[g:astring]
! catch /E1029:/
n = 88
endtry
assert_equal(88, n)
--- 958,971 ----
try
# string slice returns a string, not a number
n = g:astring[3]
! catch /E1012:/
n = 77
endtry
assert_equal(77, n)
try
n = l[g:astring]
! catch /E1012:/
n = 88
endtry
assert_equal(88, n)
***************
*** 1016,1022 ****
let nd: dict<any>
try
nd = {g:anumber: 1}
! catch /E1029:/
n = 266
endtry
assert_equal(266, n)
--- 1016,1022 ----
let nd: dict<any>
try
nd = {g:anumber: 1}
! catch /E1012:/
n = 266
endtry
assert_equal(266, n)
***************
*** 1030,1036 ****
try
&ts = g:astring
! catch /E1029:/
n = 288
endtry
assert_equal(288, n)
--- 1030,1036 ----
try
&ts = g:astring
! catch /E1012:/
n = 288
endtry
assert_equal(288, n)
***************
*** 3184,3189 ****
--- 3184,3207 ----
CheckScriptSuccess(lines)
enddef
+ let g:dict_number = #{one: 1, two: 2}
+
+ def Test_let_list_dict_type()
+ let ll: list<number>
+ ll = [1, 2, 2, 3, 3, 3]->uniq()
+ ll->assert_equal([1, 2, 3])
+
+ let dd: dict<number>
+ dd = g:dict_number
+ dd->assert_equal(g:dict_number)
+
+ let lines =<< trim END
+ let ll: list<number>
+ ll = [1, 2, 3]->map('"one"')
+ END
+ CheckDefExecFailure(lines, 'E1012: Type mismatch; expected list<number> but
got list<string>')
+ enddef
+
def Test_forward_declaration()
let lines =<< trim END
vim9script
*** ../vim-8.2.1690/src/version.c 2020-09-15 21:34:14.998383526 +0200
--- src/version.c 2020-09-16 15:07:25.270406129 +0200
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 1691,
/**/
--
ERIC IDLE PLAYED: THE DEAD COLLECTOR, MR BINT (A VILLAGE NE'ER-DO -WELL VERY
KEEN ON BURNING WITCHES), SIR ROBIN, THE GUARD WHO DOESN'T
HICOUGH BUT TRIES TO GET THINGS STRAIGHT, CONCORDE (SIR
LAUNCELOT'S TRUSTY STEED), ROGER THE SHRUBBER (A SHRUBBER),
BROTHER MAYNARD
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ 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/202009161322.08GDMPaA2143779%40masaka.moolenaar.net.