To: vim_dev@googlegroups.com Subject: Patch 8.2.4114 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.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. Files: src/vim9type.c, src/proto/vim9type.pro, src/userfunc.c, src/testdir/test_vim9_expr.vim *** ../vim-8.2.4113/src/vim9type.c 2022-01-13 21:15:17.241958539 +0000 --- src/vim9type.c 2022-01-16 18:05:04.815888199 +0000 *************** *** 687,692 **** --- 687,693 ---- /* * Check that the arguments of "type" match "argvars[argcount]". + * "base_tv" is from "expr->Func()". * Return OK/FAIL. */ int *************** *** 694,712 **** type_T *type, typval_T *argvars, int argcount, char_u *name) { int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0; int i; if (type->tt_type != VAR_FUNC && type->tt_type != VAR_PARTIAL) return OK; // just in case ! if (argcount < 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) { semsg(_(e_too_many_arguments_for_function_str), name); return FAIL; --- 695,715 ---- 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 (totcount < type->tt_min_argcount - varargs) { semsg(_(e_not_enough_arguments_for_function_str), name); return FAIL; } ! if (!varargs && type->tt_argcount >= 0 && totcount > type->tt_argcount) { semsg(_(e_too_many_arguments_for_function_str), name); return FAIL; *************** *** 715,729 **** return OK; // cannot check ! for (i = 0; i < argcount; ++i) { ! type_T *expected; 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) return FAIL; } return OK; --- 718,742 ---- return OK; // cannot check ! for (i = 0; i < totcount; ++i) { ! 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, tv, NULL, i + 1) == FAIL) return FAIL; } return OK; *** ../vim-8.2.4113/src/proto/vim9type.pro 2022-01-04 15:16:57.879864882 +0000 --- src/proto/vim9type.pro 2022-01-16 18:00:09.352062881 +0000 *************** *** 12,23 **** 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); 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); --- 12,22 ---- 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 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, 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); *** ../vim-8.2.4113/src/userfunc.c 2022-01-13 21:15:17.233958564 +0000 --- src/userfunc.c 2022-01-16 17:53:30.704180828 +0000 *************** *** 3386,3392 **** && 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, (name != NULL) ? name : funcname) == FAIL) error = FCERR_OTHER; } --- 3386,3393 ---- && 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, funcexe->fe_basetv, (name != NULL) ? name : funcname) == FAIL) error = FCERR_OTHER; } *** ../vim-8.2.4113/src/testdir/test_vim9_expr.vim 2022-01-10 18:50:48.419345326 +0000 --- src/testdir/test_vim9_expr.vim 2022-01-16 18:03:24.591952890 +0000 *************** *** 3136,3141 **** --- 3136,3149 ---- 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) *** ../vim-8.2.4113/src/version.c 2022-01-16 15:52:32.020847559 +0000 --- src/version.c 2022-01-16 18:00:38.600048025 +0000 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 4114, /**/ -- CUSTOMER: Well, can you hang around a couple of minutes? He won't be long. MORTICIAN: Naaah, I got to go on to Robinson's -- they've lost nine today. CUSTOMER: Well, when is your next round? MORTICIAN: Thursday. DEAD PERSON: I think I'll go for a walk. The Quest for the Holy Grail (Monty Python) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///