To: vim_dev@googlegroups.com Subject: Patch 8.2.2400 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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), <v, FALSE, flags, ! (char_u *)"]", op); clear_tv(<v); 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), <v, FALSE, flags, ! (char_u *)"]", op, var_idx); clear_tv(<v); 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 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 -- Bram@Moolenaar.net -- 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 ///