Mercurial > vim
diff src/vim9class.c @ 33401:bb99820510ef v9.0.1959
patch 9.0.1959: Vim9: methods parameters and types are covariant
Commit: https://github.com/vim/vim/commit/f3b68d4759a040ed0c4844c279ea3c779b3863ff
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Fri Sep 29 22:50:02 2023 +0200
patch 9.0.1959: Vim9: methods parameters and types are covariant
Problem: Vim9: methods parameters and types are covariant
Solution: Support contra-variant type check for object method arguments
(similar to Dart).
closes: #12965
closes: #13221
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Fri, 29 Sep 2023 23:00:04 +0200 |
parents | 577ef266309d |
children | 97ceabebaeaf |
line wrap: on
line diff
--- a/src/vim9class.c +++ b/src/vim9class.c @@ -2561,7 +2561,7 @@ inside_class(cctx_T *cctx_arg, class_T * { for (cctx_T *cctx = cctx_arg; cctx != NULL; cctx = cctx->ctx_outer) if (cctx->ctx_ufunc != NULL - && class_instance_of(cctx->ctx_ufunc->uf_class, cl)) + && class_instance_of(cctx->ctx_ufunc->uf_class, cl, TRUE)) return TRUE; return FALSE; } @@ -2871,29 +2871,39 @@ member_not_found_msg(class_T *cl, vartyp * interfaces matches the class "other_cl". */ int -class_instance_of(class_T *cl, class_T *other_cl) +class_instance_of(class_T *cl, class_T *other_cl, int covariance_check) { if (cl == other_cl) return TRUE; - // Recursively check the base classes. - for (; cl != NULL; cl = cl->class_extends) + if (covariance_check) { - if (cl == other_cl) - return TRUE; - // Check the implemented interfaces and the super interfaces - for (int i = cl->class_interface_count - 1; i >= 0; --i) + // Recursively check the base classes. + for (; cl != NULL; cl = cl->class_extends) { - class_T *intf = cl->class_interfaces_cl[i]; - while (intf != NULL) + if (cl == other_cl) + return TRUE; + // Check the implemented interfaces and the super interfaces + for (int i = cl->class_interface_count - 1; i >= 0; --i) { - if (intf == other_cl) - return TRUE; - // check the super interfaces - intf = intf->class_extends; + class_T *intf = cl->class_interfaces_cl[i]; + while (intf != NULL) + { + if (intf == other_cl) + return TRUE; + // check the super interfaces + intf = intf->class_extends; + } } } } + else + { + // contra-variance + for (; other_cl != NULL; other_cl = other_cl->class_extends) + if (cl == other_cl) + return TRUE; + } return FALSE; } @@ -2928,7 +2938,7 @@ f_instanceof(typval_T *argvars, typval_T } if (class_instance_of(object_tv->vval.v_object->obj_class, - li->li_tv.vval.v_class) == TRUE) + li->li_tv.vval.v_class, TRUE) == TRUE) { rettv->vval.v_number = VVAL_TRUE; return; @@ -2937,8 +2947,9 @@ f_instanceof(typval_T *argvars, typval_T } else if (classinfo_tv->v_type == VAR_CLASS) { - rettv->vval.v_number = class_instance_of(object_tv->vval.v_object->obj_class, - classinfo_tv->vval.v_class); + rettv->vval.v_number = class_instance_of( + object_tv->vval.v_object->obj_class, + classinfo_tv->vval.v_class, TRUE); } }