[vim/vim] Vim9: "exists()" fails to test existence of list item in compiled code (#8534)

43 views
Skip to first unread message

lacygoill

unread,
Jul 8, 2021, 9:31:33 PM7/8/21
to vim/vim, Subscribed

Describe the bug

In Vim9 script, exists() might fail to test the existence of a list item in compiled code.

To Reproduce

Run this shell command:

vim -Nu NONE -S <(cat <<'EOF'
    vim9script
    def Func()
        var l = ['a', 'b', 'c']
        echomsg exists('l[1]')
    enddef
    Func()
EOF
)

0 is echo'ed.

Expected behavior

1 is echo'ed (or true, not sure). Because the list l contains 3 items; one of which has the index 1 (i.e. 'b'). Therefore, l[1] does exist.

Environment

  • Vim version: 8.2 Included patches: 1-3126
  • OS: Ubuntu 20.04.2 LTS
  • Terminal: XTerm(353)

Additional context

No issue at the script level:

vim9script
var l = ['a', 'b', 'c']
echomsg exists('l[1]')
1

If this is working as intended, maybe it should be documented at :help exists():

varname internal variable (see
|internal-variables|). Also works
for |curly-braces-names|, |Dictionary|
entries, |List| items, etc. Beware
that evaluating an index may cause an
error message for an invalid
expression. E.g.: >
:let l = [1, 2, 3]
:echo exists("l[5]")
0 >
:echo exists("l[xx]")
E121: Undefined variable: xx
0


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.

lacygoill

unread,
Jul 8, 2021, 9:48:13 PM7/8/21
to vim/vim, Subscribed

Closing because I think it's working as intended: at runtime, exists() cannot find a function-local variable, because – I guess – it's on the stack, and it cannot access the latter.


Still, the example given in the help is a bit misleading:

:let l = [1, 2, 3]

:echo exists("l[5]")

Because it can be copied and adapted to successfully detect the existence of a list item inside a legacy function, but not inside a Vim9 one. I'll try to come up with a patch later.

lacygoill

unread,
Jul 8, 2021, 9:48:14 PM7/8/21
to vim/vim, Subscribed

Closed #8534.

lacygoill

unread,
Jul 9, 2021, 11:26:03 PM7/9/21
to vim/vim, Subscribed

I'll try to come up with a patch later.

As a suggestion, here is a patch:

diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index e5f9b4651..c95de2a02 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -4364,6 +4364,20 @@ exists({expr})	The result is a Number, which is |TRUE| if {expr} is defined,
 					   :echo exists("l[xx]")
 <					   E121: Undefined variable: xx
 					   0
+
+					NOTE: In a `:def` function, exists()
+					cannot test the existence of a
+					function-local variable.  The latter is
+					on the stack, and cannot be accessed
+					outside the compiled function.
+					exists() always returns 0 then: >
+					   def Func()
+					     var name = 0
+					     echo exists('name')
+					   enddef
+					   Func()
+					0
+<
 			:cmdname	Ex command: built-in command, user
 					command or command modifier |:command|.
 					Returns:

lacygoill

unread,
Jul 9, 2021, 11:58:03 PM7/9/21
to vim/vim, Subscribed

Using 0 for the variable value could be somehow confusing to the reader, because it's also the output of exists() in this case. Using another arbitrary number like 123 would be less confusing then. New patch:

diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index e5f9b4651..3c8df99ce 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -4364,6 +4364,20 @@
 exists({expr})	The result is a Number, which is |TRUE| if {expr} is defined,
 					   :echo exists("l[xx]")
 <					   E121: Undefined variable: xx
 					   0
+
+					NOTE: In a `:def` function, exists()
+					cannot test the existence of a
+					function-local variable.  The latter is
+					on the stack, and cannot be accessed
+					outside the compiled function.
+					exists() always returns 0 then: >
+					   def Func()
+					     var name = 123
+					     echo exists('name')
+					   enddef
+					   Func()
+					0
+<
 			:cmdname	Ex command: built-in command, user
 					command or command modifier |:command|.
 					Returns:

Bram Moolenaar

unread,
Jul 11, 2021, 9:00:09 AM7/11/21
to vim/vim, Subscribed

I'll add a note in the help, but keep it short, since it's already quite long.

Reply all
Reply to author
Forward
0 new messages