# HG changeset patch # User Bram Moolenaar # Date 1623506404 -7200 # Node ID 0cba2be8cbd7b534cc72f16506bad9b58503a7ef # Parent a150a8f592f11731e49056d68e2e0c9538d9ef65 patch 8.2.2983: Vim9: an inline function requires specifying the return type Commit: https://github.com/vim/vim/commit/a9931535387e5eb4e6ce62f2a661484de4a1757d Author: Bram Moolenaar Date: Sat Jun 12 15:58:16 2021 +0200 patch 8.2.2983: Vim9: an inline function requires specifying the return type Problem: Vim9: an inline function requires specifying the return type. Solution: Make the return type optional. diff --git a/src/eval.c b/src/eval.c --- 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 --- 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 --- 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 --- 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 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3565,8 +3565,12 @@ compile_lambda(char_u **arg, cctx_T *cct ++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_re 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; }