mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 9.1.0299: Vim9: return type not set for a lambda assigned to script var
Problem: Vim9: return type not set for a lambda assigned to script var (Ernie Rael) Solution: Correctly determine the return type (Yegappan Lakshmanan) fixes: #14445 closes: #14473 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
b988c7a95f
commit
7f5202143b
@@ -1104,6 +1104,27 @@ def Test_assignment_partial()
|
|||||||
Ref(0)
|
Ref(0)
|
||||||
END
|
END
|
||||||
v9.CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected string but got number')
|
v9.CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected string but got number')
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
var Fn1 = () => {
|
||||||
|
return 10
|
||||||
|
}
|
||||||
|
assert_equal('func(): number', typename(Fn1))
|
||||||
|
var Fn2 = () => {
|
||||||
|
return "a"
|
||||||
|
}
|
||||||
|
assert_equal('func(): string', typename(Fn2))
|
||||||
|
var Fn3 = () => {
|
||||||
|
return {a: [1]}
|
||||||
|
}
|
||||||
|
assert_equal('func(): dict<list<number>>', typename(Fn3))
|
||||||
|
var Fn4 = (...l: list<string>) => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
assert_equal('func(...list<string>): list<any>', typename(Fn4))
|
||||||
|
END
|
||||||
|
v9.CheckSourceSuccess(['vim9script'] + lines)
|
||||||
|
v9.CheckSourceSuccess(['def Xfunc()'] + lines + ['enddef', 'defcompile'])
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assignment_list_any_index()
|
def Test_assignment_list_any_index()
|
||||||
|
@@ -112,11 +112,13 @@ enddef
|
|||||||
|
|
||||||
# :source a list of "lines" and check whether it fails with "error"
|
# :source a list of "lines" and check whether it fails with "error"
|
||||||
export def CheckSourceFailure(lines: list<string>, error: string, lnum = -3)
|
export def CheckSourceFailure(lines: list<string>, error: string, lnum = -3)
|
||||||
|
var cwd = getcwd()
|
||||||
new
|
new
|
||||||
setline(1, lines)
|
setline(1, lines)
|
||||||
try
|
try
|
||||||
assert_fails('source', error, lines, lnum)
|
assert_fails('source', error, lines, lnum)
|
||||||
finally
|
finally
|
||||||
|
chdir(cwd)
|
||||||
bw!
|
bw!
|
||||||
endtry
|
endtry
|
||||||
enddef
|
enddef
|
||||||
@@ -124,22 +126,26 @@ enddef
|
|||||||
# :source a list of "lines" and check whether it fails with the list of
|
# :source a list of "lines" and check whether it fails with the list of
|
||||||
# "errors"
|
# "errors"
|
||||||
export def CheckSourceFailureList(lines: list<string>, errors: list<string>, lnum = -3)
|
export def CheckSourceFailureList(lines: list<string>, errors: list<string>, lnum = -3)
|
||||||
|
var cwd = getcwd()
|
||||||
new
|
new
|
||||||
setline(1, lines)
|
setline(1, lines)
|
||||||
try
|
try
|
||||||
assert_fails('source', errors, lines, lnum)
|
assert_fails('source', errors, lines, lnum)
|
||||||
finally
|
finally
|
||||||
|
chdir(cwd)
|
||||||
bw!
|
bw!
|
||||||
endtry
|
endtry
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
# :source a list of "lines" and check whether it succeeds
|
# :source a list of "lines" and check whether it succeeds
|
||||||
export def CheckSourceSuccess(lines: list<string>)
|
export def CheckSourceSuccess(lines: list<string>)
|
||||||
|
var cwd = getcwd()
|
||||||
new
|
new
|
||||||
setline(1, lines)
|
setline(1, lines)
|
||||||
try
|
try
|
||||||
:source
|
:source
|
||||||
finally
|
finally
|
||||||
|
chdir(cwd)
|
||||||
bw!
|
bw!
|
||||||
endtry
|
endtry
|
||||||
enddef
|
enddef
|
||||||
|
@@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
299,
|
||||||
/**/
|
/**/
|
||||||
298,
|
298,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -417,6 +417,36 @@ type_any_or_unknown(type_T *type)
|
|||||||
|| type->tt_type == VAR_UNKNOWN;
|
|| type->tt_type == VAR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a type_T for a partial typval in "tv".
|
||||||
|
*/
|
||||||
|
static type_T *
|
||||||
|
partial_typval2type(typval_T *tv, ufunc_T *ufunc, garray_T *type_gap)
|
||||||
|
{
|
||||||
|
partial_T *pt = tv->vval.v_partial;
|
||||||
|
type_T *type;
|
||||||
|
|
||||||
|
type = get_type_ptr(type_gap);
|
||||||
|
if (type == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*type = *ufunc->uf_func_type;
|
||||||
|
if (type->tt_argcount >= 0 && pt->pt_argc > 0)
|
||||||
|
{
|
||||||
|
type->tt_argcount -= pt->pt_argc;
|
||||||
|
type->tt_min_argcount -= pt->pt_argc;
|
||||||
|
if (type->tt_argcount > 0 && func_type_add_arg_types(type,
|
||||||
|
type->tt_argcount, type_gap) == OK)
|
||||||
|
for (int i = 0; i < type->tt_argcount; ++i)
|
||||||
|
type->tt_args[i] =
|
||||||
|
ufunc->uf_func_type->tt_args[i + pt->pt_argc];
|
||||||
|
}
|
||||||
|
if (pt->pt_func != NULL)
|
||||||
|
type->tt_member = pt->pt_func->uf_ret_type;
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a type_T for a typval_T.
|
* Get a type_T for a typval_T.
|
||||||
* "type_gap" is used to temporarily create types in.
|
* "type_gap" is used to temporarily create types in.
|
||||||
@@ -569,27 +599,8 @@ typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int flags)
|
|||||||
set_function_type(ufunc);
|
set_function_type(ufunc);
|
||||||
if (ufunc->uf_func_type != NULL)
|
if (ufunc->uf_func_type != NULL)
|
||||||
{
|
{
|
||||||
if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL
|
if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL)
|
||||||
&& tv->vval.v_partial->pt_argc > 0)
|
return partial_typval2type(tv, ufunc, type_gap);
|
||||||
{
|
|
||||||
type = get_type_ptr(type_gap);
|
|
||||||
if (type == NULL)
|
|
||||||
return NULL;
|
|
||||||
*type = *ufunc->uf_func_type;
|
|
||||||
if (type->tt_argcount >= 0)
|
|
||||||
{
|
|
||||||
type->tt_argcount -= tv->vval.v_partial->pt_argc;
|
|
||||||
type->tt_min_argcount -= tv->vval.v_partial->pt_argc;
|
|
||||||
if (type->tt_argcount > 0
|
|
||||||
&& func_type_add_arg_types(type,
|
|
||||||
type->tt_argcount, type_gap) == OK)
|
|
||||||
for (int i = 0; i < type->tt_argcount; ++i)
|
|
||||||
type->tt_args[i] =
|
|
||||||
ufunc->uf_func_type->tt_args[
|
|
||||||
i + tv->vval.v_partial->pt_argc];
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
return ufunc->uf_func_type;
|
return ufunc->uf_func_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -737,12 +748,14 @@ check_typval_type(type_T *expected, typval_T *actual_tv, where_T where)
|
|||||||
{
|
{
|
||||||
res = check_type_maybe(expected, actual_type, TRUE, where);
|
res = check_type_maybe(expected, actual_type, TRUE, where);
|
||||||
if (res == MAYBE && !(actual_type->tt_type == VAR_FUNC
|
if (res == MAYBE && !(actual_type->tt_type == VAR_FUNC
|
||||||
&& actual_type->tt_member == &t_unknown))
|
&& (actual_type->tt_member == &t_unknown
|
||||||
|
|| actual_type->tt_member == NULL)))
|
||||||
{
|
{
|
||||||
// If a type check is needed that means assigning "any" or
|
// If a type check is needed that means assigning "any" or
|
||||||
// "unknown" to a more specific type, which fails here.
|
// "unknown" to a more specific type, which fails here.
|
||||||
// Except when it looks like a lambda, since they have an
|
// Except when it looks like a lambda, since they have an
|
||||||
// incomplete type.
|
// incomplete type. A legacy lambda function has a NULL return
|
||||||
|
// type.
|
||||||
type_mismatch_where(expected, actual_type, where);
|
type_mismatch_where(expected, actual_type, where);
|
||||||
res = FAIL;
|
res = FAIL;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user