[vim/vim] Vim9: :def function in legacy script can create a script variable by assignment (Issue #21378)

5 views
Skip to first unread message

h_east

unread,
Sep 27, 2026, 5:58:37 AM (4 days ago) Sep 27
to vim/vim, Subscribed
h-east created an issue (vim/vim#21378)

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:ccc

This 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
enddef

and 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.

—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/21378@github.com>

h_east

unread,
Sep 27, 2026, 1:02:29 PM (4 days ago) Sep 27
to vim/vim, Subscribed
h-east left a comment (vim/vim#21378)

One more data point. Without the "s:" prefix the same assignment is
rejected:

let s:aaa = 1

def Aaa()
  bbb = 2    # E476: Invalid command: bbb = 2
enddef
call Aaa()

So in a :def function of a legacy script, of these three lines only the
last one works, and it creates s:bbb:

bbb = 2        # E476
var s:bbb = 2  # E1101
s:bbb = 2      # creates s:bbb

":help vim9-s:var" states that "s:" is optional there, yet adding it
changes an error into creating a new variable.

—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/21378/5857910029@github.com>

Christian Brabandt

unread,
Sep 28, 2026, 3:31:22 PM (3 days ago) Sep 28
to vim/vim, Subscribed
chrisbra left a comment (vim/vim#21378)

fixed by #21379

—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/21378/5876988877@github.com>

Reply all
Reply to author
Forward
0 new messages