[vim/vim] Vim9: cannot `call()` imported autoload function (Issue #9590)

6 views
Skip to first unread message

lacygoill

unread,
Jan 21, 2022, 6:47:18 PM1/21/22
to vim/vim, Subscribed

Steps to reproduce

Run this shell command:

vim -Nu NONE -S <(tee <<'EOF'
    vim9script
    var dir = '/tmp/.vim'
    &runtimepath = dir
    dir ..= '/autoload'
    dir->mkdir('p')
    var lines =<< trim END
        vim9script
        export def Func()
            echomsg 'from Func()'
        enddef
    END
    lines->writefile(dir .. '/script.vim')
    import autoload 'script.vim'
    call('script.Func', [])
EOF
)

E117 is given:

E117: Unknown function: script.Func

Expected behavior

No error is given. from Func() is echo'ed.

Version of Vim

8.2 Included patches: 1-4174

Environment

Operating system: Ubuntu 20.04.3 LTS
Terminal: xterm
Value of $TERM: xterm-256color
Shell: zsh 5.8

Additional context

If we replace this line:

call('script.Func', [])

With this line:

call('script#Func', [])

The issue disappears:

vim9script
var dir = '/tmp/.vim'
&runtimepath = dir
dir ..= '/autoload'
dir->mkdir('p')
var lines =<< trim END
    vim9script
    export def Func()
        echomsg 'from Func()'
    enddef
END
lines->writefile(dir .. '/script.vim')
import autoload 'script.vim'
call('script#Func', [])
from Func()

As a workaround, we can use eval() and get():

'script.Func'->eval()->get('name')->call([])

Test:

vim9script
var dir = '/tmp/.vim'
&runtimepath = dir
dir ..= '/autoload'
dir->mkdir('p')
var lines =<< trim END
    vim9script
    export def Func()
        echomsg 'from Func()'
    enddef
END
lines->writefile(dir .. '/script.vim')
import autoload 'script.vim'
'script.Func'->eval()->get('name')->call([])
from Func()

But this is cumbersome, and less readable.


I'm not sure it's a bug. Maybe call() is called in the global context, where script.Func is not defined. If so, could we evaluate call() in the context of the script where it's called? Unless it creates issues (could there be a collision with a dict function?).


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9590@github.com>

lacygoill

unread,
Jan 21, 2022, 6:51:55 PM1/21/22
to vim/vim, Subscribed

Unrelated but a word is missing at :help get():

get({func}, {what})
                Get an item with from Funcref {func}.  Possible values for
                {what} are:

In the sentence "Get an item with from Funcref {func}", get an item with what?

As a suggestion, here is a patch:

diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 403f592fc..bd226814e 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -2882,8 +2882,8 @@ get({dict}, {key} [, {default}])
 		Preferably used as a |method|: >
 			mydict->get(key)
 get({func}, {what})
-		Get an item with from Funcref {func}.  Possible values for
-		{what} are:
+		Get an item with string {what} from Funcref {func}.  Possible
+		values for {what} are:
 			"name"	The function name
 			"func"	The function
 			"dict"	The dictionary


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

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

lacygoill

unread,
Jan 22, 2022, 2:10:09 AM1/22/22
to vim/vim, Subscribed

I guess that I could remove the quotes around script.Func:

     ✘           ✘

     v           v

call('script.Func', [])



✔

call(script.Func, [])

Test:

vim9script

var dir = '/tmp/.vim'

&runtimepath = dir

dir ..= '/autoload'

dir->mkdir('p')

var lines =<< trim END

    vim9script

    export def Func()

        echomsg 'from Func()'

    enddef

END

lines->writefile(dir .. '/script.vim')

import autoload 'script.vim'

call(script.Func, [])
from Func()

However, I'm not sure it wouldn't cause the autoload script to be sourced too early. It seems that's not the case:

vim9script

var dir = '/tmp/.vim'

dir->delete('rf')

&runtimepath = dir

dir ..= '/autoload'

dir->mkdir('p')

var lines =<< trim END

    vim9script

    export def Func()

        echomsg 'from Func()'

    enddef

    sleep 5

END

lines->writefile(dir .. '/script.vim')

import autoload 'script.vim'

def Foo()

    call(script.Func, [])

enddef

defcompile
Vim compiles Foo() immediately

However, that does not seem to be consistent with the alternative script#Func name:

vim9script

var dir = '/tmp/.vim'

dir->delete('rf')

&runtimepath = dir

dir ..= '/autoload'

dir->mkdir('p')

var lines =<< trim END

    vim9script

    export def Func()

        echomsg 'from Func()'

    enddef

    sleep 5

END

lines->writefile(dir .. '/script.vim')

import autoload 'script.vim'

def Foo()

    call(script#Func, [])

enddef

defcompile
Vim compiles Foo() after 5 seconds

In this last snippet, notice that Vim takes 5 seconds to compile Foo(), because of the :sleep 5 in the autoload script. This means that the latter was sourced too early. To fix this, we need to quote script#Func when we pass it as an argument to call(). But why is it different when we use script.Func instead of script#Func? Why doesn't Vim source the autoload script as soon as we compile Foo()?

This seems inconsistent.


Reply to this email directly, view it on GitHub, or unsubscribe.


Triage notifications on the go with GitHub Mobile for iOS or Android.

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

Bram Moolenaar

unread,
Jan 22, 2022, 6:00:49 AM1/22/22
to vim/vim, Subscribed

Closed #9590 via 3d8e25a.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issue/9590/issue_event/5936572152@github.com>

Reply all
Reply to author
Forward
0 new messages