comparison src/vim9class.c @ 33211:71a097aab64d v9.0.1883

patch 9.0.1883: Vim9: Calling an interface method using a child object fails Commit: https://github.com/vim/vim/commit/cc0bcf4c9f4133750f5ee99c685ba995a1b840fd Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Fri Sep 8 19:12:03 2023 +0200 patch 9.0.1883: Vim9: Calling an interface method using a child object fails Problem: Vim9: Calling an interface method using a child object fails Solution: Search methods of parent class When a class implementing an interface is extended by another class and a child class instance is passed to a function that accepts the interface, calling an interface method doesn't work properly. closes: #13053 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
author Christian Brabandt <cb@256bit.org>
date Fri, 08 Sep 2023 19:15:08 +0200
parents 36aebbf8389f
children 499ba27ba0f6
comparison
equal deleted inserted replaced
33210:039954b5721d 33211:71a097aab64d
235 // index can be used directly and there is no need to search for the method 235 // index can be used directly and there is no need to search for the method
236 // index in one of the child classes. 236 // index in one of the child classes.
237 if (cl == itf) 237 if (cl == itf)
238 return idx; 238 return idx;
239 239
240 itf2class_T *i2c = NULL; 240 itf2class_T *i2c = NULL;
241 int searching = TRUE; 241 int searching = TRUE;
242 int method_offset = 0;
243
242 for (class_T *super = cl; super != NULL && searching; 244 for (class_T *super = cl; super != NULL && searching;
243 super = super->class_extends) 245 super = super->class_extends)
246 {
244 for (i2c = itf->class_itf2class; i2c != NULL; i2c = i2c->i2c_next) 247 for (i2c = itf->class_itf2class; i2c != NULL; i2c = i2c->i2c_next)
248 {
245 if (i2c->i2c_class == super && i2c->i2c_is_method == is_method) 249 if (i2c->i2c_class == super && i2c->i2c_is_method == is_method)
246 { 250 {
247 searching = FALSE; 251 searching = FALSE;
248 break; 252 break;
249 } 253 }
254 }
255 if (searching && is_method)
256 // The parent class methods are stored after the current class
257 // methods.
258 method_offset += is_static
259 ? super->class_class_function_count_child
260 : super->class_obj_method_count_child;
261 }
250 if (i2c == NULL) 262 if (i2c == NULL)
251 { 263 {
252 siemsg("class %s not found on interface %s", 264 siemsg("class %s not found on interface %s",
253 cl->class_name, itf->class_name); 265 cl->class_name, itf->class_name);
254 return 0; 266 return 0;
271 } 283 }
272 else 284 else
273 { 285 {
274 // A table follows the i2c for the class 286 // A table follows the i2c for the class
275 int *table = (int *)(i2c + 1); 287 int *table = (int *)(i2c + 1);
276 return table[idx]; 288 // "method_offset" is 0, if method is in the current class. If method
289 // is in a parent class, then it is non-zero.
290 return table[idx] + method_offset;
277 } 291 }
278 } 292 }
279 293
280 /* 294 /*
281 * Check whether a class named "extends_name" is present. If the class is 295 * Check whether a class named "extends_name" is present. If the class is