Mercurial > vim
diff src/vim9type.c @ 26630:57bc1001160b v8.2.3844
patch 8.2.3844: Vim9: no type error if assigning func(number) to func(string)
Commit: https://github.com/vim/vim/commit/44a8977de467241a2f9959253d06eff53a8baad9
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Dec 18 12:31:33 2021 +0000
patch 8.2.3844: Vim9: no type error if assigning func(number) to func(string)
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)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 18 Dec 2021 13:45:04 +0100 |
parents | fac6673086df |
children | e16806237a70 |
line wrap: on
line diff
--- a/src/vim9type.c +++ b/src/vim9type.c @@ -531,9 +531,31 @@ type_mismatch_where(type_T *expected, ty * 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) +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,17 +590,21 @@ check_type(type_T *expected, type_T *act { // 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, + if (expected->tt_member != &t_unknown) + { + if (actual->tt_member != &t_unknown) + ret = check_type(expected->tt_member, actual->tt_member, FALSE, where); - if (ret == OK && expected->tt_argcount != -1 + 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 == OK && expected->tt_args != NULL + if (ret != FAIL && expected->tt_args != NULL && actual->tt_args != NULL) { int i; @@ -593,10 +619,21 @@ check_type(type_T *expected, type_T *act 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; }