To: vim_dev@googlegroups.com Subject: Patch 8.2.3844 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3844 Problem: Vim9: no type error if assigning a value with type func(number) to a variable of type func(string). Solution: Use check_type_maybe(): return MAYBE if a runtime type check is useful. (issue #8492) Files: src/vim9type.c, src/proto/vim9type.pro, src/vim9compile.c, src/testdir/test_vim9_assign.vim *** ../vim-8.2.3843/src/vim9type.c 2021-12-16 20:56:52.956098576 +0000 --- src/vim9type.c 2021-12-18 12:11:57.602570711 +0000 *************** *** 531,539 **** * Check if the expected and actual types match. * Does not allow for assigning "any" to a specific type. * When "argidx" > 0 it is included in the error message. */ int ! check_type(type_T *expected, type_T *actual, int give_msg, where_T where) { int ret = OK; --- 531,561 ---- * Check if the expected and actual types match. * Does not allow for assigning "any" to a specific type. * When "argidx" > 0 it is included in the error message. + * Return OK if types match. + * Return FAIL if types do not match. */ int ! check_type( ! type_T *expected, ! type_T *actual, ! int give_msg, ! where_T where) ! { ! int ret = check_type_maybe(expected, actual, give_msg, where); ! ! return ret == MAYBE ? OK : ret; ! } ! ! /* ! * As check_type() but return MAYBE when a runtime type check should be used ! * when compiling. ! */ ! int ! check_type_maybe( ! type_T *expected, ! type_T *actual, ! int give_msg, ! where_T where) { int ret = OK; *************** *** 568,584 **** { // If the return type is unknown it can be anything, including // nothing, thus there is no point in checking. ! if (expected->tt_member != &t_unknown ! && actual->tt_member != &t_unknown) ! ret = check_type(expected->tt_member, actual->tt_member, FALSE, where); ! if (ret == OK && expected->tt_argcount != -1 && actual->tt_min_argcount != -1 && (actual->tt_argcount == -1 || (actual->tt_argcount < expected->tt_min_argcount || actual->tt_argcount > expected->tt_argcount))) ret = FAIL; ! if (ret == OK && expected->tt_args != NULL && actual->tt_args != NULL) { int i; --- 590,610 ---- { // If the return type is unknown it can be anything, including // nothing, thus there is no point in checking. ! if (expected->tt_member != &t_unknown) ! { ! if (actual->tt_member != &t_unknown) ! ret = check_type(expected->tt_member, actual->tt_member, FALSE, where); ! else ! ret = MAYBE; ! } ! if (ret != FAIL && expected->tt_argcount != -1 && actual->tt_min_argcount != -1 && (actual->tt_argcount == -1 || (actual->tt_argcount < expected->tt_min_argcount || actual->tt_argcount > expected->tt_argcount))) ret = FAIL; ! if (ret != FAIL && expected->tt_args != NULL && actual->tt_args != NULL) { int i; *************** *** 593,602 **** --- 619,639 ---- break; } } + if (ret == OK && expected->tt_argcount >= 0 + && actual->tt_argcount == -1) + // check the argument count at runtime + ret = MAYBE; } if (ret == FAIL && give_msg) type_mismatch_where(expected, actual, where); } + + if (ret == OK && expected->tt_type != VAR_UNKNOWN + && expected->tt_type != VAR_ANY + && (actual->tt_type == VAR_UNKNOWN || actual->tt_type == VAR_ANY)) + // check the type at runtime + ret = MAYBE; + return ret; } *** ../vim-8.2.3843/src/proto/vim9type.pro 2021-08-09 18:59:01.442811242 +0100 --- src/proto/vim9type.pro 2021-12-18 11:27:09.478181276 +0000 *************** *** 16,21 **** --- 16,22 ---- 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); *** ../vim-8.2.3843/src/vim9compile.c 2021-12-16 20:56:52.956098576 +0000 --- src/vim9compile.c 2021-12-18 12:12:10.578552152 +0000 *************** *** 1061,1066 **** --- 1061,1068 ---- int silent, int actual_is_const) { + int ret; + if (expected == &t_bool && actual != &t_bool && (actual->tt_flags & TTFLAG_BOOL_OK)) { *************** *** 1070,1082 **** return OK; } ! if (check_type(expected, actual, FALSE, where) == OK) return OK; // If the actual type can be the expected type add a runtime check. // If it's a constant a runtime check makes no sense. ! if ((!actual_is_const || actual == &t_any) ! && use_typecheck(actual, expected)) { generate_TYPECHECK(cctx, expected, offset, where.wt_index); return OK; --- 1072,1085 ---- return OK; } ! ret = check_type_maybe(expected, actual, FALSE, where); ! if (ret == OK) return OK; // If the actual type can be the expected type add a runtime check. // If it's a constant a runtime check makes no sense. ! if (ret == MAYBE || ((!actual_is_const || actual == &t_any) ! && use_typecheck(actual, expected))) { generate_TYPECHECK(cctx, expected, offset, where.wt_index); return OK; *** ../vim-8.2.3843/src/testdir/test_vim9_assign.vim 2021-12-17 20:15:30.448830724 +0000 --- src/testdir/test_vim9_assign.vim 2021-12-18 12:18:23.281830204 +0000 *************** *** 2146,2151 **** --- 2146,2168 ---- CheckScriptFailure(lines, 'E704:') enddef + def Test_script_funcref_runtime_type_check() + var lines =<< trim END + vim9script + def FuncWithNumberArg(n: number) + enddef + def Test() + var Ref: func(string) = function(FuncWithNumberArg) + enddef + defcompile + END + # OK at compile time + CheckScriptSuccess(lines) + + # Type check fails at runtime + CheckScriptFailure(lines + ['Test()'], 'E1012: Type mismatch; expected func(string) but got func(number)') + enddef + def Test_inc_dec() var lines =<< trim END var nr = 7 *** ../vim-8.2.3843/src/version.c 2021-12-17 20:52:53.235772342 +0000 --- src/version.c 2021-12-18 12:29:59.819959988 +0000 *************** *** 751,752 **** --- 751,754 ---- { /* Add new patch number below this line */ + /**/ + 3844, /**/ -- Over the years, I've developed my sense of deja vu so acutely that now I can remember things that *have* happened before ... /// 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 ///