# HG changeset patch # User Bram Moolenaar # Date 1589144404 -7200 # Node ID fc2d76e0994c0005c65d0b88f43bb87bdf2c2a2c # Parent 6f2382829d914e6e20e5edb6977dc12d718a2017 patch 8.2.0733: Vim9: assigning to dict or list argument does not work Commit: https://github.com/vim/vim/commit/cb2bdb1c6d8b6df4a3d9cfb1ad9e602dace5d310 Author: Bram Moolenaar Date: Sun May 10 22:53:56 2020 +0200 patch 8.2.0733: Vim9: assigning to dict or list argument does not work Problem: Vim9: assigning to dict or list argument does not work. Solution: Recognize an argument as assignment target. diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -193,6 +193,26 @@ def Test_using_var_as_arg() call delete('Xdef') enddef +def DictArg(arg: dict) + arg['key'] = 'value' +enddef + +def ListArg(arg: list) + arg[0] = 'value' +enddef + +def Test_assign_to_argument() + " works for dict and list + let d: dict = {} + DictArg(d) + assert_equal('value', d['key']) + let l: list = [] + ListArg(l) + assert_equal('value', l[0]) + + call CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef'], 'E1090:') +enddef + def Test_call_func_defined_later() call assert_equal('one', g:DefinedLater('one')) call assert_fails('call NotDefined("one")', 'E117:') diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 733, +/**/ 732, /**/ 731, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -135,6 +135,7 @@ struct cctx_S { static char e_var_notfound[] = N_("E1001: variable not found: %s"); static char e_syntax_at[] = N_("E1002: Syntax error at %s"); +static char e_used_as_arg[] = N_("E1006: %s is used as an argument"); static void delete_def_function_contents(dfunc_T *dfunc); static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx); @@ -1652,7 +1653,7 @@ reserve_local(cctx_T *cctx, char_u *name if (lookup_arg(name, len, NULL, NULL, NULL, cctx) == OK) { - emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len); + emsg_namelen(_(e_used_as_arg), name, (int)len); return NULL; } @@ -4592,6 +4593,7 @@ compile_assignment(char_u *arg, exarg_T type_T *type = &t_any; type_T *member_type = &t_any; lvar_T *lvar = NULL; + lvar_T arg_lvar; char_u *name; char_u *sp; int has_type = FALSE; @@ -4760,6 +4762,19 @@ compile_assignment(char_u *arg, exarg_T } lvar = lookup_local(arg, varlen, cctx); + if (lvar == NULL + && lookup_arg(arg, varlen, + &arg_lvar.lv_idx, &arg_lvar.lv_type, + &arg_lvar.lv_from_outer, cctx) == OK) + { + if (is_decl) + { + semsg(_(e_used_as_arg), name); + goto theend; + } + arg_lvar.lv_const = 0; + lvar = &arg_lvar; + } if (lvar != NULL) { if (is_decl) @@ -4861,13 +4876,13 @@ compile_assignment(char_u *arg, exarg_T member_type = type; if (var_end > arg + varlen) { + // Something follows after the variable: "var[idx]". if (is_decl) { emsg(_("E1087: cannot use an index when declaring a variable")); goto theend; } - // Something follows after the variable: "var[idx]". if (arg[varlen] == '[') { has_index = TRUE; @@ -4884,6 +4899,11 @@ compile_assignment(char_u *arg, exarg_T goto theend; } } + else if (lvar == &arg_lvar) + { + semsg(_("E1090: Cannot assign to argument %s"), name); + goto theend; + } if (heredoc) { @@ -6515,6 +6535,8 @@ compile_def_function(ufunc_T *ufunc, int oplen = assignment_len(skipwhite(var_end), &heredoc); if (oplen > 0) { + size_t len = p - ea.cmd; + // Recognize an assignment if we recognize the variable // name: // "g:var = expr" @@ -6527,10 +6549,12 @@ compile_def_function(ufunc_T *ufunc, int if (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@' - || ((p - ea.cmd) > 2 && ea.cmd[1] == ':') - || lookup_local(ea.cmd, p - ea.cmd, &cctx) != NULL - || lookup_script(ea.cmd, p - ea.cmd) == OK - || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL) + || ((len) > 2 && ea.cmd[1] == ':') + || lookup_local(ea.cmd, len, &cctx) != NULL + || lookup_arg(ea.cmd, len, NULL, NULL, + NULL, &cctx) == OK + || lookup_script(ea.cmd, len) == OK + || find_imported(ea.cmd, len, &cctx) != NULL) { line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx); if (line == NULL)