diff options
-rw-r--r-- | src/dict.c | 3 | ||||
-rw-r--r-- | src/errors.h | 2 | ||||
-rw-r--r-- | src/eval.c | 12 | ||||
-rw-r--r-- | src/evalvars.c | 34 | ||||
-rw-r--r-- | src/list.c | 20 | ||||
-rw-r--r-- | src/proto/eval.pro | 2 | ||||
-rw-r--r-- | src/proto/evalvars.pro | 2 | ||||
-rw-r--r-- | src/proto/vim9script.pro | 2 | ||||
-rw-r--r-- | src/proto/vim9type.pro | 8 | ||||
-rw-r--r-- | src/structs.h | 7 | ||||
-rw-r--r-- | src/testdir/test_vim9_assign.vim | 8 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 16 | ||||
-rw-r--r-- | src/vim9execute.c | 24 | ||||
-rw-r--r-- | src/vim9script.c | 12 | ||||
-rw-r--r-- | src/vim9type.c | 51 |
16 files changed, 146 insertions, 59 deletions
diff --git a/src/dict.c b/src/dict.c index b36b2bf6dd..922da473ce 100644 --- a/src/dict.c +++ b/src/dict.c @@ -1089,7 +1089,8 @@ dict_extend(dict_T *d1, dict_T *d2, char_u *action) } if (type != NULL - && check_typval_type(type, &HI2DI(hi2)->di_tv, 0) == FAIL) + && check_typval_arg_type(type, &HI2DI(hi2)->di_tv, 0) + == FAIL) break; if (di1 == NULL) diff --git a/src/errors.h b/src/errors.h index 39eca7e943..927e1ffde9 100644 --- a/src/errors.h +++ b/src/errors.h @@ -361,3 +361,5 @@ EXTERN char e_cannot_json_encode_str[] INIT(= N_("E1161: Cannot json encode a %s")); EXTERN char e_register_name_must_be_one_char_str[] INIT(= N_("E1162: Register name must be one character: %s")); +EXTERN char e_variable_nr_type_mismatch_expected_str_but_got_str[] + INIT(= N_("E1163: Variable %d: type mismatch, expected %s but got %s")); diff --git a/src/eval.c b/src/eval.c index 8b942e8e21..aae6ee8ffa 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1299,8 +1299,9 @@ set_var_lval( char_u *endp, typval_T *rettv, int copy, - int flags, // ASSIGN_CONST, ASSIGN_NO_DECL - char_u *op) + int flags, // ASSIGN_CONST, ASSIGN_NO_DECL + char_u *op, + int var_idx) // index for "let [a, b] = list" { int cc; listitem_T *ri; @@ -1390,9 +1391,10 @@ set_var_lval( else { if (lp->ll_type != NULL - && check_typval_type(lp->ll_type, rettv, 0) == FAIL) + && check_typval_arg_type(lp->ll_type, rettv, 0) == FAIL) return; - set_var_const(lp->ll_name, lp->ll_type, rettv, copy, flags); + set_var_const(lp->ll_name, lp->ll_type, rettv, copy, + flags, var_idx); } *endp = cc; } @@ -1471,7 +1473,7 @@ set_var_lval( } if (lp->ll_valtype != NULL - && check_typval_type(lp->ll_valtype, rettv, 0) == FAIL) + && check_typval_arg_type(lp->ll_valtype, rettv, 0) == FAIL) return; if (lp->ll_newkey != NULL) diff --git a/src/evalvars.c b/src/evalvars.c index b6a6927d60..57a881a289 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -173,7 +173,7 @@ static void list_buf_vars(int *first); static void list_win_vars(int *first); static void list_tab_vars(int *first); static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first); -static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int flags, char_u *endchars, char_u *op); +static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int flags, char_u *endchars, char_u *op, int var_idx); static int do_unlet_var(lval_T *lp, char_u *name_end, exarg_T *eap, int deep, void *cookie); static int do_lock_var(lval_T *lp, char_u *name_end, exarg_T *eap, int deep, void *cookie); static void list_one_var(dictitem_T *v, char *prefix, int *first); @@ -929,13 +929,14 @@ ex_let_vars( char_u *arg = arg_start; list_T *l; int i; + int var_idx = 0; listitem_T *item; typval_T ltv; if (*arg != '[') { // ":let var = expr" or ":for var in list" - if (ex_let_one(arg, tv, copy, flags, op, op) == NULL) + if (ex_let_one(arg, tv, copy, flags, op, op, var_idx) == NULL) return FAIL; return OK; } @@ -964,7 +965,9 @@ ex_let_vars( while (*arg != ']') { arg = skipwhite(arg + 1); - arg = ex_let_one(arg, &item->li_tv, TRUE, flags, (char_u *)",;]", op); + ++var_idx; + arg = ex_let_one(arg, &item->li_tv, TRUE, flags, (char_u *)",;]", + op, var_idx); item = item->li_next; if (arg == NULL) return FAIL; @@ -987,9 +990,10 @@ ex_let_vars( ltv.v_lock = 0; ltv.vval.v_list = l; l->lv_refcount = 1; + ++var_idx; arg = ex_let_one(skipwhite(arg + 1), <v, FALSE, flags, - (char_u *)"]", op); + (char_u *)"]", op, var_idx); clear_tv(<v); if (arg == NULL) return FAIL; @@ -1284,7 +1288,8 @@ ex_let_one( int copy, // copy value from "tv" int flags, // ASSIGN_CONST, ASSIGN_FINAL, etc. char_u *endchars, // valid chars after variable name or NULL - char_u *op) // "+", "-", "." or NULL + char_u *op, // "+", "-", "." or NULL + int var_idx) // variable index for "let [a, b] = list" { int c1; char_u *name; @@ -1508,7 +1513,7 @@ ex_let_one( emsg(_(e_letunexp)); else { - set_var_lval(&lv, p, tv, copy, flags, op); + set_var_lval(&lv, p, tv, copy, flags, op, var_idx); arg_end = p; } } @@ -3075,7 +3080,7 @@ set_var( typval_T *tv, int copy) // make copy of value in "tv" { - set_var_const(name, NULL, tv, copy, ASSIGN_DECL); + set_var_const(name, NULL, tv, copy, ASSIGN_DECL, 0); } /* @@ -3089,7 +3094,8 @@ set_var_const( type_T *type, typval_T *tv_arg, int copy, // make copy of value in "tv" - int flags) // ASSIGN_CONST, ASSIGN_FINAL, etc. + int flags, // ASSIGN_CONST, ASSIGN_FINAL, etc. + int var_idx) // index for ":let [a, b] = list" { typval_T *tv = tv_arg; typval_T bool_tv; @@ -3148,6 +3154,8 @@ set_var_const( if (is_script_local && vim9script) { + where_T where; + if ((flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0) { semsg(_(e_redefining_script_item_str), name); @@ -3155,7 +3163,9 @@ set_var_const( } // check the type and adjust to bool if needed - if (check_script_var_type(&di->di_tv, tv, name) == FAIL) + where.wt_index = var_idx; + where.wt_variable = TRUE; + if (check_script_var_type(&di->di_tv, tv, name, where) == FAIL) goto failed; } @@ -3719,10 +3729,10 @@ var_redir_start(char_u *name, int append) tv.vval.v_string = (char_u *)""; if (append) set_var_lval(redir_lval, redir_endp, &tv, TRUE, - ASSIGN_NO_DECL, (char_u *)"."); + ASSIGN_NO_DECL, (char_u *)".", 0); else set_var_lval(redir_lval, redir_endp, &tv, TRUE, - ASSIGN_NO_DECL, (char_u *)"="); + ASSIGN_NO_DECL, (char_u *)"=", 0); clear_lval(redir_lval); if (called_emsg > called_emsg_before) { @@ -3794,7 +3804,7 @@ var_redir_stop(void) FALSE, FALSE, 0, FNE_CHECK_START); if (redir_endp != NULL && redir_lval->ll_name != NULL) set_var_lval(redir_lval, redir_endp, &tv, FALSE, 0, - (char_u *)"."); + (char_u *)".", 0); clear_lval(redir_lval); } diff --git a/src/list.c b/src/list.c index 4d33aa6e08..484ce74c98 100644 --- a/src/list.c +++ b/src/list.c @@ -698,7 +698,7 @@ list_insert_tv(list_T *l, typval_T *tv, listitem_T *item) listitem_T *ni; if (l->lv_type != NULL && l->lv_type->tt_member != NULL - && check_typval_type(l->lv_type->tt_member, tv, 0) == FAIL) + && check_typval_arg_type(l->lv_type->tt_member, tv, 0) == FAIL) return FAIL; ni = listitem_alloc(); if (ni == NULL) @@ -2135,8 +2135,8 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap) } if (filtermap == FILTERMAP_MAP) { - if (type != NULL && check_typval_type(type->tt_member, - &newtv, 0) == FAIL) + if (type != NULL && check_typval_arg_type( + type->tt_member, &newtv, 0) == FAIL) { clear_tv(&newtv); break; @@ -2270,8 +2270,8 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap) if (filtermap != FILTERMAP_FILTER) { if (filtermap == FILTERMAP_MAP && type != NULL - && check_typval_type(type->tt_member, - &newtv, 0) == FAIL) + && check_typval_arg_type( + type->tt_member, &newtv, 0) == FAIL) { clear_tv(&newtv); break; @@ -2314,8 +2314,8 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap) } if (filtermap == FILTERMAP_MAP) { - if (type != NULL && check_typval_type(type->tt_member, - &newtv, 0) == FAIL) + if (type != NULL && check_typval_arg_type( + type->tt_member, &newtv, 0) == FAIL) { clear_tv(&newtv); break; @@ -2584,7 +2584,8 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new) } else item = NULL; - if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL) + if (type != NULL && check_typval_arg_type( + type, &argvars[1], 2) == FAIL) goto theend; list_extend(l1, l2, item); @@ -2641,7 +2642,8 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new) else action = (char_u *)"force"; - if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL) + if (type != NULL && check_typval_arg_type( + type, &argvars[1], 2) == FAIL) goto theend; dict_extend(d1, d2, action); diff --git a/src/proto/eval.pro b/src/proto/eval.pro index 07b11b25a5..03630c4b03 100644 --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -25,7 +25,7 @@ void *call_func_retlist(char_u *func, int argc, typval_T *argv); int eval_foldexpr(char_u *arg, int *cp); char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags); void clear_lval(lval_T *lp); -void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int flags, char_u *op); +void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int flags, char_u *op, int var_idx); void *eval_for_line(char_u *arg, int *errp, exarg_T *eap, evalarg_T *evalarg); void skip_for_lines(void *fi_void, evalarg_T *evalarg); int next_for_item(void *fi_void, char_u *arg); diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro index 0861a8866a..ce160d7de5 100644 --- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -70,7 +70,7 @@ void vars_clear(hashtab_T *ht); void vars_clear_ext(hashtab_T *ht, int free_val); void delete_var(hashtab_T *ht, hashitem_T *hi); void set_var(char_u *name, typval_T *tv, int copy); -void set_var_const(char_u *name, type_T *type, typval_T *tv_arg, int copy, int flags); +void set_var_const(char_u *name, type_T *type, typval_T *tv_arg, int copy, int flags, int var_idx); int var_check_permission(dictitem_T *di, char_u *name); int var_check_ro(int flags, char_u *name, int use_gettext); int var_check_lock(int flags, char_u *name, int use_gettext); diff --git a/src/proto/vim9script.pro b/src/proto/vim9script.pro index 2a63b8b274..c6493519cf 100644 --- a/src/proto/vim9script.pro +++ b/src/proto/vim9script.pro @@ -14,5 +14,5 @@ void update_vim9_script_var(int create, dictitem_T *di, int flags, typval_T *tv, void hide_script_var(scriptitem_T *si, int idx, int func_defined); void free_all_script_vars(scriptitem_T *si); svar_T *find_typval_in_script(typval_T *dest); -int check_script_var_type(typval_T *dest, typval_T *value, char_u *name); +int check_script_var_type(typval_T *dest, typval_T *value, char_u *name, where_T where); /* vim: set ft=c : */ diff --git a/src/proto/vim9type.pro b/src/proto/vim9type.pro index f7b472c9e6..35da1fe72e 100644 --- a/src/proto/vim9type.pro +++ b/src/proto/vim9type.pro @@ -11,10 +11,12 @@ int func_type_add_arg_types(type_T *functype, int argcount, garray_T *type_gap); int need_convert_to_bool(type_T *type, typval_T *tv); type_T *typval2type(typval_T *tv, garray_T *type_gap); type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap); -int check_typval_type(type_T *expected, typval_T *actual_tv, int argidx); +int check_typval_arg_type(type_T *expected, typval_T *actual_tv, int arg_idx); +int check_typval_type(type_T *expected, typval_T *actual_tv, where_T where); void type_mismatch(type_T *expected, type_T *actual); -void arg_type_mismatch(type_T *expected, type_T *actual, int argidx); -int check_type(type_T *expected, type_T *actual, int give_msg, int argidx); +void arg_type_mismatch(type_T *expected, type_T *actual, int arg_idx); +void type_mismatch_where(type_T *expected, type_T *actual, where_T where); +int check_type(type_T *expected, type_T *actual, int give_msg, where_T where); int check_argument_types(type_T *type, typval_T *argvars, int argcount, char_u *name); char_u *skip_type(char_u *start, int optional); type_T *parse_type(char_u **arg, garray_T *type_gap, int give_error); diff --git a/src/structs.h b/src/structs.h index 8d86d11b18..550e53a2bc 100644 --- a/src/structs.h +++ b/src/structs.h @@ -4387,3 +4387,10 @@ typedef enum { MAGIC_ON = 3, // "\m" or 'magic' MAGIC_ALL = 4 // "\v" very magic } magic_T; + +// Struct used to pass to error messages about where the error happened. +typedef struct { + char wt_index; // argument or variable index, 0 means unknown + char wt_variable; // "variable" when TRUE, "argument" otherwise +} where_T; + diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 55beffa958..7599df2c54 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -284,6 +284,14 @@ def Test_assign_unpack() [v1, v2] = '' END CheckDefFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 3) + + lines =<< trim END + g:values = [false, 0] + var x: bool + var y: string + [x, y] = g:values + END + CheckDefExecAndScriptFailure(lines, 'E1163: Variable 2: type mismatch, expected string but got number') enddef def Test_assign_linebreak() diff --git a/src/version.c b/src/version.c index 8918ec5fca..1037c18412 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2501, +/**/ 2500, /**/ 2499, diff --git a/src/vim9compile.c b/src/vim9compile.c index 512f7246c2..4dfb42f352 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -893,6 +893,8 @@ need_type( int silent, int actual_is_const) { + where_T where; + if (expected == &t_bool && actual != &t_bool && (actual->tt_flags & TTFLAG_BOOL_OK)) { @@ -902,7 +904,9 @@ need_type( return OK; } - if (check_type(expected, actual, FALSE, arg_idx) == OK) + where.wt_index = arg_idx; + where.wt_variable = FALSE; + if (check_type(expected, actual, FALSE, where) == OK) return OK; // If the actual type can be the expected type add a runtime check. @@ -4287,10 +4291,13 @@ compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) { garray_T *stack = &cctx->ctx_type_stack; type_T *actual; + where_T where; generate_ppconst(cctx, ppconst); actual = ((type_T **)stack->ga_data)[stack->ga_len - 1]; - if (check_type(want_type, actual, FALSE, 0) == FAIL) + where.wt_index = 0; + where.wt_variable = FALSE; + if (check_type(want_type, actual, FALSE, where) == FAIL) { if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) == FAIL) return FAIL; @@ -8078,6 +8085,7 @@ compile_def_function( garray_T *stack = &cctx.ctx_type_stack; type_T *val_type; int arg_idx = first_def_arg + i; + where_T where; ufunc->uf_def_arg_idx[i] = instr->ga_len; arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i]; @@ -8088,13 +8096,15 @@ compile_def_function( // Otherwise check that the default value type matches the // specified type. val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; + where.wt_index = arg_idx + 1; + where.wt_variable = FALSE; if (ufunc->uf_arg_types[arg_idx] == &t_unknown) { did_set_arg_type = TRUE; ufunc->uf_arg_types[arg_idx] = val_type; } else if (check_type(ufunc->uf_arg_types[arg_idx], val_type, - TRUE, arg_idx + 1) == FAIL) + TRUE, where) == FAIL) goto erret; if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL) diff --git a/src/vim9execute.c b/src/vim9execute.c index 8728088c08..6d462eaf1d 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -851,7 +851,7 @@ store_var(char_u *name, typval_T *tv) funccal_entry_T entry; save_funccal(&entry); - set_var_const(name, NULL, tv, FALSE, ASSIGN_DECL); + set_var_const(name, NULL, tv, FALSE, ASSIGN_DECL, 0); restore_funccal(); } @@ -1146,6 +1146,7 @@ call_def_function( int save_did_emsg_def = did_emsg_def; int trylevel_at_start = trylevel; int orig_funcdepth; + where_T where; // Get pointer to item in the stack. #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) @@ -1202,7 +1203,7 @@ call_def_function( ++idx) { if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len - && check_typval_type(ufunc->uf_arg_types[idx], &argv[idx], + && check_typval_arg_type(ufunc->uf_arg_types[idx], &argv[idx], idx + 1) == FAIL) goto failed_early; copy_tv(&argv[idx], STACK_TV_BOT(0)); @@ -1233,7 +1234,7 @@ call_def_function( for (idx = 0; idx < vararg_count; ++idx) { - if (check_typval_type(expected, &li->li_tv, + if (check_typval_arg_type(expected, &li->li_tv, argc + idx + 1) == FAIL) goto failed_early; li = li->li_next; @@ -1333,6 +1334,9 @@ call_def_function( emsg_silent_def = emsg_silent; did_emsg_def = 0; + where.wt_index = 0; + where.wt_variable = FALSE; + // Decide where to start execution, handles optional arguments. init_instr_idx(ufunc, argc, &ectx); @@ -3170,6 +3174,11 @@ call_def_function( goto failed; ++ectx.ec_stack.ga_len; copy_tv(&li->li_tv, STACK_TV_BOT(-1)); + + // Useful when used in unpack assignment. Reset at + // ISN_DROP. + where.wt_index = index + 1; + where.wt_variable = TRUE; } break; @@ -3288,9 +3297,12 @@ call_def_function( tv = STACK_TV_BOT((int)ct->ct_off); SOURCING_LNUM = iptr->isn_lnum; - if (check_typval_type(ct->ct_type, tv, ct->ct_arg_idx) - == FAIL) + if (!where.wt_variable) + where.wt_index = ct->ct_arg_idx; + if (check_typval_type(ct->ct_type, tv, where) == FAIL) goto on_error; + if (!where.wt_variable) + where.wt_index = 0; // number 0 is FALSE, number 1 is TRUE if (tv->v_type == VAR_NUMBER @@ -3573,6 +3585,8 @@ call_def_function( case ISN_DROP: --ectx.ec_stack.ga_len; clear_tv(STACK_TV_BOT(0)); + where.wt_index = 0; + where.wt_variable = FALSE; break; } continue; diff --git a/src/vim9script.c b/src/vim9script.c index 387c9bedc4..fea478592d 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -650,7 +650,7 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg) init_tv.v_type = VAR_NUMBER; else init_tv.v_type = type->tt_type; - set_var_const(name, type, &init_tv, FALSE, 0); + set_var_const(name, type, &init_tv, FALSE, 0, 0); vim_free(name); return p; @@ -855,7 +855,7 @@ find_typval_in_script(typval_T *dest) if (sv->sv_name != NULL && sv->sv_tv == dest) return sv; } - iemsg("check_script_var_type(): not found"); + iemsg("find_typval_in_script(): not found"); return NULL; } @@ -864,7 +864,11 @@ find_typval_in_script(typval_T *dest) * If needed convert "value" to a bool. */ int -check_script_var_type(typval_T *dest, typval_T *value, char_u *name) +check_script_var_type( + typval_T *dest, + typval_T *value, + char_u *name, + where_T where) { svar_T *sv = find_typval_in_script(dest); int ret; @@ -876,7 +880,7 @@ check_script_var_type(typval_T *dest, typval_T *value, char_u *name) semsg(_(e_readonlyvar), name); return FAIL; } - ret = check_typval_type(sv->sv_type, value, 0); + ret = check_typval_type(sv->sv_type, value, where); if (ret == OK && need_convert_to_bool(sv->sv_type, value)) { int val = tv2bool(value); diff --git a/src/vim9type.c b/src/vim9type.c index 1a20ef5796..d1ada8e96b 100644 --- a/src/vim9type.c +++ b/src/vim9type.c @@ -399,13 +399,22 @@ typval2type_vimvar(typval_T *tv, garray_T *type_gap) return typval2type(tv, type_gap); } + int +check_typval_arg_type(type_T *expected, typval_T *actual_tv, int arg_idx) +{ + where_T where; + + where.wt_index = arg_idx; + where.wt_variable = FALSE; + return check_typval_type(expected, actual_tv, where); +} /* * Return FAIL if "expected" and "actual" don't match. * When "argidx" > 0 it is included in the error message. */ int -check_typval_type(type_T *expected, typval_T *actual_tv, int argidx) +check_typval_type(type_T *expected, typval_T *actual_tv, where_T where) { garray_T type_list; type_T *actual_type; @@ -414,7 +423,7 @@ check_typval_type(type_T *expected, typval_T *actual_tv, int argidx) ga_init2(&type_list, sizeof(type_T *), 10); actual_type = typval2type(actual_tv, &type_list); if (actual_type != NULL) - res = check_type(expected, actual_type, TRUE, argidx); + res = check_type(expected, actual_type, TRUE, where); clear_type_list(&type_list); return res; } @@ -426,15 +435,29 @@ type_mismatch(type_T *expected, type_T *actual) } void -arg_type_mismatch(type_T *expected, type_T *actual, int argidx) +arg_type_mismatch(type_T *expected, type_T *actual, int arg_idx) +{ + where_T where; + + where.wt_index = arg_idx; + where.wt_variable = FALSE; + type_mismatch_where(expected, actual, where); +} + + void +type_mismatch_where(type_T *expected, type_T *actual, where_T where) { char *tofree1, *tofree2; char *typename1 = type_name(expected, &tofree1); char *typename2 = type_name(actual, &tofree2); - if (argidx > 0) - semsg(_(e_argument_nr_type_mismatch_expected_str_but_got_str), - argidx, typename1, typename2); + if (where.wt_index > 0) + { + semsg(_(where.wt_variable + ? e_variable_nr_type_mismatch_expected_str_but_got_str + : e_argument_nr_type_mismatch_expected_str_but_got_str), + where.wt_index, typename1, typename2); + } else semsg(_(e_type_mismatch_expected_str_but_got_str), typename1, typename2); @@ -448,7 +471,7 @@ arg_type_mismatch(type_T *expected, type_T *actual, int argidx) * When "argidx" > 0 it is included in the error message. */ int -check_type(type_T *expected, type_T *actual, int give_msg, int argidx) +check_type(type_T *expected, type_T *actual, int give_msg, where_T where) { int ret = OK; @@ -469,7 +492,7 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx) // Using number 0 or 1 for bool is OK. return OK; if (give_msg) - arg_type_mismatch(expected, actual, argidx); + type_mismatch_where(expected, actual, where); return FAIL; } if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST) @@ -477,7 +500,7 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx) // "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, 0); + FALSE, where); } else if (expected->tt_type == VAR_FUNC) { @@ -486,7 +509,7 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx) if (expected->tt_member != &t_unknown && actual->tt_member != &t_unknown) ret = check_type(expected->tt_member, actual->tt_member, - FALSE, 0); + FALSE, where); if (ret == OK && expected->tt_argcount != -1 && actual->tt_argcount != -1 && (actual->tt_argcount < expected->tt_min_argcount @@ -500,8 +523,8 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx) for (i = 0; i < expected->tt_argcount; ++i) // Allow for using "any" argument type, lambda's have them. if (actual->tt_args[i] != &t_any && check_type( - expected->tt_args[i], actual->tt_args[i], FALSE, 0) - == FAIL) + expected->tt_args[i], actual->tt_args[i], FALSE, + where) == FAIL) { ret = FAIL; break; @@ -509,7 +532,7 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx) } } if (ret == FAIL && give_msg) - arg_type_mismatch(expected, actual, argidx); + type_mismatch_where(expected, actual, where); } return ret; } @@ -552,7 +575,7 @@ check_argument_types( expected = type->tt_args[type->tt_argcount - 1]->tt_member; else expected = type->tt_args[i]; - if (check_typval_type(expected, &argvars[i], i + 1) == FAIL) + if (check_typval_arg_type(expected, &argvars[i], i + 1) == FAIL) return FAIL; } return OK; |