Vim9: :def function in legacy script can create a script variable by assignment
In a legacy script (no vim9script), a :def function can create a
new script-local variable just by assigning to it:
def s:F()
s:ccc = 1
enddef
call s:F()
echo s:cccThis echoes 1. Declaring the variable in the same place is rejected:
def s:F()
var s:ccc = 1 # E1101: Cannot declare a script variable in a function
enddefand let s:ccc = 1 gives E1126, since :let cannot be used in a
:def function.
Patch 8.2.1373 (#6630) added an error for assigning to a script
variable that does not exist, but only for a function defined in a
Vim9 script ("Check that in Vim9 script the variable was defined").
The check in compile_lhs() still tests
uf_script_ctx_version == SCRIPT_VERSION_VIM9, so a :def function in
a legacy script was left out. (In a Vim9 script the s: prefix itself
has since become an error, E1268.) The help does not cover this case:
:help vim9-s:var only states that "s:" is optional in a :def
function in a legacy script.
This looks inconsistent to me. The body of a :def function follows
Vim9 rules, where a variable is declared before it is used, and
:help E1269 states that script-local variables must be declared at
the script level. Yet var s:ccc = 1 is an error while a plain
s:ccc = 1 creates the variable.
Making this an error (E1089, "Unknown variable") would break a legacy script that relies on it. The error would only be given when the variable does not exist yet at the time the function is compiled; assigning to an existing script variable keeps working.
I went through the legacy scripts under runtime/ that contain a :def
function, and none of them creates a script variable this way. So I
would still like to change it. What do others think? If you know of
a plugin that depends on this, please let me know.
Source: vim/vim