summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-06-12 15:58:16 +0200
committerBram Moolenaar <Bram@vim.org>2021-06-12 15:58:16 +0200
commita9931535387e5eb4e6ce62f2a661484de4a1757d (patch)
tree4c6c45dab74c4c5bf3f27939d4ddb8a2282c77dd
parent742357718000927d652b1a98d313a3950571c8ec (diff)
downloadvim-git-a9931535387e5eb4e6ce62f2a661484de4a1757d.tar.gz
patch 8.2.2983: Vim9: an inline function requires specifying the return typev8.2.2983
Problem: Vim9: an inline function requires specifying the return type. Solution: Make the return type optional.
-rw-r--r--src/eval.c8
-rw-r--r--src/testdir/test_vim9_func.vim20
-rw-r--r--src/userfunc.c2
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c15
5 files changed, 41 insertions, 6 deletions
diff --git a/src/eval.c b/src/eval.c
index ca181d524..8a6539e3f 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -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;
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index 96e144f5d..925e7c82a 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -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()
diff --git a/src/userfunc.c b/src/userfunc.c
index 64e815d04..f610c022d 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -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;
diff --git a/src/version.c b/src/version.c
index 17ae9a4de..fcb0d927a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2983,
+/**/
2982,
/**/
2981,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 44c082d41..dfd5aaa3c 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -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;
}