To: vim_dev@googlegroups.com Subject: Patch 8.2.3890 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3890 Problem: Vim9: type check for using v: variables is basic. Solution: Specify a more precise type. Files: src/evalvars.c, src/proto/evalvars.pro, src/vim9instr.c, src/testdir/test_vim9_expr.vim *** ../vim-8.2.3889/src/evalvars.c 2021-12-24 20:47:34.748104242 +0000 --- src/evalvars.c 2021-12-24 21:29:56.660545467 +0000 *************** *** 45,162 **** { char *vv_name; // name of variable, without v: dictitem16_T vv_di; // value and name for key (max 16 chars!) char vv_flags; // VV_COMPAT, VV_RO, VV_RO_SBX } vimvars[VV_LEN] = { // The order here must match the VV_ defines in vim.h! // Initializing a union does not work, leave tv.vval empty to get zero's. ! {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO}, ! {VV_NAME("count1", VAR_NUMBER), VV_RO}, ! {VV_NAME("prevcount", VAR_NUMBER), VV_RO}, ! {VV_NAME("errmsg", VAR_STRING), VV_COMPAT}, ! {VV_NAME("warningmsg", VAR_STRING), 0}, ! {VV_NAME("statusmsg", VAR_STRING), 0}, ! {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO}, ! {VV_NAME("this_session", VAR_STRING), VV_COMPAT}, ! {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO}, ! {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX}, ! {VV_NAME("termresponse", VAR_STRING), VV_RO}, ! {VV_NAME("fname", VAR_STRING), VV_RO}, ! {VV_NAME("lang", VAR_STRING), VV_RO}, ! {VV_NAME("lc_time", VAR_STRING), VV_RO}, ! {VV_NAME("ctype", VAR_STRING), VV_RO}, ! {VV_NAME("charconvert_from", VAR_STRING), VV_RO}, ! {VV_NAME("charconvert_to", VAR_STRING), VV_RO}, ! {VV_NAME("fname_in", VAR_STRING), VV_RO}, ! {VV_NAME("fname_out", VAR_STRING), VV_RO}, ! {VV_NAME("fname_new", VAR_STRING), VV_RO}, ! {VV_NAME("fname_diff", VAR_STRING), VV_RO}, ! {VV_NAME("cmdarg", VAR_STRING), VV_RO}, ! {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX}, ! {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX}, ! {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX}, ! {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX}, ! {VV_NAME("progname", VAR_STRING), VV_RO}, ! {VV_NAME("servername", VAR_STRING), VV_RO}, ! {VV_NAME("dying", VAR_NUMBER), VV_RO}, ! {VV_NAME("exception", VAR_STRING), VV_RO}, ! {VV_NAME("throwpoint", VAR_STRING), VV_RO}, ! {VV_NAME("register", VAR_STRING), VV_RO}, ! {VV_NAME("cmdbang", VAR_NUMBER), VV_RO}, ! {VV_NAME("insertmode", VAR_STRING), VV_RO}, ! {VV_NAME("val", VAR_UNKNOWN), VV_RO}, ! {VV_NAME("key", VAR_UNKNOWN), VV_RO}, ! {VV_NAME("profiling", VAR_NUMBER), VV_RO}, ! {VV_NAME("fcs_reason", VAR_STRING), VV_RO}, ! {VV_NAME("fcs_choice", VAR_STRING), 0}, ! {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO}, ! {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO}, ! {VV_NAME("beval_winid", VAR_NUMBER), VV_RO}, ! {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO}, ! {VV_NAME("beval_col", VAR_NUMBER), VV_RO}, ! {VV_NAME("beval_text", VAR_STRING), VV_RO}, ! {VV_NAME("scrollstart", VAR_STRING), 0}, ! {VV_NAME("swapname", VAR_STRING), VV_RO}, ! {VV_NAME("swapchoice", VAR_STRING), 0}, ! {VV_NAME("swapcommand", VAR_STRING), VV_RO}, ! {VV_NAME("char", VAR_STRING), 0}, ! {VV_NAME("mouse_win", VAR_NUMBER), 0}, ! {VV_NAME("mouse_winid", VAR_NUMBER), 0}, ! {VV_NAME("mouse_lnum", VAR_NUMBER), 0}, ! {VV_NAME("mouse_col", VAR_NUMBER), 0}, ! {VV_NAME("operator", VAR_STRING), VV_RO}, ! {VV_NAME("searchforward", VAR_NUMBER), 0}, ! {VV_NAME("hlsearch", VAR_NUMBER), 0}, ! {VV_NAME("oldfiles", VAR_LIST), 0}, ! {VV_NAME("windowid", VAR_NUMBER), VV_RO}, ! {VV_NAME("progpath", VAR_STRING), VV_RO}, ! {VV_NAME("completed_item", VAR_DICT), VV_RO}, ! {VV_NAME("option_new", VAR_STRING), VV_RO}, ! {VV_NAME("option_old", VAR_STRING), VV_RO}, ! {VV_NAME("option_oldlocal", VAR_STRING), VV_RO}, ! {VV_NAME("option_oldglobal", VAR_STRING), VV_RO}, ! {VV_NAME("option_command", VAR_STRING), VV_RO}, ! {VV_NAME("option_type", VAR_STRING), VV_RO}, ! {VV_NAME("errors", VAR_LIST), 0}, ! {VV_NAME("false", VAR_BOOL), VV_RO}, ! {VV_NAME("true", VAR_BOOL), VV_RO}, ! {VV_NAME("none", VAR_SPECIAL), VV_RO}, ! {VV_NAME("null", VAR_SPECIAL), VV_RO}, ! {VV_NAME("numbermax", VAR_NUMBER), VV_RO}, ! {VV_NAME("numbermin", VAR_NUMBER), VV_RO}, ! {VV_NAME("numbersize", VAR_NUMBER), VV_RO}, ! {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO}, ! {VV_NAME("testing", VAR_NUMBER), 0}, ! {VV_NAME("t_number", VAR_NUMBER), VV_RO}, ! {VV_NAME("t_string", VAR_NUMBER), VV_RO}, ! {VV_NAME("t_func", VAR_NUMBER), VV_RO}, ! {VV_NAME("t_list", VAR_NUMBER), VV_RO}, ! {VV_NAME("t_dict", VAR_NUMBER), VV_RO}, ! {VV_NAME("t_float", VAR_NUMBER), VV_RO}, ! {VV_NAME("t_bool", VAR_NUMBER), VV_RO}, ! {VV_NAME("t_none", VAR_NUMBER), VV_RO}, ! {VV_NAME("t_job", VAR_NUMBER), VV_RO}, ! {VV_NAME("t_channel", VAR_NUMBER), VV_RO}, ! {VV_NAME("t_blob", VAR_NUMBER), VV_RO}, ! {VV_NAME("termrfgresp", VAR_STRING), VV_RO}, ! {VV_NAME("termrbgresp", VAR_STRING), VV_RO}, ! {VV_NAME("termu7resp", VAR_STRING), VV_RO}, ! {VV_NAME("termstyleresp", VAR_STRING), VV_RO}, ! {VV_NAME("termblinkresp", VAR_STRING), VV_RO}, ! {VV_NAME("event", VAR_DICT), VV_RO}, ! {VV_NAME("versionlong", VAR_NUMBER), VV_RO}, ! {VV_NAME("echospace", VAR_NUMBER), VV_RO}, ! {VV_NAME("argv", VAR_LIST), VV_RO}, ! {VV_NAME("collate", VAR_STRING), VV_RO}, ! {VV_NAME("exiting", VAR_SPECIAL), VV_RO}, ! {VV_NAME("colornames", VAR_DICT), VV_RO}, ! {VV_NAME("sizeofint", VAR_NUMBER), VV_RO}, ! {VV_NAME("sizeoflong", VAR_NUMBER), VV_RO}, ! {VV_NAME("sizeofpointer", VAR_NUMBER), VV_RO}, }; // shorthand ! #define vv_type vv_di.di_tv.v_type #define vv_nr vv_di.di_tv.vval.v_number #define vv_float vv_di.di_tv.vval.v_float #define vv_str vv_di.di_tv.vval.v_string --- 45,163 ---- { char *vv_name; // name of variable, without v: dictitem16_T vv_di; // value and name for key (max 16 chars!) + type_T *vv_type; // type or NULL char vv_flags; // VV_COMPAT, VV_RO, VV_RO_SBX } vimvars[VV_LEN] = { // The order here must match the VV_ defines in vim.h! // Initializing a union does not work, leave tv.vval empty to get zero's. ! {VV_NAME("count", VAR_NUMBER), NULL, VV_COMPAT+VV_RO}, ! {VV_NAME("count1", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("prevcount", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("errmsg", VAR_STRING), NULL, VV_COMPAT}, ! {VV_NAME("warningmsg", VAR_STRING), NULL, 0}, ! {VV_NAME("statusmsg", VAR_STRING), NULL, 0}, ! {VV_NAME("shell_error", VAR_NUMBER), NULL, VV_COMPAT+VV_RO}, ! {VV_NAME("this_session", VAR_STRING), NULL, VV_COMPAT}, ! {VV_NAME("version", VAR_NUMBER), NULL, VV_COMPAT+VV_RO}, ! {VV_NAME("lnum", VAR_NUMBER), NULL, VV_RO_SBX}, ! {VV_NAME("termresponse", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("fname", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("lang", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("lc_time", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("ctype", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("charconvert_from", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("charconvert_to", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("fname_in", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("fname_out", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("fname_new", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("fname_diff", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("cmdarg", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("foldstart", VAR_NUMBER), NULL, VV_RO_SBX}, ! {VV_NAME("foldend", VAR_NUMBER), NULL, VV_RO_SBX}, ! {VV_NAME("folddashes", VAR_STRING), NULL, VV_RO_SBX}, ! {VV_NAME("foldlevel", VAR_NUMBER), NULL, VV_RO_SBX}, ! {VV_NAME("progname", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("servername", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("dying", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("exception", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("throwpoint", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("register", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("cmdbang", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("insertmode", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("val", VAR_UNKNOWN), NULL, VV_RO}, ! {VV_NAME("key", VAR_UNKNOWN), NULL, VV_RO}, ! {VV_NAME("profiling", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("fcs_reason", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("fcs_choice", VAR_STRING), NULL, 0}, ! {VV_NAME("beval_bufnr", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("beval_winnr", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("beval_winid", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("beval_lnum", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("beval_col", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("beval_text", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("scrollstart", VAR_STRING), NULL, 0}, ! {VV_NAME("swapname", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("swapchoice", VAR_STRING), NULL, 0}, ! {VV_NAME("swapcommand", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("char", VAR_STRING), NULL, 0}, ! {VV_NAME("mouse_win", VAR_NUMBER), NULL, 0}, ! {VV_NAME("mouse_winid", VAR_NUMBER), NULL, 0}, ! {VV_NAME("mouse_lnum", VAR_NUMBER), NULL, 0}, ! {VV_NAME("mouse_col", VAR_NUMBER), NULL, 0}, ! {VV_NAME("operator", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("searchforward", VAR_NUMBER), NULL, 0}, ! {VV_NAME("hlsearch", VAR_NUMBER), NULL, 0}, ! {VV_NAME("oldfiles", VAR_LIST), &t_list_string, 0}, ! {VV_NAME("windowid", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("progpath", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("completed_item", VAR_DICT), &t_dict_string, VV_RO}, ! {VV_NAME("option_new", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("option_old", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("option_oldlocal", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("option_oldglobal", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("option_command", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("option_type", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("errors", VAR_LIST), &t_list_string, 0}, ! {VV_NAME("false", VAR_BOOL), NULL, VV_RO}, ! {VV_NAME("true", VAR_BOOL), NULL, VV_RO}, ! {VV_NAME("none", VAR_SPECIAL), NULL, VV_RO}, ! {VV_NAME("null", VAR_SPECIAL), NULL, VV_RO}, ! {VV_NAME("numbermax", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("numbermin", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("numbersize", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("vim_did_enter", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("testing", VAR_NUMBER), NULL, 0}, ! {VV_NAME("t_number", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("t_string", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("t_func", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("t_list", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("t_dict", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("t_float", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("t_bool", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("t_none", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("t_job", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("t_channel", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("t_blob", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("termrfgresp", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("termrbgresp", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("termu7resp", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("termstyleresp", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("termblinkresp", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("event", VAR_DICT), NULL, VV_RO}, ! {VV_NAME("versionlong", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("echospace", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("argv", VAR_LIST), &t_list_string, VV_RO}, ! {VV_NAME("collate", VAR_STRING), NULL, VV_RO}, ! {VV_NAME("exiting", VAR_SPECIAL), NULL, VV_RO}, ! {VV_NAME("colornames", VAR_DICT), &t_dict_string, VV_RO}, ! {VV_NAME("sizeofint", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("sizeoflong", VAR_NUMBER), NULL, VV_RO}, ! {VV_NAME("sizeofpointer", VAR_NUMBER), NULL, VV_RO}, }; // shorthand ! #define vv_tv_type vv_di.di_tv.v_type #define vv_nr vv_di.di_tv.vval.v_number #define vv_float vv_di.di_tv.vval.v_float #define vv_str vv_di.di_tv.vval.v_string *************** *** 214,220 **** p->vv_di.di_flags = DI_FLAGS_FIX; // add to v: scope dict, unless the value is not always available ! if (p->vv_type != VAR_UNKNOWN) hash_add(&vimvarht, p->vv_di.di_key); if (p->vv_flags & VV_COMPAT) // add to compat scope dict --- 215,221 ---- p->vv_di.di_flags = DI_FLAGS_FIX; // add to v: scope dict, unless the value is not always available ! if (p->vv_tv_type != VAR_UNKNOWN) hash_add(&vimvarht, p->vv_di.di_key); if (p->vv_flags & VV_COMPAT) // add to compat scope dict *************** *** 510,516 **** { *save_tv = vimvars[idx].vv_tv; vimvars[idx].vv_str = NULL; // don't free it now ! if (vimvars[idx].vv_type == VAR_UNKNOWN) hash_add(&vimvarht, vimvars[idx].vv_di.di_key); } --- 511,517 ---- { *save_tv = vimvars[idx].vv_tv; vimvars[idx].vv_str = NULL; // don't free it now ! if (vimvars[idx].vv_tv_type == VAR_UNKNOWN) hash_add(&vimvarht, vimvars[idx].vv_di.di_key); } *************** *** 525,531 **** hashitem_T *hi; vimvars[idx].vv_tv = *save_tv; ! if (vimvars[idx].vv_type == VAR_UNKNOWN) { hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key); if (HASHITEM_EMPTY(hi)) --- 526,532 ---- hashitem_T *hi; vimvars[idx].vv_tv = *save_tv; ! if (vimvars[idx].vv_tv_type == VAR_UNKNOWN) { hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key); if (HASHITEM_EMPTY(hi)) *************** *** 2265,2271 **** void set_vim_var_type(int idx, vartype_T type) { ! vimvars[idx].vv_type = type; } /* --- 2266,2272 ---- void set_vim_var_type(int idx, vartype_T type) { ! vimvars[idx].vv_tv_type = type; } /* *************** *** 2293,2298 **** --- 2294,2307 ---- return &vimvars[idx].vv_tv; } + type_T * + get_vim_var_type(int idx, garray_T *type_list) + { + if (vimvars[idx].vv_type != NULL) + return vimvars[idx].vv_type; + return typval2type_vimvar(&vimvars[idx].vv_tv, type_list); + } + /* * Set v: variable to "tv". Only accepts the same type. * Takes over the value of "tv". *************** *** 2300,2306 **** int set_vim_var_tv(int idx, typval_T *tv) { ! if (vimvars[idx].vv_type != tv->v_type) { emsg(_(e_type_mismatch_for_v_variable)); clear_tv(tv); --- 2309,2315 ---- int set_vim_var_tv(int idx, typval_T *tv) { ! if (vimvars[idx].vv_tv_type != tv->v_type) { emsg(_(e_type_mismatch_for_v_variable)); clear_tv(tv); *************** *** 2430,2436 **** int len) // length of "val" to use or -1 (whole string) { clear_tv(&vimvars[idx].vv_di.di_tv); ! vimvars[idx].vv_type = VAR_STRING; if (val == NULL) vimvars[idx].vv_str = NULL; else if (len == -1) --- 2439,2445 ---- int len) // length of "val" to use or -1 (whole string) { clear_tv(&vimvars[idx].vv_di.di_tv); ! vimvars[idx].vv_tv_type = VAR_STRING; if (val == NULL) vimvars[idx].vv_str = NULL; else if (len == -1) *************** *** 2446,2452 **** set_vim_var_list(int idx, list_T *val) { clear_tv(&vimvars[idx].vv_di.di_tv); ! vimvars[idx].vv_type = VAR_LIST; vimvars[idx].vv_list = val; if (val != NULL) ++val->lv_refcount; --- 2455,2461 ---- set_vim_var_list(int idx, list_T *val) { clear_tv(&vimvars[idx].vv_di.di_tv); ! vimvars[idx].vv_tv_type = VAR_LIST; vimvars[idx].vv_list = val; if (val != NULL) ++val->lv_refcount; *************** *** 2459,2465 **** set_vim_var_dict(int idx, dict_T *val) { clear_tv(&vimvars[idx].vv_di.di_tv); ! vimvars[idx].vv_type = VAR_DICT; vimvars[idx].vv_dict = val; if (val != NULL) { --- 2468,2474 ---- set_vim_var_dict(int idx, dict_T *val) { clear_tv(&vimvars[idx].vv_di.di_tv); ! vimvars[idx].vv_tv_type = VAR_DICT; vimvars[idx].vv_dict = val; if (val != NULL) { *************** *** 3925,3931 **** { struct vimvar *vp = &vimvars[VV_ERRORS]; ! if (vp->vv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL) // Make sure v:errors is a list. set_vim_var_list(VV_ERRORS, list_alloc()); list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, gap->ga_len); --- 3934,3940 ---- { struct vimvar *vp = &vimvars[VV_ERRORS]; ! if (vp->vv_tv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL) // Make sure v:errors is a list. set_vim_var_list(VV_ERRORS, list_alloc()); list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, gap->ga_len); *** ../vim-8.2.3889/src/proto/evalvars.pro 2021-11-22 20:10:14.886598758 +0000 --- src/proto/evalvars.pro 2021-12-24 21:23:15.377098259 +0000 *************** *** 38,43 **** --- 38,44 ---- void set_vim_var_nr(int idx, varnumber_T val); char *get_vim_var_name(int idx); typval_T *get_vim_var_tv(int idx); + type_T *get_vim_var_type(int idx, garray_T *type_list); int set_vim_var_tv(int idx, typval_T *tv); varnumber_T get_vim_var_nr(int idx); char_u *get_vim_var_str(int idx); *************** *** 71,77 **** 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_arg, 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); --- 72,78 ---- 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_arg, typval_T *tv_arg, int copy, int flags_arg, 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.3889/src/vim9instr.c 2021-12-21 12:32:13.296529989 +0000 --- src/vim9instr.c 2021-12-24 21:22:14.045182069 +0000 *************** *** 946,953 **** semsg(_(e_variable_not_found_str), name); return FAIL; } ! type = typval2type_vimvar(get_vim_var_tv(vidx), cctx->ctx_type_list); ! return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type); } --- 946,952 ---- semsg(_(e_variable_not_found_str), name); return FAIL; } ! type = get_vim_var_type(vidx, cctx->ctx_type_list); return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type); } *** ../vim-8.2.3889/src/testdir/test_vim9_expr.vim 2021-12-22 21:40:29.350644184 +0000 --- src/testdir/test_vim9_expr.vim 2021-12-24 21:30:28.332501591 +0000 *************** *** 1821,1828 **** enddef def Test_expr7_vimvar() var old: list = v:oldfiles ! var compl: dict = v:completed_item CheckDefFailure(["var old: list = v:oldfiles"], 'E1012: Type mismatch; expected list but got list', 1) CheckScriptFailure(['vim9script', 'v:oldfiles = ["foo"]', "var old: list = v:oldfiles"], 'E1012: Type mismatch; expected list but got list', 3) --- 1821,1841 ---- enddef def Test_expr7_vimvar() + v:errors = [] + var errs: list = v:errors + CheckDefFailure(['var errs: list = v:errors'], 'E1012:') + var old: list = v:oldfiles ! CheckDefFailure(['var old: list = v:oldfiles'], 'E1012:') ! ! var compl: dict = v:completed_item ! CheckDefFailure(['var compl: dict = v:completed_item'], 'E1012:') ! ! var args: list = v:argv ! CheckDefFailure(['var args: list = v:argv'], 'E1012:') ! ! var colors: dict = v:colornames ! CheckDefFailure(['var colors: dict = v:colornames'], 'E1012:') CheckDefFailure(["var old: list = v:oldfiles"], 'E1012: Type mismatch; expected list but got list', 1) CheckScriptFailure(['vim9script', 'v:oldfiles = ["foo"]', "var old: list = v:oldfiles"], 'E1012: Type mismatch; expected list but got list', 3) *** ../vim-8.2.3889/src/version.c 2021-12-24 20:47:34.748104242 +0000 --- src/version.c 2021-12-24 21:12:18.429977544 +0000 *************** *** 751,752 **** --- 751,754 ---- { /* Add new patch number below this line */ + /**/ + 3890, /**/ -- hundred-and-one symptoms of being an internet addict: 92. It takes you two hours to check all 14 of your mailboxes. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///