summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-01-16 18:06:21 +0000
committerBram Moolenaar <Bram@vim.org>2022-01-16 18:06:21 +0000
commitc84287d6d8dd055bb6e30605465a23a8addb6fde (patch)
tree125f6d9e504f7b676d137e7230522ec92ba67e0d
parentdc98776f89689846466462767be75c6b63b6630f (diff)
downloadvim-git-c84287d6d8dd055bb6e30605465a23a8addb6fde.tar.gz
patch 8.2.4114: Vim9: type checking for a funcref does not work for methodv8.2.4114
Problem: Vim9: type checking for a funcref does not work for when it is used in a method. Solution: Pass the base to where the type is checked.
-rw-r--r--src/proto/vim9type.pro3
-rw-r--r--src/testdir/test_vim9_expr.vim8
-rw-r--r--src/userfunc.c3
-rw-r--r--src/version.c2
-rw-r--r--src/vim9type.c23
5 files changed, 31 insertions, 8 deletions
diff --git a/src/proto/vim9type.pro b/src/proto/vim9type.pro
index 015531c1e..1c80cbf55 100644
--- a/src/proto/vim9type.pro
+++ b/src/proto/vim9type.pro
@@ -12,12 +12,11 @@ type_T *typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags);
type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap);
int check_typval_arg_type(type_T *expected, typval_T *actual_tv, char *func_name, int arg_idx);
int check_typval_type(type_T *expected, typval_T *actual_tv, where_T where);
-void type_mismatch(type_T *expected, type_T *actual);
void arg_type_mismatch(type_T *expected, type_T *actual, int arg_idx);
void type_mismatch_where(type_T *expected, type_T *actual, where_T where);
int check_type(type_T *expected, type_T *actual, int give_msg, where_T where);
int check_type_maybe(type_T *expected, type_T *actual, int give_msg, where_T where);
-int check_argument_types(type_T *type, typval_T *argvars, int argcount, char_u *name);
+int check_argument_types(type_T *type, typval_T *argvars, int argcount, typval_T *base_tv, char_u *name);
char_u *skip_type(char_u *start, int optional);
type_T *parse_type(char_u **arg, garray_T *type_gap, int give_error);
int equal_type(type_T *type1, type_T *type2, int flags);
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index 039387dc3..e1b48d7db 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -3136,6 +3136,14 @@ def Test_expr7_method_call()
var sorted = [3, 1, 2]
-> sort()
assert_equal([1, 2, 3], sorted)
+
+ def SetNumber(n: number)
+ g:number = n
+ enddef
+ const Setit = SetNumber
+ len('text')->Setit()
+ assert_equal(4, g:number)
+ unlet g:number
END
CheckDefAndScriptSuccess(lines)
diff --git a/src/userfunc.c b/src/userfunc.c
index 1dd5612b9..0fb042e38 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -3386,7 +3386,8 @@ call_func(
&& funcexe->fe_evaluate)
{
// Check that the argument types are OK for the types of the funcref.
- if (check_argument_types(funcexe->fe_check_type, argvars, argcount,
+ if (check_argument_types(funcexe->fe_check_type,
+ argvars, argcount, funcexe->fe_basetv,
(name != NULL) ? name : funcname) == FAIL)
error = FCERR_OTHER;
}
diff --git a/src/version.c b/src/version.c
index 886267428..d75555958 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 */
/**/
+ 4114,
+/**/
4113,
/**/
4112,
diff --git a/src/vim9type.c b/src/vim9type.c
index 5b85c8e53..82c1b5f45 100644
--- a/src/vim9type.c
+++ b/src/vim9type.c
@@ -687,6 +687,7 @@ check_type_maybe(
/*
* Check that the arguments of "type" match "argvars[argcount]".
+ * "base_tv" is from "expr->Func()".
* Return OK/FAIL.
*/
int
@@ -694,19 +695,21 @@ check_argument_types(
type_T *type,
typval_T *argvars,
int argcount,
+ typval_T *base_tv,
char_u *name)
{
int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
int i;
+ int totcount = argcount + (base_tv == NULL ? 0 : 1);
if (type->tt_type != VAR_FUNC && type->tt_type != VAR_PARTIAL)
return OK; // just in case
- if (argcount < type->tt_min_argcount - varargs)
+ if (totcount < type->tt_min_argcount - varargs)
{
semsg(_(e_not_enough_arguments_for_function_str), name);
return FAIL;
}
- if (!varargs && type->tt_argcount >= 0 && argcount > type->tt_argcount)
+ if (!varargs && type->tt_argcount >= 0 && totcount > type->tt_argcount)
{
semsg(_(e_too_many_arguments_for_function_str), name);
return FAIL;
@@ -715,15 +718,25 @@ check_argument_types(
return OK; // cannot check
- for (i = 0; i < argcount; ++i)
+ for (i = 0; i < totcount; ++i)
{
- type_T *expected;
+ type_T *expected;
+ typval_T *tv;
+ if (base_tv != NULL)
+ {
+ if (i == 0)
+ tv = base_tv;
+ else
+ tv = &argvars[i - 1];
+ }
+ else
+ tv = &argvars[i];
if (varargs && i >= type->tt_argcount - 1)
expected = type->tt_args[type->tt_argcount - 1]->tt_member;
else
expected = type->tt_args[i];
- if (check_typval_arg_type(expected, &argvars[i], NULL, i + 1) == FAIL)
+ if (check_typval_arg_type(expected, tv, NULL, i + 1) == FAIL)
return FAIL;
}
return OK;