diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-11-26 17:36:51 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-11-26 17:36:51 +0000 |
commit | 7824fc80f675b8098e6483ce082e287aad14b6da (patch) | |
tree | 7958a448ca9c5d0a45fef498b670a355f2f92b44 | |
parent | bfc5786a61693aaadc3e45f80a2f147c3a6711a3 (diff) | |
download | vim-git-7824fc80f675b8098e6483ce082e287aad14b6da.tar.gz |
patch 8.2.3682: Vim9: assigning to a script variable drops the typev8.2.3682
Problem: Vim9: assigning to a script variable drops the required type.
Solution: Lookup the type of the variable and use it. (closes #9219)
-rw-r--r-- | src/evalvars.c | 20 | ||||
-rw-r--r-- | src/proto/vim9script.pro | 2 | ||||
-rw-r--r-- | src/testdir/test_vim9_assign.vim | 10 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9script.c | 34 |
5 files changed, 40 insertions, 28 deletions
diff --git a/src/evalvars.c b/src/evalvars.c index b1d7b78c8..434fd9611 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -3206,13 +3206,14 @@ set_var( void set_var_const( char_u *name, - type_T *type, + type_T *type_arg, typval_T *tv_arg, int copy, // make copy of value in "tv" int flags_arg, // ASSIGN_CONST, ASSIGN_FINAL, etc. int var_idx) // index for ":let [a, b] = list" { typval_T *tv = tv_arg; + type_T *type = type_arg; typval_T bool_tv; dictitem_T *di; typval_T *dest_tv = NULL; @@ -3334,13 +3335,18 @@ set_var_const( if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0) { where_T where = WHERE_INIT; + svar_T *sv = find_typval_in_script(&di->di_tv); - // 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; + if (sv != NULL) + { + // check the type and adjust to bool if needed + where.wt_index = var_idx; + where.wt_variable = TRUE; + if (check_script_var_type(sv, tv, name, where) == FAIL) + goto failed; + if (type == NULL) + type = sv->sv_type; + } } if ((flags & ASSIGN_FOR_LOOP) == 0 diff --git a/src/proto/vim9script.pro b/src/proto/vim9script.pro index 97c1c92ad..1b2181923 100644 --- a/src/proto/vim9script.pro +++ b/src/proto/vim9script.pro @@ -16,6 +16,6 @@ char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg); void update_vim9_script_var(int create, dictitem_T *di, int flags, typval_T *tv, type_T **type, int do_member); void hide_script_var(scriptitem_T *si, int idx, int func_defined); 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); +int check_script_var_type(svar_T *sv, typval_T *value, char_u *name, where_T where); int check_reserved_name(char_u *name); /* vim: set ft=c : */ diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 0d07e07eb..df8f486f9 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -322,6 +322,16 @@ def Test_skipped_assignment() CheckDefAndScriptSuccess(lines) enddef +def Test_assign_keep_type() + var lines =<< trim END + vim9script + var l: list<number> = [123] + l = [123] + l->add('string') + END + CheckScriptFailure(lines, 'E1012:', 4) +enddef + def Test_assign_unpack() var lines =<< trim END var v1: number diff --git a/src/version.c b/src/version.c index 532b59e82..f328f833c 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3682, +/**/ 3681, /**/ 3680, diff --git a/src/vim9script.c b/src/vim9script.c index 9696dfe81..62341b0ca 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -999,35 +999,29 @@ find_typval_in_script(typval_T *dest) */ int check_script_var_type( - typval_T *dest, + svar_T *sv, typval_T *value, char_u *name, where_T where) { - svar_T *sv = find_typval_in_script(dest); int ret; - if (sv != NULL) + if (sv->sv_const != 0) { - if (sv->sv_const != 0) - { - semsg(_(e_cannot_change_readonly_variable_str), 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); - - clear_tv(value); - value->v_type = VAR_BOOL; - value->v_lock = 0; - value->vval.v_number = val ? VVAL_TRUE : VVAL_FALSE; - } - return ret; + semsg(_(e_cannot_change_readonly_variable_str), 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); - return OK; // not really + clear_tv(value); + value->v_type = VAR_BOOL; + value->v_lock = 0; + value->vval.v_number = val ? VVAL_TRUE : VVAL_FALSE; + } + return ret; } // words that cannot be used as a variable |