Patch 8.2.2501
Problem:    Not always clear where an error is reported.
Solution:   Add the where_T structure and pass it around. (closes #7796)
Files:      src/structs.h, src/vim9type.c, src/proto/vim9type.pro,
            src/errors.h, src/evalvars.c, src/proto/evalvars.pro, src/eval.c,
            src/proto/eval.pro, src/vim9execute.c, src/vim9script.c,
            src/proto/vim9script.pro, src/dict.c, src/list.c,
            src/vim9compile.c, src/testdir/test_vim9_assign.vim


*** ../vim-8.2.2500/src/structs.h       2021-02-07 12:12:39.377215418 +0100
--- src/structs.h       2021-02-11 20:45:26.822390345 +0100
***************
*** 4387,4389 ****
--- 4387,4396 ----
      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;
+ 
*** ../vim-8.2.2500/src/vim9type.c      2021-02-07 18:06:25.266692335 +0100
--- src/vim9type.c      2021-02-11 21:05:07.873763997 +0100
***************
*** 399,411 ****
      return typval2type(tv, type_gap);
  }
  
  
  /*
   * 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)
  {
      garray_T  type_list;
      type_T    *actual_type;
--- 399,420 ----
      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, where_T where)
  {
      garray_T  type_list;
      type_T    *actual_type;
***************
*** 414,420 ****
      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);
      clear_type_list(&type_list);
      return res;
  }
--- 423,429 ----
      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, where);
      clear_type_list(&type_list);
      return res;
  }
***************
*** 426,440 ****
  }
  
      void
! arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
  {
      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);
      else
        semsg(_(e_type_mismatch_expected_str_but_got_str),
                                                         typename1, typename2);
--- 435,463 ----
  }
  
      void
! 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 (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,454 ****
   * When "argidx" > 0 it is included in the error message.
   */
      int
! check_type(type_T *expected, type_T *actual, int give_msg, int argidx)
  {
      int ret = OK;
  
--- 471,477 ----
   * When "argidx" > 0 it is included in the error message.
   */
      int
! check_type(type_T *expected, type_T *actual, int give_msg, where_T where)
  {
      int ret = OK;
  
***************
*** 469,475 ****
                // Using number 0 or 1 for bool is OK.
                return OK;
            if (give_msg)
!               arg_type_mismatch(expected, actual, argidx);
            return FAIL;
        }
        if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
--- 492,498 ----
                // Using number 0 or 1 for bool is OK.
                return OK;
            if (give_msg)
!               type_mismatch_where(expected, actual, where);
            return FAIL;
        }
        if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
***************
*** 477,483 ****
            // "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);
        }
        else if (expected->tt_type == VAR_FUNC)
        {
--- 500,506 ----
            // "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, where);
        }
        else if (expected->tt_type == VAR_FUNC)
        {
***************
*** 486,492 ****
            if (expected->tt_member != &t_unknown
                                            && actual->tt_member != &t_unknown)
                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
--- 509,515 ----
            if (expected->tt_member != &t_unknown
                                            && actual->tt_member != &t_unknown)
                ret = check_type(expected->tt_member, actual->tt_member,
!                                                                FALSE, where);
            if (ret == OK && expected->tt_argcount != -1
                    && actual->tt_argcount != -1
                    && (actual->tt_argcount < expected->tt_min_argcount
***************
*** 500,507 ****
                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)
                    {
                        ret = FAIL;
                        break;
--- 523,530 ----
                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,
!                                                               where) == FAIL)
                    {
                        ret = FAIL;
                        break;
***************
*** 509,515 ****
            }
        }
        if (ret == FAIL && give_msg)
!           arg_type_mismatch(expected, actual, argidx);
      }
      return ret;
  }
--- 532,538 ----
            }
        }
        if (ret == FAIL && give_msg)
!           type_mismatch_where(expected, actual, where);
      }
      return ret;
  }
***************
*** 552,558 ****
            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)
            return FAIL;
      }
      return OK;
--- 575,581 ----
            expected = type->tt_args[type->tt_argcount - 1]->tt_member;
        else
            expected = type->tt_args[i];
!       if (check_typval_arg_type(expected, &argvars[i], i + 1) == FAIL)
            return FAIL;
      }
      return OK;
*** ../vim-8.2.2500/src/proto/vim9type.pro      2021-01-16 16:06:58.126713782 
+0100
--- src/proto/vim9type.pro      2021-02-11 20:57:26.463773355 +0100
***************
*** 11,20 ****
  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);
  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);
  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);
--- 11,22 ----
  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_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 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);
*** ../vim-8.2.2500/src/errors.h        2021-02-10 22:23:36.398613504 +0100
--- src/errors.h        2021-02-11 19:56:36.101245373 +0100
***************
*** 361,363 ****
--- 361,365 ----
        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"));
*** ../vim-8.2.2500/src/evalvars.c      2021-01-23 13:39:10.395533599 +0100
--- src/evalvars.c      2021-02-11 20:45:13.374442236 +0100
***************
*** 173,179 ****
  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 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);
--- 173,179 ----
  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, 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,941 ****
      char_u    *arg = arg_start;
      list_T    *l;
      int               i;
      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)
            return FAIL;
        return OK;
      }
--- 929,942 ----
      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, var_idx) == NULL)
            return FAIL;
        return OK;
      }
***************
*** 964,970 ****
      while (*arg != ']')
      {
        arg = skipwhite(arg + 1);
!       arg = ex_let_one(arg, &item->li_tv, TRUE, flags, (char_u *)",;]", op);
        item = item->li_next;
        if (arg == NULL)
            return FAIL;
--- 965,973 ----
      while (*arg != ']')
      {
        arg = skipwhite(arg + 1);
!       ++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,995 ****
            ltv.v_lock = 0;
            ltv.vval.v_list = l;
            l->lv_refcount = 1;
  
            arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, flags,
!                                                           (char_u *)"]", op);
            clear_tv(&ltv);
            if (arg == NULL)
                return FAIL;
--- 990,999 ----
            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, var_idx);
            clear_tv(&ltv);
            if (arg == NULL)
                return FAIL;
***************
*** 1284,1290 ****
      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
  {
      int               c1;
      char_u    *name;
--- 1288,1295 ----
      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
!     int               var_idx)        // variable index for "let [a, b] = 
list"
  {
      int               c1;
      char_u    *name;
***************
*** 1508,1514 ****
                emsg(_(e_letunexp));
            else
            {
!               set_var_lval(&lv, p, tv, copy, flags, op);
                arg_end = p;
            }
        }
--- 1513,1519 ----
                emsg(_(e_letunexp));
            else
            {
!               set_var_lval(&lv, p, tv, copy, flags, op, var_idx);
                arg_end = p;
            }
        }
***************
*** 3075,3081 ****
      typval_T  *tv,
      int               copy)       // make copy of value in "tv"
  {
!     set_var_const(name, NULL, tv, copy, ASSIGN_DECL);
  }
  
  /*
--- 3080,3086 ----
      typval_T  *tv,
      int               copy)       // make copy of value in "tv"
  {
!     set_var_const(name, NULL, tv, copy, ASSIGN_DECL, 0);
  }
  
  /*
***************
*** 3089,3095 ****
      type_T    *type,
      typval_T  *tv_arg,
      int               copy,       // make copy of value in "tv"
!     int               flags)      // ASSIGN_CONST, ASSIGN_FINAL, etc.
  {
      typval_T  *tv = tv_arg;
      typval_T  bool_tv;
--- 3094,3101 ----
      type_T    *type,
      typval_T  *tv_arg,
      int               copy,       // make copy of value in "tv"
!     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,3153 ****
--- 3154,3161 ----
  
            if (is_script_local && vim9script)
            {
+               where_T where;
+ 
                if ((flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0)
                {
                    semsg(_(e_redefining_script_item_str), name);
***************
*** 3155,3161 ****
                }
  
                // check the type and adjust to bool if needed
!               if (check_script_var_type(&di->di_tv, tv, name) == FAIL)
                    goto failed;
            }
  
--- 3163,3171 ----
                }
  
                // check the type and adjust to bool if needed
!               where.wt_index = var_idx;
!               where.wt_variable = TRUE;
!               if (check_script_var_type(&di->di_tv, tv, name, where) == FAIL)
                    goto failed;
            }
  
***************
*** 3719,3728 ****
      tv.vval.v_string = (char_u *)"";
      if (append)
        set_var_lval(redir_lval, redir_endp, &tv, TRUE,
!                                               ASSIGN_NO_DECL, (char_u *)".");
      else
        set_var_lval(redir_lval, redir_endp, &tv, TRUE,
!                                               ASSIGN_NO_DECL, (char_u *)"=");
      clear_lval(redir_lval);
      if (called_emsg > called_emsg_before)
      {
--- 3729,3738 ----
      tv.vval.v_string = (char_u *)"";
      if (append)
        set_var_lval(redir_lval, redir_endp, &tv, TRUE,
!                                            ASSIGN_NO_DECL, (char_u *)".", 0);
      else
        set_var_lval(redir_lval, redir_endp, &tv, TRUE,
!                                            ASSIGN_NO_DECL, (char_u *)"=", 0);
      clear_lval(redir_lval);
      if (called_emsg > called_emsg_before)
      {
***************
*** 3794,3800 ****
                                        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 *)".");
            clear_lval(redir_lval);
        }
  
--- 3804,3810 ----
                                        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 *)".", 0);
            clear_lval(redir_lval);
        }
  
*** ../vim-8.2.2500/src/proto/evalvars.pro      2021-01-13 19:48:41.628312470 
+0100
--- src/proto/evalvars.pro      2021-02-11 20:53:53.224524973 +0100
***************
*** 70,76 ****
  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);
  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);
--- 70,76 ----
  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, 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);
*** ../vim-8.2.2500/src/eval.c  2021-02-03 19:51:14.935468638 +0100
--- src/eval.c  2021-02-11 20:50:35.937234567 +0100
***************
*** 1299,1306 ****
      char_u    *endp,
      typval_T  *rettv,
      int               copy,
!     int               flags,    // ASSIGN_CONST, ASSIGN_NO_DECL
!     char_u    *op)
  {
      int               cc;
      listitem_T        *ri;
--- 1299,1307 ----
      char_u    *endp,
      typval_T  *rettv,
      int               copy,
!     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,1398 ****
        else
        {
            if (lp->ll_type != NULL
!                          && check_typval_type(lp->ll_type, rettv, 0) == FAIL)
                return;
!           set_var_const(lp->ll_name, lp->ll_type, rettv, copy, flags);
        }
        *endp = cc;
      }
--- 1391,1400 ----
        else
        {
            if (lp->ll_type != NULL
!                      && check_typval_arg_type(lp->ll_type, rettv, 0) == FAIL)
                return;
!           set_var_const(lp->ll_name, lp->ll_type, rettv, copy,
!                                                              flags, var_idx);
        }
        *endp = cc;
      }
***************
*** 1471,1477 ****
        }
  
        if (lp->ll_valtype != NULL
!                       && check_typval_type(lp->ll_valtype, rettv, 0) == FAIL)
            return;
  
        if (lp->ll_newkey != NULL)
--- 1473,1479 ----
        }
  
        if (lp->ll_valtype != NULL
!                   && check_typval_arg_type(lp->ll_valtype, rettv, 0) == FAIL)
            return;
  
        if (lp->ll_newkey != NULL)
*** ../vim-8.2.2500/src/proto/eval.pro  2021-01-21 12:34:11.441508288 +0100
--- src/proto/eval.pro  2021-02-11 20:08:36.171007139 +0100
***************
*** 25,31 ****
  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 *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);
--- 25,31 ----
  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, 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);
*** ../vim-8.2.2500/src/vim9execute.c   2021-02-03 20:01:16.777542349 +0100
--- src/vim9execute.c   2021-02-11 21:18:14.586440583 +0100
***************
*** 851,857 ****
      funccal_entry_T entry;
  
      save_funccal(&entry);
!     set_var_const(name, NULL, tv, FALSE, ASSIGN_DECL);
      restore_funccal();
  }
  
--- 851,857 ----
      funccal_entry_T entry;
  
      save_funccal(&entry);
!     set_var_const(name, NULL, tv, FALSE, ASSIGN_DECL, 0);
      restore_funccal();
  }
  
***************
*** 1146,1151 ****
--- 1146,1152 ----
      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,1208 ****
                                                                         ++idx)
      {
        if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len
!               && check_typval_type(ufunc->uf_arg_types[idx], &argv[idx],
                                                              idx + 1) == FAIL)
            goto failed_early;
        copy_tv(&argv[idx], STACK_TV_BOT(0));
--- 1203,1209 ----
                                                                         ++idx)
      {
        if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len
!               && 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,1239 ****
  
            for (idx = 0; idx < vararg_count; ++idx)
            {
!               if (check_typval_type(expected, &li->li_tv,
                                                       argc + idx + 1) == FAIL)
                    goto failed_early;
                li = li->li_next;
--- 1234,1240 ----
  
            for (idx = 0; idx < vararg_count; ++idx)
            {
!               if (check_typval_arg_type(expected, &li->li_tv,
                                                       argc + idx + 1) == FAIL)
                    goto failed_early;
                li = li->li_next;
***************
*** 1333,1338 ****
--- 1334,1342 ----
      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,3175 ****
--- 3174,3184 ----
                        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,3296 ****
  
                    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)
                        goto on_error;
  
                    // number 0 is FALSE, number 1 is TRUE
                    if (tv->v_type == VAR_NUMBER
--- 3297,3308 ----
  
                    tv = STACK_TV_BOT((int)ct->ct_off);
                    SOURCING_LNUM = iptr->isn_lnum;
!                   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,3578 ****
--- 3585,3592 ----
            case ISN_DROP:
                --ectx.ec_stack.ga_len;
                clear_tv(STACK_TV_BOT(0));
+               where.wt_index = 0;
+               where.wt_variable = FALSE;
                break;
        }
        continue;
*** ../vim-8.2.2500/src/vim9script.c    2021-02-07 15:28:05.792508596 +0100
--- src/vim9script.c    2021-02-11 20:47:20.029959029 +0100
***************
*** 650,656 ****
        init_tv.v_type = VAR_NUMBER;
      else
        init_tv.v_type = type->tt_type;
!     set_var_const(name, type, &init_tv, FALSE, 0);
  
      vim_free(name);
      return p;
--- 650,656 ----
        init_tv.v_type = VAR_NUMBER;
      else
        init_tv.v_type = type->tt_type;
!     set_var_const(name, type, &init_tv, FALSE, 0, 0);
  
      vim_free(name);
      return p;
***************
*** 855,861 ****
        if (sv->sv_name != NULL && sv->sv_tv == dest)
            return sv;
      }
!     iemsg("check_script_var_type(): not found");
      return NULL;
  }
  
--- 855,861 ----
        if (sv->sv_name != NULL && sv->sv_tv == dest)
            return sv;
      }
!     iemsg("find_typval_in_script(): not found");
      return NULL;
  }
  
***************
*** 864,870 ****
   * If needed convert "value" to a bool.
   */
      int
! check_script_var_type(typval_T *dest, typval_T *value, char_u *name)
  {
      svar_T  *sv = find_typval_in_script(dest);
      int           ret;
--- 864,874 ----
   * If needed convert "value" to a bool.
   */
      int
! 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,882 ****
            semsg(_(e_readonlyvar), name);
            return FAIL;
        }
!       ret = check_typval_type(sv->sv_type, value, 0);
        if (ret == OK && need_convert_to_bool(sv->sv_type, value))
        {
            int val = tv2bool(value);
--- 880,886 ----
            semsg(_(e_readonlyvar), name);
            return FAIL;
        }
!       ret = check_typval_type(sv->sv_type, value, where);
        if (ret == OK && need_convert_to_bool(sv->sv_type, value))
        {
            int val = tv2bool(value);
*** ../vim-8.2.2500/src/proto/vim9script.pro    2021-01-11 21:20:05.669652000 
+0100
--- src/proto/vim9script.pro    2021-02-11 20:53:00.444713247 +0100
***************
*** 14,18 ****
  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);
  /* vim: set ft=c : */
--- 14,18 ----
  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, 
where_T where);
  /* vim: set ft=c : */
*** ../vim-8.2.2500/src/dict.c  2021-02-07 18:06:25.266692335 +0100
--- src/dict.c  2021-02-11 20:49:23.173500910 +0100
***************
*** 1089,1095 ****
            }
  
            if (type != NULL
!                    && check_typval_type(type, &HI2DI(hi2)->di_tv, 0) == FAIL)
                break;
  
            if (di1 == NULL)
--- 1089,1096 ----
            }
  
            if (type != NULL
!                    && check_typval_arg_type(type, &HI2DI(hi2)->di_tv, 0)
!                                                                      == FAIL)
                break;
  
            if (di1 == NULL)
*** ../vim-8.2.2500/src/list.c  2021-02-07 18:06:25.266692335 +0100
--- src/list.c  2021-02-11 20:51:55.068947950 +0100
***************
*** 698,704 ****
      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)
        return FAIL;
      ni = listitem_alloc();
      if (ni == NULL)
--- 698,704 ----
      listitem_T        *ni;
  
      if (l->lv_type != NULL && l->lv_type->tt_member != NULL
!               && check_typval_arg_type(l->lv_type->tt_member, tv, 0) == FAIL)
        return FAIL;
      ni = listitem_alloc();
      if (ni == NULL)
***************
*** 2135,2142 ****
                    }
                    if (filtermap == FILTERMAP_MAP)
                    {
!                       if (type != NULL && check_typval_type(type->tt_member,
!                                                           &newtv, 0) == FAIL)
                        {
                            clear_tv(&newtv);
                            break;
--- 2135,2142 ----
                    }
                    if (filtermap == FILTERMAP_MAP)
                    {
!                       if (type != NULL && check_typval_arg_type(
!                                          type->tt_member, &newtv, 0) == FAIL)
                        {
                            clear_tv(&newtv);
                            break;
***************
*** 2270,2277 ****
                    if (filtermap != FILTERMAP_FILTER)
                    {
                        if (filtermap == FILTERMAP_MAP && type != NULL
!                                         && check_typval_type(type->tt_member,
!                                                           &newtv, 0) == FAIL)
                        {
                            clear_tv(&newtv);
                            break;
--- 2270,2277 ----
                    if (filtermap != FILTERMAP_FILTER)
                    {
                        if (filtermap == FILTERMAP_MAP && type != NULL
!                                     && check_typval_arg_type(
!                                          type->tt_member, &newtv, 0) == FAIL)
                        {
                            clear_tv(&newtv);
                            break;
***************
*** 2314,2321 ****
                    }
                    if (filtermap == FILTERMAP_MAP)
                    {
!                       if (type != NULL && check_typval_type(type->tt_member,
!                                                           &newtv, 0) == FAIL)
                        {
                            clear_tv(&newtv);
                            break;
--- 2314,2321 ----
                    }
                    if (filtermap == FILTERMAP_MAP)
                    {
!                       if (type != NULL && check_typval_arg_type(
!                                          type->tt_member, &newtv, 0) == FAIL)
                        {
                            clear_tv(&newtv);
                            break;
***************
*** 2584,2590 ****
            }
            else
                item = NULL;
!           if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
                goto theend;
            list_extend(l1, l2, item);
  
--- 2584,2591 ----
            }
            else
                item = NULL;
!           if (type != NULL && check_typval_arg_type(
!                                                type, &argvars[1], 2) == FAIL)
                goto theend;
            list_extend(l1, l2, item);
  
***************
*** 2641,2647 ****
            else
                action = (char_u *)"force";
  
!           if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
                goto theend;
            dict_extend(d1, d2, action);
  
--- 2642,2649 ----
            else
                action = (char_u *)"force";
  
!           if (type != NULL && check_typval_arg_type(
!                                                type, &argvars[1], 2) == FAIL)
                goto theend;
            dict_extend(d1, d2, action);
  
*** ../vim-8.2.2500/src/vim9compile.c   2021-02-07 18:06:25.266692335 +0100
--- src/vim9compile.c   2021-02-11 20:57:11.231826641 +0100
***************
*** 893,898 ****
--- 893,900 ----
        int     silent,
        int     actual_is_const)
  {
+     where_T where;
+ 
      if (expected == &t_bool && actual != &t_bool
                                        && (actual->tt_flags & TTFLAG_BOOL_OK))
      {
***************
*** 902,908 ****
        return OK;
      }
  
!     if (check_type(expected, actual, FALSE, arg_idx) == OK)
        return OK;
  
      // If the actual type can be the expected type add a runtime check.
--- 904,912 ----
        return 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,4296 ****
      {
        garray_T    *stack = &cctx->ctx_type_stack;
        type_T      *actual;
  
        generate_ppconst(cctx, ppconst);
        actual = ((type_T **)stack->ga_data)[stack->ga_len - 1];
!       if (check_type(want_type, actual, FALSE, 0) == FAIL)
        {
            if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) == FAIL)
                return FAIL;
--- 4291,4303 ----
      {
        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];
!       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,8083 ****
--- 8085,8091 ----
            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,8100 ****
            // Otherwise check that the default value type matches the
            // specified type.
            val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
            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)
                goto erret;
  
            if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
--- 8096,8110 ----
            // 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, where) == FAIL)
                goto erret;
  
            if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
*** ../vim-8.2.2500/src/testdir/test_vim9_assign.vim    2021-01-23 
13:39:10.395533599 +0100
--- src/testdir/test_vim9_assign.vim    2021-02-11 21:09:37.020541628 +0100
***************
*** 284,289 ****
--- 284,297 ----
        [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()
*** ../vim-8.2.2500/src/version.c       2021-02-11 19:18:54.274296667 +0100
--- src/version.c       2021-02-11 21:19:08.686231844 +0100
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2501,
  /**/

-- 
Some say the world will end in fire; some say in segfaults.
I say it will end in a curly bracket.

 /// 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/202102112022.11BKMAjF690652%40masaka.moolenaar.net.

Raspunde prin e-mail lui