Skip to content

Commit

Permalink
patch 8.2.2983: Vim9: an inline function requires specifying the retu…
Browse files Browse the repository at this point in the history
…rn type

Problem:    Vim9: an inline function requires specifying the return type.
Solution:   Make the return type optional.
  • Loading branch information
brammool committed Jun 12, 2021
1 parent 7423577 commit a993153
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 6 deletions.
8 changes: 6 additions & 2 deletions src/eval.c
Expand Up @@ -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;
Expand Down
20 changes: 20 additions & 0 deletions src/testdir/test_vim9_func.vim
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion src/userfunc.c
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/version.c
Expand Up @@ -750,6 +750,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2983,
/**/
2982,
/**/
Expand Down
15 changes: 12 additions & 3 deletions src/vim9compile.c
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit a993153

Please sign in to comment.