]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0903: Vim9: cannot use an exported function of an autoload import v9.2.0903
authorHirohito Higashi <h.east.727@gmail.com>
Mon, 3 Aug 2026 20:02:51 +0000 (20:02 +0000)
committerChristian Brabandt <cb@256bit.org>
Mon, 3 Aug 2026 20:02:51 +0000 (20:02 +0000)
Problem:  Using an exported function of a script imported with "import
          autoload" as a value gives E121, unless the script is under an
          "autoload" directory.
Solution: When the name is not a script variable also look for an exported
          function and push a funcref for it (Hirohito Hirohito).

fixes:  #20911
closes: #20922

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/testdir/test_vim9_import.vim
src/version.c
src/vim9execute.c

index 54bbd3f2aaf1900a4ed82c1e7e678fe6c3148e21..4c441b1ca3f2ff85db9d6c5e30792383f1de71b6 100644 (file)
@@ -2843,6 +2843,41 @@ def Test_import_autoload_postponed()
   &rtp = save_rtp
 enddef
 
+def Test_import_autoload_func_as_value()
+  var lines =<< trim END
+      vim9script
+      export def Exported(): string
+        return 'exported'
+      enddef
+  END
+  writefile(lines, 'XimportRelFunc.vim', 'D')
+  writefile(lines, 'XimportRelFunc2.vim', 'D')
+
+  # Using the exported function as a value, not calling it.
+  lines =<< trim END
+      vim9script
+      import autoload './XimportRelFunc.vim'
+      def Func()
+        var Fn: func = XimportRelFunc.Exported
+        assert_equal('exported', Fn())
+      enddef
+      Func()
+  END
+  v9.CheckScriptSuccess(lines)
+
+  # The script is not loaded yet when compiling, thus the name is only
+  # checked when the function runs.
+  lines =<< trim END
+      vim9script
+      import autoload './XimportRelFunc2.vim'
+      def Func()
+        var Fn: func = XimportRelFunc2.NoSuchFunc
+      enddef
+      Func()
+  END
+  v9.CheckScriptFailure(lines, 'E121: Undefined variable: NoSuchFunc', 1)
+enddef
+
 def Test_import_autoload_override()
   mkdir('Xoverdir/autoload', 'pR')
   var save_rtp = &rtp
index 851013e9e555eb2343bc814d38b985b0dfa4e582..2fed34c3a1d50382172fd29aa98c1d65d8bc342a 100644 (file)
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    903,
 /**/
     902,
 /**/
index 1c30338eb845f2b0106624a8755a577ab6a07da8..c8790d634aba3edf2e47c09f6ca1f49e858b78e9 100644 (file)
@@ -4180,9 +4180,30 @@ exec_instructions(ectx_T *ectx)
 
                    if (di == NULL)
                    {
-                       SOURCING_LNUM = iptr->isn_lnum;
-                       semsg(_(e_undefined_variable_str), name);
-                       goto on_error;
+                       ufunc_T *ufunc = NULL;
+
+                       if (iptr->isn_type == ISN_LOADEXPORT)
+                       {
+                           type_T      *type;
+
+                           // Not a variable, it can be an exported function
+                           // used as a value.
+                           (void)find_exported(sid, name, &ufunc, &type,
+                                                        NULL, NULL, FALSE);
+                       }
+                       if (ufunc == NULL)
+                       {
+                           SOURCING_LNUM = iptr->isn_lnum;
+                           semsg(_(e_undefined_variable_str), name);
+                           goto on_error;
+                       }
+                       if (GA_GROW_FAILS(&ectx->ec_stack, 1))
+                           goto theend;
+                       tv = STACK_TV_BOT(0);
+                       tv->v_lock = 0;
+                       ++ectx->ec_stack.ga_len;
+                       tv->v_type = VAR_FUNC;
+                       tv->vval.v_string = vim_strsave(ufunc->uf_name);
                    }
                    else
                    {