forked from aniani/vim
patch 9.0.1974: vim9: using contra-variant type-checks
Problem: vim9: using contra-variant type-checks (after v9.0.1959) Solution: Use invariant type checking instead closes: #13248 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
parent
6d11347260
commit
b32064fedb
@ -547,11 +547,9 @@ Object variables from the base class are all taken over by the child class. It
|
||||
is not possible to override them (unlike some other languages).
|
||||
|
||||
*E1356* *E1357* *E1358*
|
||||
Object methods of the base class can be overruled. The number of arguments
|
||||
must be exactly the same. The method argument type can be a contra-variant
|
||||
type of the base class method argument type. The method return value type can
|
||||
be a covariant type of the base class method return value type. The method of
|
||||
the base class can be called by prefixing "super.".
|
||||
Object methods of the base class can be overruled. The signature (arguments,
|
||||
argument types and return type) must be exactly the same. The method of the
|
||||
base class can be called by prefixing "super.".
|
||||
|
||||
*E1377*
|
||||
The access level of a method (public or private) in a child class should be
|
||||
|
@ -29,5 +29,5 @@ int object_free_nonref(int copyID);
|
||||
void method_not_found_msg(class_T *cl, vartype_T v_type, char_u *name, size_t len);
|
||||
void member_not_found_msg(class_T *cl, vartype_T v_type, char_u *name, size_t len);
|
||||
void f_instanceof(typval_T *argvars, typval_T *rettv);
|
||||
int class_instance_of(class_T *cl, class_T *other_cl, int covariance_check);
|
||||
int class_instance_of(class_T *cl, class_T *other_cl);
|
||||
/* vim: set ft=c : */
|
||||
|
@ -6338,7 +6338,31 @@ def Test_extended_obj_method_type_check()
|
||||
endclass
|
||||
|
||||
class Bar extends Foo
|
||||
def Doit(p: A): C
|
||||
def Doit(p: C): B
|
||||
return B.new()
|
||||
enddef
|
||||
endclass
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class A
|
||||
endclass
|
||||
class B extends A
|
||||
endclass
|
||||
class C extends B
|
||||
endclass
|
||||
|
||||
class Foo
|
||||
def Doit(p: B): B
|
||||
return B.new()
|
||||
enddef
|
||||
endclass
|
||||
|
||||
class Bar extends Foo
|
||||
def Doit(p: B): C
|
||||
return C.new()
|
||||
enddef
|
||||
endclass
|
||||
@ -6362,12 +6386,12 @@ def Test_extended_obj_method_type_check()
|
||||
endclass
|
||||
|
||||
class Bar extends Foo
|
||||
def Doit(p: C): B
|
||||
def Doit(p: A): B
|
||||
return B.new()
|
||||
enddef
|
||||
endclass
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
|
||||
v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<A>): object<B>', 20)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1974,
|
||||
/**/
|
||||
1973,
|
||||
/**/
|
||||
|
@ -2561,7 +2561,7 @@ inside_class(cctx_T *cctx_arg, class_T *cl)
|
||||
{
|
||||
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, TRUE))
|
||||
&& class_instance_of(cctx->ctx_ufunc->uf_class, cl))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
@ -2871,13 +2871,11 @@ member_not_found_msg(class_T *cl, vartype_T v_type, char_u *name, size_t len)
|
||||
* interfaces matches the class "other_cl".
|
||||
*/
|
||||
int
|
||||
class_instance_of(class_T *cl, class_T *other_cl, int covariance_check)
|
||||
class_instance_of(class_T *cl, class_T *other_cl)
|
||||
{
|
||||
if (cl == other_cl)
|
||||
return TRUE;
|
||||
|
||||
if (covariance_check)
|
||||
{
|
||||
// Recursively check the base classes.
|
||||
for (; cl != NULL; cl = cl->class_extends)
|
||||
{
|
||||
@ -2896,14 +2894,6 @@ class_instance_of(class_T *cl, class_T *other_cl, int covariance_check)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// contra-variance
|
||||
for (; other_cl != NULL; other_cl = other_cl->class_extends)
|
||||
if (cl == other_cl)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -2938,7 +2928,7 @@ f_instanceof(typval_T *argvars, typval_T *rettv)
|
||||
}
|
||||
|
||||
if (class_instance_of(object_tv->vval.v_object->obj_class,
|
||||
li->li_tv.vval.v_class, TRUE) == TRUE)
|
||||
li->li_tv.vval.v_class) == TRUE)
|
||||
{
|
||||
rettv->vval.v_number = VVAL_TRUE;
|
||||
return;
|
||||
@ -2947,9 +2937,8 @@ f_instanceof(typval_T *argvars, typval_T *rettv)
|
||||
}
|
||||
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, TRUE);
|
||||
rettv->vval.v_number = class_instance_of(object_tv->vval.v_object->obj_class,
|
||||
classinfo_tv->vval.v_class);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -925,10 +925,14 @@ check_type_maybe(
|
||||
if (actual->tt_class == NULL)
|
||||
return OK; // A null object matches
|
||||
|
||||
// For object method arguments, do a contra-variance type check in
|
||||
// an extended class. For all others, do a co-variance type check.
|
||||
if (class_instance_of(actual->tt_class, expected->tt_class,
|
||||
where.wt_kind != WT_METHOD_ARG) == FALSE)
|
||||
// For object method arguments, do a invariant type check in
|
||||
// an extended class. For all others, do a covariance type check.
|
||||
if (where.wt_kind == WT_METHOD_ARG)
|
||||
{
|
||||
if (actual->tt_class != expected->tt_class)
|
||||
ret = FAIL;
|
||||
}
|
||||
else if (!class_instance_of(actual->tt_class, expected->tt_class))
|
||||
ret = FAIL;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user