mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 9.0.1119: type of arguments not checked when calling a partial
Problem: Type of arguments not checked when calling a partial. Solution: Give an error for a wrong argument type. (closes #11753)
This commit is contained in:
@@ -4277,6 +4277,32 @@ func Test_lambda_allocation_failure()
|
|||||||
bw!
|
bw!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
def Test_lambda_argument_type_check()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
def Scan(ll: list<any>): func(func(any))
|
||||||
|
return (Emit: func(any)) => {
|
||||||
|
for e in ll
|
||||||
|
Emit(e)
|
||||||
|
endfor
|
||||||
|
}
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def Sum(Cont: func(func(any))): any
|
||||||
|
var sum = 0.0
|
||||||
|
Cont((v: float) => { # <== NOTE: the lambda expects a float
|
||||||
|
sum += v
|
||||||
|
})
|
||||||
|
return sum
|
||||||
|
enddef
|
||||||
|
|
||||||
|
const ml = [3.0, 2, 7]
|
||||||
|
echo Scan(ml)->Sum()
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected float but got number')
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_multiple_funcref()
|
def Test_multiple_funcref()
|
||||||
# This was using a NULL pointer
|
# This was using a NULL pointer
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
|
@@ -695,6 +695,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 */
|
||||||
|
/**/
|
||||||
|
1119,
|
||||||
/**/
|
/**/
|
||||||
1118,
|
1118,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -376,6 +376,41 @@ get_pt_outer(partial_T *pt)
|
|||||||
return &ptref->pt_outer;
|
return &ptref->pt_outer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check "argcount" arguments on the stack against what "ufunc" expects.
|
||||||
|
* "off" is the offset of arguments on the stack.
|
||||||
|
* Return OK or FAIL.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
check_ufunc_arg_types(ufunc_T *ufunc, int argcount, int off, ectx_T *ectx)
|
||||||
|
{
|
||||||
|
if (ufunc->uf_arg_types != NULL || ufunc->uf_va_type != NULL)
|
||||||
|
{
|
||||||
|
typval_T *argv = STACK_TV_BOT(0) - argcount - off;
|
||||||
|
|
||||||
|
// The function can change at runtime, check that the argument
|
||||||
|
// types are correct.
|
||||||
|
for (int i = 0; i < argcount; ++i)
|
||||||
|
{
|
||||||
|
type_T *type = NULL;
|
||||||
|
|
||||||
|
// assume a v:none argument, using the default value, is always OK
|
||||||
|
if (argv[i].v_type == VAR_SPECIAL
|
||||||
|
&& argv[i].vval.v_number == VVAL_NONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (i < ufunc->uf_args.ga_len && ufunc->uf_arg_types != NULL)
|
||||||
|
type = ufunc->uf_arg_types[i];
|
||||||
|
else if (ufunc->uf_va_type != NULL)
|
||||||
|
type = ufunc->uf_va_type->tt_member;
|
||||||
|
if (type != NULL && check_typval_arg_type(type,
|
||||||
|
&argv[i], NULL, i + 1) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call compiled function "cdf_idx" from compiled code.
|
* Call compiled function "cdf_idx" from compiled code.
|
||||||
* This adds a stack frame and sets the instruction pointer to the start of the
|
* This adds a stack frame and sets the instruction pointer to the start of the
|
||||||
@@ -498,6 +533,10 @@ call_dfunc(
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check the argument types.
|
||||||
|
if (check_ufunc_arg_types(ufunc, argcount, vararg_count, ectx) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
// Reserve space for:
|
// Reserve space for:
|
||||||
// - missing arguments
|
// - missing arguments
|
||||||
// - stack frame
|
// - stack frame
|
||||||
@@ -1345,26 +1384,8 @@ call_by_name(
|
|||||||
|
|
||||||
if (ufunc != NULL)
|
if (ufunc != NULL)
|
||||||
{
|
{
|
||||||
if (ufunc->uf_arg_types != NULL || ufunc->uf_va_type != NULL)
|
if (check_ufunc_arg_types(ufunc, argcount, 0, ectx) == FAIL)
|
||||||
{
|
return FAIL;
|
||||||
int i;
|
|
||||||
typval_T *argv = STACK_TV_BOT(0) - argcount;
|
|
||||||
|
|
||||||
// The function can change at runtime, check that the argument
|
|
||||||
// types are correct.
|
|
||||||
for (i = 0; i < argcount; ++i)
|
|
||||||
{
|
|
||||||
type_T *type = NULL;
|
|
||||||
|
|
||||||
if (i < ufunc->uf_args.ga_len && ufunc->uf_arg_types != NULL)
|
|
||||||
type = ufunc->uf_arg_types[i];
|
|
||||||
else if (ufunc->uf_va_type != NULL)
|
|
||||||
type = ufunc->uf_va_type->tt_member;
|
|
||||||
if (type != NULL && check_typval_arg_type(type,
|
|
||||||
&argv[i], NULL, i + 1) == FAIL)
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return call_ufunc(ufunc, NULL, argcount, ectx, iptr, selfdict);
|
return call_ufunc(ufunc, NULL, argcount, ectx, iptr, selfdict);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user