1
0
forked from aniani/vim

patch 9.0.1108: type error when using "any" type and adding to float

Problem:    Type error when using "any" type and adding a number to a float.
Solution:   Accept both a number and a float. (closes #11753)
This commit is contained in:
Bram Moolenaar 2022-12-29 20:56:24 +00:00
parent 73ade49c4b
commit c6951a76a5
12 changed files with 117 additions and 54 deletions

View File

@ -215,7 +215,7 @@ check_arg_type(
type_T *actual, type_T *actual,
argcontext_T *context) argcontext_T *context)
{ {
return need_type(actual, expected, return need_type(actual, expected, FALSE,
context->arg_idx - context->arg_count, context->arg_idx + 1, context->arg_idx - context->arg_count, context->arg_idx + 1,
context->arg_cctx, FALSE, FALSE); context->arg_cctx, FALSE, FALSE);
} }
@ -229,7 +229,7 @@ check_arg_type_mod(
type_T *actual, type_T *actual,
argcontext_T *context) argcontext_T *context)
{ {
if (need_type(actual, expected, if (need_type(actual, expected, FALSE,
context->arg_idx - context->arg_count, context->arg_idx + 1, context->arg_idx - context->arg_count, context->arg_idx + 1,
context->arg_cctx, FALSE, FALSE) == FAIL) context->arg_cctx, FALSE, FALSE) == FAIL)
return FAIL; return FAIL;

View File

@ -5,9 +5,9 @@ void update_script_var_block_id(char_u *name, int block_id);
int script_is_vim9(void); int script_is_vim9(void);
int script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack); int script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack);
int check_defined(char_u *p, size_t len, cctx_T *cctx, cstack_T *cstack, int is_arg); int check_defined(char_u *p, size_t len, cctx_T *cctx, cstack_T *cstack, int is_arg);
int need_type_where(type_T *actual, type_T *expected, int offset, where_T where, cctx_T *cctx, int silent, int actual_is_const); int need_type_where(type_T *actual, type_T *expected, int number_ok, int offset, where_T where, cctx_T *cctx, int silent, int actual_is_const);
int need_type(type_T *actual, type_T *expected, int offset, int arg_idx, cctx_T *cctx, int silent, int actual_is_const); int need_type(type_T *actual, type_T *expected, int number_ok, int offset, int arg_idx, cctx_T *cctx, int silent, int actual_is_const);
lvar_T *reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type); lvar_T *reserve_local(cctx_T *cctx, char_u *name, size_t len, int assign, type_T *type);
int get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx, cstack_T *cstack); int get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx, cstack_T *cstack);
imported_T *find_imported(char_u *name, size_t len, int load); imported_T *find_imported(char_u *name, size_t len, int load);
char_u *may_peek_next_line(cctx_T *cctx, char_u *arg, char_u **nextp); char_u *may_peek_next_line(cctx_T *cctx, char_u *arg, char_u **nextp);

View File

@ -15,7 +15,7 @@ int generate_COMPARE(cctx_T *cctx, exprtype_T exprtype, int ic);
int generate_CONCAT(cctx_T *cctx, int count); int generate_CONCAT(cctx_T *cctx, int count);
int generate_2BOOL(cctx_T *cctx, int invert, int offset); int generate_2BOOL(cctx_T *cctx, int invert, int offset);
int generate_COND2BOOL(cctx_T *cctx); int generate_COND2BOOL(cctx_T *cctx);
int generate_TYPECHECK(cctx_T *cctx, type_T *expected, int offset, int is_var, int argidx); int generate_TYPECHECK(cctx_T *cctx, type_T *expected, int number_ok, int offset, int is_var, int argidx);
int generate_SETTYPE(cctx_T *cctx, type_T *expected); int generate_SETTYPE(cctx_T *cctx, type_T *expected);
int generate_tv_PUSH(cctx_T *cctx, typval_T *tv); int generate_tv_PUSH(cctx_T *cctx, typval_T *tv);
int generate_PUSHNR(cctx_T *cctx, varnumber_T number); int generate_PUSHNR(cctx_T *cctx, varnumber_T number);

View File

@ -1460,6 +1460,12 @@ typedef struct {
type_T *type_decl; // declared type or equal to type_current type_T *type_decl; // declared type or equal to type_current
} type2_T; } type2_T;
#define TTFLAG_VARARGS 0x01 // func args ends with "..."
#define TTFLAG_BOOL_OK 0x02 // can be converted to bool
#define TTFLAG_NUMBER_OK 0x04 // tt_type is VAR_FLOAT, VAR_NUMBER is OK
#define TTFLAG_STATIC 0x08 // one of the static types, e.g. t_any
#define TTFLAG_CONST 0x10 // cannot be changed
typedef enum { typedef enum {
ACCESS_PRIVATE, // read/write only inside th class ACCESS_PRIVATE, // read/write only inside th class
ACCESS_READ, // read everywhere, write only inside th class ACCESS_READ, // read everywhere, write only inside th class
@ -1517,11 +1523,6 @@ struct object_S
int obj_copyID; // used by garbage collection int obj_copyID; // used by garbage collection
}; };
#define TTFLAG_VARARGS 0x01 // func args ends with "..."
#define TTFLAG_BOOL_OK 0x02 // can be converted to bool
#define TTFLAG_STATIC 0x04 // one of the static types, e.g. t_any
#define TTFLAG_CONST 0x08 // cannot be changed
/* /*
* Structure to hold an internal variable without a name. * Structure to hold an internal variable without a name.
*/ */

View File

@ -2033,6 +2033,34 @@ def Test_expr8()
v9.CheckScriptFailure(['vim9script', "var x = <number>"], 'E15:', 2) v9.CheckScriptFailure(['vim9script', "var x = <number>"], 'E15:', 2)
v9.CheckDefAndScriptFailure(["var x = <number >123"], 'E1068:', 1) v9.CheckDefAndScriptFailure(["var x = <number >123"], 'E1068:', 1)
v9.CheckDefAndScriptFailure(["var x = <number 123"], 'E1104:', 1) v9.CheckDefAndScriptFailure(["var x = <number 123"], 'E1104:', 1)
lines =<< trim END
vim9script
def Sum(v: any): float
var sum = 0.0
sum += v
return sum
enddef
const kk = 1
echo Sum(kk)
END
v9.CheckScriptSuccess(lines)
lines =<< trim END
vim9script
def Sum(v: any): float
var sum = 0.0
sum += <float>v
return sum
enddef
const kk = 1
Sum(kk)
END
v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected float but got number')
enddef enddef
" test low level expression " test low level expression

View File

@ -695,6 +695,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1108,
/**/ /**/
1107, 1107,
/**/ /**/

View File

@ -1045,7 +1045,7 @@ compile_for(char_u *arg_start, cctx_T *cctx)
if (lhs_type == &t_any) if (lhs_type == &t_any)
lhs_type = item_type; lhs_type = item_type;
else if (item_type != &t_unknown else if (item_type != &t_unknown
&& need_type_where(item_type, lhs_type, -1, && need_type_where(item_type, lhs_type, FALSE, -1,
where, cctx, FALSE, FALSE) == FAIL) where, cctx, FALSE, FALSE) == FAIL)
goto failed; goto failed;
var_lvar = reserve_local(cctx, arg, varlen, ASSIGN_FINAL, var_lvar = reserve_local(cctx, arg, varlen, ASSIGN_FINAL,
@ -2469,7 +2469,7 @@ compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
if (compile_assign_lhs(arg, lhs, CMD_redir, if (compile_assign_lhs(arg, lhs, CMD_redir,
FALSE, FALSE, FALSE, 1, cctx) == FAIL) FALSE, FALSE, FALSE, 1, cctx) == FAIL)
return NULL; return NULL;
if (need_type(&t_string, lhs->lhs_member_type, if (need_type(&t_string, lhs->lhs_member_type, FALSE,
-1, 0, cctx, FALSE, FALSE) == FAIL) -1, 0, cctx, FALSE, FALSE) == FAIL)
return NULL; return NULL;
if (cctx->ctx_skip == SKIP_YES) if (cctx->ctx_skip == SKIP_YES)
@ -2551,7 +2551,7 @@ compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
int save_flags = cmdmod.cmod_flags; int save_flags = cmdmod.cmod_flags;
generate_LEGACY_EVAL(cctx, p); generate_LEGACY_EVAL(cctx, p);
if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, -1, if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, FALSE, -1,
0, cctx, FALSE, FALSE) == FAIL) 0, cctx, FALSE, FALSE) == FAIL)
return NULL; return NULL;
cmdmod.cmod_flags |= CMOD_LEGACY; cmdmod.cmod_flags |= CMOD_LEGACY;
@ -2580,8 +2580,8 @@ compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
} }
else else
{ {
if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, FALSE,
0, cctx, FALSE, FALSE) == FAIL) -1, 0, cctx, FALSE, FALSE) == FAIL)
return NULL; return NULL;
} }
} }

View File

@ -451,6 +451,7 @@ use_typecheck(type_T *actual, type_T *expected)
need_type_where( need_type_where(
type_T *actual, type_T *actual,
type_T *expected, type_T *expected,
int number_ok, // expect VAR_FLOAT but VAR_NUMBER is OK
int offset, int offset,
where_T where, where_T where,
cctx_T *cctx, cctx_T *cctx,
@ -480,7 +481,7 @@ need_type_where(
// If the actual type can be the expected type add a runtime check. // If the actual type can be the expected type add a runtime check.
if (!actual_is_const && ret == MAYBE && use_typecheck(actual, expected)) if (!actual_is_const && ret == MAYBE && use_typecheck(actual, expected))
{ {
generate_TYPECHECK(cctx, expected, offset, generate_TYPECHECK(cctx, expected, number_ok, offset,
where.wt_variable, where.wt_index); where.wt_variable, where.wt_index);
return OK; return OK;
} }
@ -494,6 +495,7 @@ need_type_where(
need_type( need_type(
type_T *actual, type_T *actual,
type_T *expected, type_T *expected,
int number_ok, // when expected is float number is also OK
int offset, int offset,
int arg_idx, int arg_idx,
cctx_T *cctx, cctx_T *cctx,
@ -503,7 +505,7 @@ need_type(
where_T where = WHERE_INIT; where_T where = WHERE_INIT;
where.wt_index = arg_idx; where.wt_index = arg_idx;
return need_type_where(actual, expected, offset, where, return need_type_where(actual, expected, number_ok, offset, where,
cctx, silent, actual_is_const); cctx, silent, actual_is_const);
} }
@ -2000,8 +2002,8 @@ compile_load_lhs(
// now we can properly check the type // now we can properly check the type
if (rhs_type != NULL && lhs->lhs_type->tt_member != NULL if (rhs_type != NULL && lhs->lhs_type->tt_member != NULL
&& rhs_type != &t_void && rhs_type != &t_void
&& need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx, && need_type(rhs_type, lhs->lhs_type->tt_member, FALSE,
FALSE, FALSE) == FAIL) -2, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL; return FAIL;
} }
else else
@ -2090,13 +2092,13 @@ compile_assign_unlet(
if (range) if (range)
{ {
type = get_type_on_stack(cctx, 1); type = get_type_on_stack(cctx, 1);
if (need_type(type, &t_number, if (need_type(type, &t_number, FALSE,
-2, 0, cctx, FALSE, FALSE) == FAIL) -2, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL; return FAIL;
} }
type = get_type_on_stack(cctx, 0); type = get_type_on_stack(cctx, 0);
if ((dest_type != VAR_BLOB && type->tt_type != VAR_SPECIAL) if ((dest_type != VAR_BLOB && type->tt_type != VAR_SPECIAL)
&& need_type(type, &t_number, && need_type(type, &t_number, FALSE,
-1, 0, cctx, FALSE, FALSE) == FAIL) -1, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL; return FAIL;
} }
@ -2357,7 +2359,7 @@ compile_assignment(
emsg(_(e_cannot_use_void_value)); emsg(_(e_cannot_use_void_value));
goto theend; goto theend;
} }
if (need_type(stacktype, &t_list_any, -1, 0, cctx, if (need_type(stacktype, &t_list_any, FALSE, -1, 0, cctx,
FALSE, FALSE) == FAIL) FALSE, FALSE) == FAIL)
goto theend; goto theend;
// If a constant list was used we can check the length right here. // If a constant list was used we can check the length right here.
@ -2424,7 +2426,7 @@ compile_assignment(
{ {
SOURCING_LNUM = start_lnum; SOURCING_LNUM = start_lnum;
if (lhs.lhs_has_type if (lhs.lhs_has_type
&& need_type(&t_list_string, lhs.lhs_type, && need_type(&t_list_string, lhs.lhs_type, FALSE,
-1, 0, cctx, FALSE, FALSE) == FAIL) -1, 0, cctx, FALSE, FALSE) == FAIL)
goto theend; goto theend;
} }
@ -2549,8 +2551,8 @@ compile_assignment(
&& !has_list_index(var_start + lhs.lhs_varlen, && !has_list_index(var_start + lhs.lhs_varlen,
cctx)) cctx))
use_type = lhs.lhs_member_type; use_type = lhs.lhs_member_type;
if (need_type_where(rhs_type, use_type, -1, where, if (need_type_where(rhs_type, use_type, FALSE, -1,
cctx, FALSE, is_const) == FAIL) where, cctx, FALSE, is_const) == FAIL)
goto theend; goto theend;
} }
} }
@ -2565,7 +2567,7 @@ compile_assignment(
|| lhs_type == &t_float) || lhs_type == &t_float)
&& rhs_type->tt_type == VAR_NUMBER) && rhs_type->tt_type == VAR_NUMBER)
lhs_type = &t_number; lhs_type = &t_number;
if (*p != '=' && need_type(rhs_type, lhs_type, if (*p != '=' && need_type(rhs_type, lhs_type, FALSE,
-1, 0, cctx, FALSE, FALSE) == FAIL) -1, 0, cctx, FALSE, FALSE) == FAIL)
goto theend; goto theend;
} }
@ -2622,8 +2624,8 @@ compile_assignment(
if ( if (
// If variable is float operation with number is OK. // If variable is float operation with number is OK.
!(expected == &t_float && (stacktype == &t_number !(expected == &t_float && (stacktype == &t_number
|| stacktype == &t_number_bool)) && || stacktype == &t_number_bool))
need_type(stacktype, expected, -1, 0, cctx, && need_type(stacktype, expected, TRUE, -1, 0, cctx,
FALSE, FALSE) == FAIL) FALSE, FALSE) == FAIL)
goto theend; goto theend;
} }
@ -3104,7 +3106,7 @@ compile_def_function(
ufunc->uf_arg_types[arg_idx] = val_type; ufunc->uf_arg_types[arg_idx] = val_type;
} }
else if (need_type_where(val_type, ufunc->uf_arg_types[arg_idx], else if (need_type_where(val_type, ufunc->uf_arg_types[arg_idx],
-1, where, &cctx, FALSE, FALSE) == FAIL) FALSE, -1, where, &cctx, FALSE, FALSE) == FAIL)
goto erret; goto erret;
if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL) if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)

View File

@ -6872,16 +6872,23 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
case ISN_CHECKTYPE: case ISN_CHECKTYPE:
{ {
checktype_T *ct = &iptr->isn_arg.type; checktype_T *ct = &iptr->isn_arg.type;
char *tofree; char *tofree = NULL;
char *typename;
if (ct->ct_type->tt_type == VAR_FLOAT
&& (ct->ct_type->tt_flags & TTFLAG_NUMBER_OK))
typename = "float|number";
else
typename = type_name(ct->ct_type, &tofree);
if (ct->ct_arg_idx == 0) if (ct->ct_arg_idx == 0)
smsg("%s%4d CHECKTYPE %s stack[%d]", pfx, current, smsg("%s%4d CHECKTYPE %s stack[%d]", pfx, current,
type_name(ct->ct_type, &tofree), typename,
(int)ct->ct_off); (int)ct->ct_off);
else else
smsg("%s%4d CHECKTYPE %s stack[%d] %s %d", smsg("%s%4d CHECKTYPE %s stack[%d] %s %d",
pfx, current, pfx, current,
type_name(ct->ct_type, &tofree), typename,
(int)ct->ct_off, (int)ct->ct_off,
ct->ct_is_var ? "var": "arg", ct->ct_is_var ? "var": "arg",
(int)ct->ct_arg_idx); (int)ct->ct_arg_idx);

View File

@ -99,13 +99,14 @@ compile_member(int is_slice, int *keeping_dict, cctx_T *cctx)
vartype = VAR_DICT; vartype = VAR_DICT;
if (vartype == VAR_STRING || vartype == VAR_LIST || vartype == VAR_BLOB) if (vartype == VAR_STRING || vartype == VAR_LIST || vartype == VAR_BLOB)
{ {
if (need_type(idxtype, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL) if (need_type(idxtype, &t_number, FALSE,
-1, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL; return FAIL;
if (is_slice) if (is_slice)
{ {
idxtype = get_type_on_stack(cctx, 1); idxtype = get_type_on_stack(cctx, 1);
if (need_type(idxtype, &t_number, -2, 0, cctx, if (need_type(idxtype, &t_number, FALSE,
FALSE, FALSE) == FAIL) -2, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL; return FAIL;
} }
} }
@ -135,8 +136,8 @@ compile_member(int is_slice, int *keeping_dict, cctx_T *cctx)
} }
else else
{ {
if (need_type(typep->type_curr, &t_dict_any, -2, 0, cctx, if (need_type(typep->type_curr, &t_dict_any, FALSE,
FALSE, FALSE) == FAIL) -2, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL; return FAIL;
typep->type_curr = &t_any; typep->type_curr = &t_any;
typep->type_decl = &t_any; typep->type_decl = &t_any;
@ -1725,7 +1726,7 @@ bool_on_stack(cctx_T *cctx)
// This requires a runtime type check. // This requires a runtime type check.
return generate_COND2BOOL(cctx); return generate_COND2BOOL(cctx);
return need_type(type, &t_bool, -1, 0, cctx, FALSE, FALSE); return need_type(type, &t_bool, FALSE, -1, 0, cctx, FALSE, FALSE);
} }
/* /*
@ -1759,7 +1760,7 @@ compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
{ {
type_T *type = get_type_on_stack(cctx, 0); type_T *type = get_type_on_stack(cctx, 0);
if (type->tt_type != VAR_FLOAT && need_type(type, &t_number, if (type->tt_type != VAR_FLOAT && need_type(type, &t_number,
-1, 0, cctx, FALSE, FALSE) == FAIL) FALSE, -1, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL; return FAIL;
// only '-' has an effect, for '+' we only check the type // only '-' has an effect, for '+' we only check the type
@ -2517,8 +2518,8 @@ compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
actual = get_type_on_stack(cctx, 0); actual = get_type_on_stack(cctx, 0);
if (check_type_maybe(want_type, actual, FALSE, where) != OK) if (check_type_maybe(want_type, actual, FALSE, where) != OK)
{ {
if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) if (need_type(actual, want_type, FALSE,
== FAIL) -1, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL; return FAIL;
} }
} }
@ -2759,7 +2760,7 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{ {
type_T *t = get_type_on_stack(cctx, 0); type_T *t = get_type_on_stack(cctx, 0);
if (need_type(t, &t_number, 0, 0, cctx, FALSE, FALSE) == FAIL) if (need_type(t, &t_number, FALSE, 0, 0, cctx, FALSE, FALSE) == FAIL)
{ {
emsg(_(e_bitshift_ops_must_be_number)); emsg(_(e_bitshift_ops_must_be_number));
return FAIL; return FAIL;
@ -2814,8 +2815,8 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
} }
else else
{ {
if (need_type(get_type_on_stack(cctx, 0), &t_number, 0, 0, cctx, if (need_type(get_type_on_stack(cctx, 0), &t_number, FALSE,
FALSE, FALSE) == FAIL) 0, 0, cctx, FALSE, FALSE) == FAIL)
{ {
emsg(_(e_bitshift_ops_must_be_number)); emsg(_(e_bitshift_ops_must_be_number));
return FAIL; return FAIL;

View File

@ -576,6 +576,7 @@ generate_COND2BOOL(cctx_T *cctx)
generate_TYPECHECK( generate_TYPECHECK(
cctx_T *cctx, cctx_T *cctx,
type_T *expected, type_T *expected,
int number_ok, // add TTFLAG_NUMBER_OK flag
int offset, int offset,
int is_var, int is_var,
int argidx) int argidx)
@ -585,7 +586,21 @@ generate_TYPECHECK(
RETURN_OK_IF_SKIP(cctx); RETURN_OK_IF_SKIP(cctx);
if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL) if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
return FAIL; return FAIL;
isn->isn_arg.type.ct_type = alloc_type(expected); type_T *tt;
if (expected->tt_type == VAR_FLOAT && number_ok)
{
// always allocate, also for static types
tt = ALLOC_ONE(type_T);
if (tt != NULL)
{
*tt = *expected;
tt->tt_flags |= TTFLAG_NUMBER_OK;
}
}
else
tt = alloc_type(expected);
isn->isn_arg.type.ct_type = tt;
isn->isn_arg.type.ct_off = (int8_T)offset; isn->isn_arg.type.ct_off = (int8_T)offset;
isn->isn_arg.type.ct_is_var = is_var; isn->isn_arg.type.ct_is_var = is_var;
isn->isn_arg.type.ct_arg_idx = (int8_T)argidx; isn->isn_arg.type.ct_arg_idx = (int8_T)argidx;
@ -1601,7 +1616,7 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
if (maptype != NULL && maptype[0].type_decl->tt_member != NULL if (maptype != NULL && maptype[0].type_decl->tt_member != NULL
&& maptype[0].type_decl->tt_member != &t_any) && maptype[0].type_decl->tt_member != &t_any)
// Check that map() didn't change the item types. // Check that map() didn't change the item types.
generate_TYPECHECK(cctx, maptype[0].type_decl, -1, FALSE, 1); generate_TYPECHECK(cctx, maptype[0].type_decl, FALSE, -1, FALSE, 1);
return OK; return OK;
} }
@ -1625,7 +1640,7 @@ generate_LISTAPPEND(cctx_T *cctx)
return FAIL; return FAIL;
item_type = get_type_on_stack(cctx, 0); item_type = get_type_on_stack(cctx, 0);
expected = list_type->tt_member; expected = list_type->tt_member;
if (need_type(item_type, expected, -1, 0, cctx, FALSE, FALSE) == FAIL) if (need_type(item_type, expected, FALSE, -1, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL; return FAIL;
if (generate_instr(cctx, ISN_LISTAPPEND) == NULL) if (generate_instr(cctx, ISN_LISTAPPEND) == NULL)
@ -1648,7 +1663,8 @@ generate_BLOBAPPEND(cctx_T *cctx)
if (arg_type_modifiable(get_decl_type_on_stack(cctx, 1), 1) == FAIL) if (arg_type_modifiable(get_decl_type_on_stack(cctx, 1), 1) == FAIL)
return FAIL; return FAIL;
item_type = get_type_on_stack(cctx, 0); item_type = get_type_on_stack(cctx, 0);
if (need_type(item_type, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL) if (need_type(item_type, &t_number, FALSE,
-1, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL; return FAIL;
if (generate_instr(cctx, ISN_BLOBAPPEND) == NULL) if (generate_instr(cctx, ISN_BLOBAPPEND) == NULL)
@ -1713,8 +1729,8 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
expected = &t_any; expected = &t_any;
else else
expected = ufunc->uf_va_type->tt_member; expected = ufunc->uf_va_type->tt_member;
if (need_type(actual, expected, -argcount + i, i + 1, cctx, if (need_type(actual, expected, FALSE,
TRUE, FALSE) == FAIL) -argcount + i, i + 1, cctx, TRUE, FALSE) == FAIL)
{ {
arg_type_mismatch(expected, actual, i + 1); arg_type_mismatch(expected, actual, i + 1);
return FAIL; return FAIL;
@ -1821,8 +1837,8 @@ check_func_args_from_type(
expected = &t_any; expected = &t_any;
else else
expected = type->tt_args[i]; expected = type->tt_args[i];
if (need_type(actual, expected, offset, i + 1, if (need_type(actual, expected, FALSE,
cctx, TRUE, FALSE) == FAIL) offset, i + 1, cctx, TRUE, FALSE) == FAIL)
{ {
arg_type_mismatch(expected, actual, i + 1); arg_type_mismatch(expected, actual, i + 1);
return FAIL; return FAIL;

View File

@ -813,6 +813,11 @@ check_type_maybe(
&& (actual->tt_flags & TTFLAG_BOOL_OK)) && (actual->tt_flags & TTFLAG_BOOL_OK))
// Using number 0 or 1 for bool is OK. // Using number 0 or 1 for bool is OK.
return OK; return OK;
if (expected->tt_type == VAR_FLOAT
&& (expected->tt_flags & TTFLAG_NUMBER_OK)
&& actual->tt_type == VAR_NUMBER)
// Using number where float is expected is OK here.
return OK;
if (give_msg) if (give_msg)
type_mismatch_where(expected, actual, where); type_mismatch_where(expected, actual, where);
return FAIL; return FAIL;
@ -848,7 +853,8 @@ check_type_maybe(
{ {
int i; int i;
for (i = 0; i < expected->tt_argcount && i < actual->tt_argcount; ++i) for (i = 0; i < expected->tt_argcount
&& i < actual->tt_argcount; ++i)
// Allow for using "any" argument type, lambda's have them. // Allow for using "any" argument type, lambda's have them.
if (actual->tt_args[i] != &t_any && check_type( if (actual->tt_args[i] != &t_any && check_type(
expected->tt_args[i], actual->tt_args[i], FALSE, expected->tt_args[i], actual->tt_args[i], FALSE,