]> granicus.if.org Git - vim/commitdiff
patch 8.2.2983: Vim9: an inline function requires specifying the return type v8.2.2983
authorBram Moolenaar <Bram@vim.org>
Sat, 12 Jun 2021 13:58:16 +0000 (15:58 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 12 Jun 2021 13:58:16 +0000 (15:58 +0200)
Problem:    Vim9: an inline function requires specifying the return type.
Solution:   Make the return type optional.

src/eval.c
src/testdir/test_vim9_func.vim
src/userfunc.c
src/version.c
src/vim9compile.c

index ca181d524f05e4c938d66de22205387829d06361..8a6539e3fcf4bd726e8994ba7bef21e3bb179a6d 100644 (file)
@@ -3530,9 +3530,13 @@ eval7(
                    {
                        ufunc_T *ufunc = rettv->vval.v_partial->pt_func;
 
-                       // compile it here to get the return type
+                       // Compile it here to get the return type.  The return
+                       // type is optional, when it's missing use t_unknown.
+                       // This is recognized in compile_return().
+                       if (ufunc->uf_ret_type->tt_type == VAR_VOID)
+                           ufunc->uf_ret_type = &t_unknown;
                        if (compile_def_function(ufunc,
-                                        TRUE, PROFILING(ufunc), NULL) == FAIL)
+                                        FALSE, PROFILING(ufunc), NULL) == FAIL)
                        {
                            clear_tv(rettv);
                            ret = FAIL;
index 96e144f5dcc52fef43453b05d50966858024516e..925e7c82a1a23bf31e75956b90711a7df8c85a46 100644 (file)
@@ -948,6 +948,26 @@ def Test_lambda_return_type()
       echo FilterWithCond('foo', (v) => v .. '^b')
   END
   CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected func(string): bool but got func(any): string', 1)
+
+  lines =<< trim END
+      var Lambda1 = (x) => {
+              return x
+              }
+      assert_equal('asdf', Lambda1('asdf'))
+      var Lambda2 = (x): string => {
+              return x
+              }
+      assert_equal('foo', Lambda2('foo'))
+  END
+  CheckDefAndScriptSuccess(lines)
+
+  lines =<< trim END
+      var Lambda = (x): string => {
+              return x
+              }
+      echo Lambda(['foo'])
+  END
+  CheckDefExecAndScriptFailure(lines, 'E1012:')
 enddef
 
 def Test_lambda_uses_assigned_var()
index 64e815d04207c93732ce28aa8f6cc69f3083abad..f610c022d61b5722a0f21220f57b8e8177829713 100644 (file)
@@ -1377,7 +1377,7 @@ get_lambda_tv(
                    goto errret;
            }
            else
-               fp->uf_ret_type = &t_any;
+               fp->uf_ret_type = &t_unknown;
        }
 
        fp->uf_lines = newlines;
index 17ae9a4de252c450a29bf594c1b85070c9e404d9..fcb0d927a1f2f8591ec805136d2c6ce59ae17e46 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2983,
 /**/
     2982,
 /**/
index 44c082d415addc4ceb8c705e9ea38cfde48fb0c3..dfd5aaa3cbdde145b617395a9b93a52a8d49573d 100644 (file)
@@ -3565,8 +3565,12 @@ compile_lambda(char_u **arg, cctx_T *cctx)
     ++ufunc->uf_refcount;
     clear_tv(&rettv);
 
-    // Compile the function into instructions.
-    compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx);
+    // Compile it here to get the return type.  The return type is optional,
+    // when it's missing use t_unknown.  This is recognized in
+    // compile_return().
+    if (ufunc->uf_ret_type->tt_type == VAR_VOID)
+       ufunc->uf_ret_type = &t_unknown;
+    compile_def_function(ufunc, FALSE, PROFILING(ufunc), cctx);
 
     // evalarg.eval_tofree_cmdline may have a copy of the last line and "*arg"
     // points into it.  Point to the original line to avoid a dangling pointer.
@@ -5398,10 +5402,15 @@ compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
 
        if (cctx->ctx_skip != SKIP_YES)
        {
+           // "check_return_type" with uf_ret_type set to &t_unknown is used
+           // for an inline function without a specified return type.  Set the
+           // return type here.
            stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
-           if (check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
+           if ((check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
                                || cctx->ctx_ufunc->uf_ret_type == &t_unknown
                                || cctx->ctx_ufunc->uf_ret_type == &t_any))
+                   || (!check_return_type
+                               && cctx->ctx_ufunc->uf_ret_type == &t_unknown))
            {
                cctx->ctx_ufunc->uf_ret_type = stack_type;
            }