0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

patch 8.2.1691: Vim9: list<any> is not accepted where list<number> is expected

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)
This commit is contained in:
Bram Moolenaar
2020-09-16 15:22:00 +02:00
parent 8b51b7f0f1
commit 5e65423077
13 changed files with 253 additions and 149 deletions

View File

@@ -704,7 +704,10 @@ generate_2BOOL(cctx_T *cctx, int invert)
}
static int
generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
generate_TYPECHECK(
cctx_T *cctx,
type_T *expected,
int offset)
{
isn_T *isn;
garray_T *stack = &cctx->ctx_type_stack;
@@ -712,19 +715,18 @@ generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
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_type = alloc_type(expected);
isn->isn_arg.type.ct_off = offset;
// type becomes vartype
((type_T **)stack->ga_data)[stack->ga_len + offset] = vartype;
// type becomes expected
((type_T **)stack->ga_data)[stack->ga_len + offset] = expected;
return OK;
}
/*
* Check that
* - "actual" is "expected" type or
* - "actual" matches "expected" type or
* - "actual" is a type that can be "expected" type: add a runtime check; or
* - return FAIL.
*/
@@ -747,17 +749,29 @@ need_type(
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 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))
{
if (!silent)
type_mismatch(expected, actual);
return FAIL;
generate_TYPECHECK(cctx, expected, offset);
return OK;
}
generate_TYPECHECK(cctx, expected, offset);
return OK;
if (!silent)
type_mismatch(expected, actual);
return FAIL;
}
/*
@@ -776,7 +790,7 @@ generate_PUSHNR(cctx_T *cctx, varnumber_T number)
if (number == 0 || number == 1)
{
type_T *type = alloc_type(cctx->ctx_type_list);
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,7 +4051,7 @@ compile_and_or(
typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
if (*typep != &t_bool)
{
type_T *type = alloc_type(cctx->ctx_type_list);
type_T *type = get_type_ptr(cctx->ctx_type_list);
if (type != NULL)
{
@@ -7290,6 +7304,10 @@ delete_instr(isn_T *isn)
}
break;
case ISN_CHECKTYPE:
free_type(isn->isn_arg.type.ct_type);
break;
case ISN_2BOOL:
case ISN_2STRING:
case ISN_2STRING_ANY:
@@ -7301,7 +7319,6 @@ delete_instr(isn_T *isn)
case ISN_CATCH:
case ISN_CHECKLEN:
case ISN_CHECKNR:
case ISN_CHECKTYPE:
case ISN_COMPAREANY:
case ISN_COMPAREBLOB:
case ISN_COMPAREBOOL: