Patch 9.0.1184
Problem: Interface of an object is not recognized when checking type.
Solution: Use the interface implemented by an object.
Files: src/vim9type.c, src/structs.h, src/vim9class.c,
src/testdir/test_vim9_class.vim
*** ../vim-9.0.1183/src/vim9type.c 2023-01-11 21:14:11.832106048 +0000
--- src/vim9type.c 2023-01-12 13:54:29.918762015 +0000
***************
*** 876,886 ****
--- 876,896 ----
}
else if (expected->tt_type == VAR_OBJECT)
{
+ // check the class, base class or an implemented interface matches
class_T *cl;
for (cl = (class_T *)actual->tt_member; cl != NULL;
cl = cl->class_extends)
+ {
if ((class_T *)expected->tt_member == cl)
break;
+ int i;
+ for (i = cl->class_interface_count - 1; i >= 0; --i)
+ if ((class_T *)expected->tt_member
+ == cl->class_interfaces_cl[i])
+ break;
+ if (i >= 0)
+ break;
+ }
if (cl == NULL)
ret = FAIL;
}
*** ../vim-9.0.1183/src/structs.h 2023-01-11 15:59:01.175405240 +0000
--- src/structs.h 2023-01-12 13:47:23.316980720 +0000
***************
*** 1500,1505 ****
--- 1500,1506 ----
// interfaces declared for the class
int class_interface_count;
char_u **class_interfaces; // allocated array of names
+ class_T **class_interfaces_cl; // interfaces (counts as reference)
// class members: "static varname"
int class_class_member_count;
*** ../vim-9.0.1183/src/vim9class.c 2023-01-11 15:59:01.175405240 +0000
--- src/vim9class.c 2023-01-12 14:22:27.662808427 +0000
***************
*** 582,590 ****
--- 582,594 ----
}
VIM_CLEAR(extends);
+ class_T **intf_classes = NULL;
+
// Check all "implements" entries are valid.
if (success && ga_impl.ga_len > 0)
{
+ intf_classes = ALLOC_CLEAR_MULT(class_T *, ga_impl.ga_len);
+
for (int i = 0; i < ga_impl.ga_len && success; ++i)
{
char_u *impl = ((char_u **)ga_impl.ga_data)[i];
***************
*** 605,612 ****
success = FALSE;
}
- // check the members of the interface match the members of the class
class_T *ifcl = tv.vval.v_class;
for (int loop = 1; loop <= 2 && success; ++loop)
{
// loop == 1: check class members
--- 609,619 ----
success = FALSE;
}
class_T *ifcl = tv.vval.v_class;
+ intf_classes[i] = ifcl;
+ ++ifcl->class_refcount;
+
+ // check the members of the interface match the members of the class
for (int loop = 1; loop <= 2 && success; ++loop)
{
// loop == 1: check class members
***************
*** 717,722 ****
--- 724,732 ----
cl->class_interfaces[i] = ((char_u **)ga_impl.ga_data)[i];
VIM_CLEAR(ga_impl.ga_data);
ga_impl.ga_len = 0;
+
+ cl->class_interfaces_cl = intf_classes;
+ intf_classes = NULL;
}
// Add class and object members to "cl".
***************
*** 930,935 ****
--- 940,957 ----
{
vim_free(cl->class_name);
vim_free(cl->class_class_functions);
+ if (cl->class_interfaces != NULL)
+ {
+ for (int i = 0; i < cl->class_interface_count; ++i)
+ vim_free(cl->class_interfaces[i]);
+ vim_free(cl->class_interfaces);
+ }
+ if (cl->class_interfaces_cl != NULL)
+ {
+ for (int i = 0; i < cl->class_interface_count; ++i)
+ class_unref(cl->class_interfaces_cl[i]);
+ vim_free(cl->class_interfaces_cl);
+ }
vim_free(cl->class_obj_members);
vim_free(cl->class_obj_methods);
vim_free(cl);
***************
*** 937,942 ****
--- 959,971 ----
vim_free(extends);
class_unref(extends_cl);
+
+ if (intf_classes != NULL)
+ {
+ for (int i = 0; i < ga_impl.ga_len; ++i)
+ class_unref(intf_classes[i]);
+ vim_free(intf_classes);
+ }
ga_clear_strings(&ga_impl);
for (int round = 1; round <= 2; ++round)
***************
*** 1321,1328 ****
--- 1350,1362 ----
class_unref(cl->class_extends);
for (int i = 0; i < cl->class_interface_count; ++i)
+ {
vim_free(((char_u **)cl->class_interfaces)[i]);
+ if (cl->class_interfaces_cl[i] != NULL)
+ class_unref(cl->class_interfaces_cl[i]);
+ }
vim_free(cl->class_interfaces);
+ vim_free(cl->class_interfaces_cl);
for (int i = 0; i < cl->class_class_member_count; ++i)
{
*** ../vim-9.0.1183/src/testdir/test_vim9_class.vim 2023-01-11 21:14:11.832106048 +0000
--- src/testdir/test_vim9_class.vim 2023-01-12 14:25:03.343498208 +0000
***************
*** 455,460 ****
--- 455,478 ----
var o: One = Two.new()
END
v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
+
+ lines =<< trim END
+ vim9script
+
+ interface One
+ def GetMember(): number
+ endinterface
+ class Two implements One
+ this.one = 1
+ def GetMember(): number
+ return this.one
+ enddef
+ endclass
+
+ var o: One = Two.new(5)
+ assert_equal(5, o.GetMember())
+ END
+ v9.CheckScriptSuccess(lines)
enddef
def Test_class_member()
*** ../vim-9.0.1183/src/version.c 2023-01-12 12:33:25.428525183 +0000
--- src/version.c 2023-01-12 13:35:55.706192841 +0000
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 1184,
/**/
--
Normal people believe that if it ain't broke, don't fix it. Engineers believe
that if it ain't broke, it doesn't have enough features yet.
(Scott Adams - The Dilbert principle)
/// Bram Moolenaar -- Br...@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 ///