]> granicus.if.org Git - vim/commitdiff
patch 8.2.2501: not always clear where an error is reported v8.2.2501
authorBram Moolenaar <Bram@vim.org>
Thu, 11 Feb 2021 20:19:34 +0000 (21:19 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 11 Feb 2021 20:19:34 +0000 (21:19 +0100)
Problem:    Not always clear where an error is reported.
Solution:   Add the where_T structure and pass it around. (closes #7796)

16 files changed:
src/dict.c
src/errors.h
src/eval.c
src/evalvars.c
src/list.c
src/proto/eval.pro
src/proto/evalvars.pro
src/proto/vim9script.pro
src/proto/vim9type.pro
src/structs.h
src/testdir/test_vim9_assign.vim
src/version.c
src/vim9compile.c
src/vim9execute.c
src/vim9script.c
src/vim9type.c

index b36b2bf6ddb16351980d1233b92704864d0044fa..922da473ced7bd738b8e152306edfcd609b7db23 100644 (file)
@@ -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)
index 39eca7e9431646c7b74bf996ea42f5c71fb0693e..927e1ffde9b3e378077547249ef006e735083858 100644 (file)
@@ -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"));
index 8b942e8e218331d4b9b868c52613f59928619576..aae6ee8ffa9fe80388ca2dd74a7e9b958297a9f6 100644 (file)
@@ -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)
index b6a6927d60f38184f53ad2374b14d9531816b17f..57a881a289b30a81f81948a444d0cb3b5dd095b8 100644 (file)
@@ -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), &ltv, FALSE, flags,
-                                                           (char_u *)"]", op);
+                                                  (char_u *)"]", op, var_idx);
            clear_tv(&ltv);
            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);
        }
 
index 4d33aa6e082048f58c96c30f3f87d8894a8795fb..484ce74c985581c6c1fc81e6e6524ff3e3710a23 100644 (file)
@@ -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);
 
index 07b11b25a5478ce003bac64ab6e84b006415b113..03630c4b03cb6cc199391d015dc50308d197a6fa 100644 (file)
@@ -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);
index 0861a8866ad95b60a4b2160a56c088373cf2a21a..ce160d7de510bf6c2431e15fee9b23a03db23cff 100644 (file)
@@ -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);
index 2a63b8b274e2f820f45579a620e73fc2abaf78b7..c6493519cf5169b23ba228f31b7dc40886365754 100644 (file)
@@ -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 : */
index f7b472c9e6895a5d283a242e1f4e600233af8318..35da1fe72e54bfc54bc65548682ee7c94f604235 100644 (file)
@@ -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);
index 8d86d11b18b3a28b8d2f5c96224be92f582d42c2..550e53a2bcebe85bc498d8e2710be30d3bdd3699 100644 (file)
@@ -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;
+
index 55beffa958442fda84a65da69b10e2774d550420..7599df2c54c34e8edd2d61f2396da761d31bcaf8 100644 (file)
@@ -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()
index 8918ec5fca01833d45c65fa229004654471c7bb6..1037c184123ef07cdb1e2088c600bc11ca2628b9 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2501,
 /**/
     2500,
 /**/
index 512f7246c20a1ea0b5ed193ab26b741f33b7074f..4dfb42f352c4c05c1e9b699472302e8edb6e3b6d 100644 (file)
@@ -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)
index 8728088c08f4213206cde227315b654450b9abe3..6d462eaf1dbdc3baa9f16f6b36918709488ed1b4 100644 (file)
@@ -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;
index 387c9bedc45be57fa761488434aa40c17561e355..fea478592d73eedfc0de8585dae84a74b803b2eb 100644 (file)
@@ -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);
index 1a20ef57961ec73b49c6c8959dcdfac6f1f8c713..d1ada8e96b46c38dc2af50d5bd1374adbe8eec5e 100644 (file)
@@ -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;