mirror of
https://github.com/vim/vim
synced 2025-07-16 09:12:00 +00:00
patch 9.1.1267: Vim9: no support for type list/dict<object<any>>
Problem: Vim9: no support for type list/dict<object<any>> Solution: add proper support for t_object_any (Yegappan Lakshmanan) closes: #17025 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
7b6add0b4a
commit
de8f8f732a
@ -308,7 +308,7 @@ arg_object(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
|
|||||||
if (type->tt_type == VAR_OBJECT
|
if (type->tt_type == VAR_OBJECT
|
||||||
|| type_any_or_unknown(type))
|
|| type_any_or_unknown(type))
|
||||||
return OK;
|
return OK;
|
||||||
arg_type_mismatch(&t_object, type, context->arg_idx + 1);
|
arg_type_mismatch(&t_object_any, type, context->arg_idx + 1);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,8 +540,8 @@ EXTERN int garbage_collect_at_exit INIT(= FALSE);
|
|||||||
#define t_super (static_types[84])
|
#define t_super (static_types[84])
|
||||||
#define t_const_super (static_types[85])
|
#define t_const_super (static_types[85])
|
||||||
|
|
||||||
#define t_object (static_types[86])
|
#define t_object_any (static_types[86])
|
||||||
#define t_const_object (static_types[87])
|
#define t_const_object_any (static_types[87])
|
||||||
|
|
||||||
#define t_class (static_types[88])
|
#define t_class (static_types[88])
|
||||||
#define t_const_class (static_types[89])
|
#define t_const_class (static_types[89])
|
||||||
@ -731,7 +731,7 @@ EXTERN type_T static_types[96]
|
|||||||
{VAR_CLASS, 0, 0, TTFLAG_STATIC, &t_bool, NULL, NULL},
|
{VAR_CLASS, 0, 0, TTFLAG_STATIC, &t_bool, NULL, NULL},
|
||||||
{VAR_CLASS, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL, NULL},
|
{VAR_CLASS, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL, NULL},
|
||||||
|
|
||||||
// 86: t_object
|
// 86: t_object_any
|
||||||
{VAR_OBJECT, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
|
{VAR_OBJECT, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL},
|
||||||
{VAR_OBJECT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
|
{VAR_OBJECT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL},
|
||||||
|
|
||||||
|
@ -2430,7 +2430,7 @@ def Test_instanceof()
|
|||||||
enddef
|
enddef
|
||||||
Bar()
|
Bar()
|
||||||
END
|
END
|
||||||
v9.CheckSourceScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected object<Unknown> but got string')
|
v9.CheckSourceScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected object<any> but got string')
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
|
@ -564,7 +564,7 @@ def Test_using_null_class()
|
|||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
assert_equal(12, type(null_class))
|
assert_equal(12, type(null_class))
|
||||||
assert_equal('class<Unknown>', typename(null_class))
|
assert_equal('class<any>', typename(null_class))
|
||||||
END
|
END
|
||||||
v9.CheckSourceSuccess(lines)
|
v9.CheckSourceSuccess(lines)
|
||||||
enddef
|
enddef
|
||||||
@ -643,7 +643,6 @@ def Test_object_not_set()
|
|||||||
END
|
END
|
||||||
v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
|
v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
|
||||||
|
|
||||||
# TODO: this should not give an error but be handled at runtime
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
|
|
||||||
@ -660,7 +659,7 @@ def Test_object_not_set()
|
|||||||
enddef
|
enddef
|
||||||
Func()
|
Func()
|
||||||
END
|
END
|
||||||
v9.CheckSourceFailure(lines, 'E1363: Incomplete type', 1)
|
v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
|
||||||
|
|
||||||
# Reference a object variable through a null class object which is stored in a
|
# Reference a object variable through a null class object which is stored in a
|
||||||
# variable of type "any".
|
# variable of type "any".
|
||||||
@ -710,7 +709,7 @@ def Test_null_object_assign_compare()
|
|||||||
def F(): any
|
def F(): any
|
||||||
return nullo
|
return nullo
|
||||||
enddef
|
enddef
|
||||||
assert_equal('object<Unknown>', typename(F()))
|
assert_equal('object<any>', typename(F()))
|
||||||
|
|
||||||
var o0 = F()
|
var o0 = F()
|
||||||
assert_true(o0 == null_object)
|
assert_true(o0 == null_object)
|
||||||
@ -12486,37 +12485,325 @@ def Test_method_call_from_list_of_objects()
|
|||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
|
|
||||||
class C
|
class A
|
||||||
|
var n: list<number> = [100, 101]
|
||||||
def F(): string
|
def F(): string
|
||||||
return 'C.F'
|
return 'A.F'
|
||||||
enddef
|
enddef
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
class D
|
class B
|
||||||
var x: string
|
var name: string
|
||||||
def new(this.x)
|
var n: list<number> = [200, 201]
|
||||||
|
def new(this.name)
|
||||||
|
enddef
|
||||||
|
def F(): string
|
||||||
|
return 'B.F'
|
||||||
|
enddef
|
||||||
|
endclass
|
||||||
|
|
||||||
|
var obj1 = A.new()
|
||||||
|
var obj2 = B.new('b1')
|
||||||
|
|
||||||
|
def CheckObjectList()
|
||||||
|
var objlist = [obj1, obj2]
|
||||||
|
assert_equal('list<object<any>>', typename(objlist))
|
||||||
|
|
||||||
|
# Use a member function
|
||||||
|
assert_equal('A.F', objlist[0].F())
|
||||||
|
assert_equal('B.F', objlist[1].F())
|
||||||
|
|
||||||
|
# Use a member variable on the RHS
|
||||||
|
assert_equal([100, 101], objlist[0].n)
|
||||||
|
assert_equal([200, 201], objlist[1].n)
|
||||||
|
|
||||||
|
# Use a member variable on the LHS
|
||||||
|
objlist[0].n[1] = 110
|
||||||
|
objlist[1].n[1] = 210
|
||||||
|
assert_equal([100, 110], objlist[0].n)
|
||||||
|
assert_equal([200, 210], objlist[1].n)
|
||||||
|
|
||||||
|
# Iterate using a for loop
|
||||||
|
var s1 = []
|
||||||
|
for o in objlist
|
||||||
|
add(s1, o.F())
|
||||||
|
endfor
|
||||||
|
assert_equal(['A.F', 'B.F'], s1)
|
||||||
|
|
||||||
|
# Iterate using foreach()
|
||||||
|
var s2 = []
|
||||||
|
foreach(objlist, (k, v) => add(s2, v.F()))
|
||||||
|
assert_equal(['A.F', 'B.F'], s2)
|
||||||
|
|
||||||
|
# Add a new list item
|
||||||
|
objlist->add(B.new('b2'))
|
||||||
|
assert_equal('b2', objlist[2].name)
|
||||||
enddef
|
enddef
|
||||||
def F(): string
|
|
||||||
return 'D.F'
|
CheckObjectList()
|
||||||
|
|
||||||
|
var objlist = [A.new(), B.new('b2')]
|
||||||
|
assert_equal('list<object<any>>', typename(objlist))
|
||||||
|
|
||||||
|
# Use a member function
|
||||||
|
assert_equal('A.F', objlist[0].F())
|
||||||
|
assert_equal('B.F', objlist[1].F())
|
||||||
|
|
||||||
|
# Use a member variable on the RHS
|
||||||
|
assert_equal([100, 101], objlist[0].n)
|
||||||
|
assert_equal([200, 201], objlist[1].n)
|
||||||
|
|
||||||
|
# Use a member variable on the LHS
|
||||||
|
objlist[0].n[1] = 110
|
||||||
|
objlist[1].n[1] = 210
|
||||||
|
assert_equal([100, 110], objlist[0].n)
|
||||||
|
assert_equal([200, 210], objlist[1].n)
|
||||||
|
|
||||||
|
# Iterate using a for loop
|
||||||
|
var s1 = []
|
||||||
|
for o in objlist
|
||||||
|
add(s1, o.F())
|
||||||
|
endfor
|
||||||
|
assert_equal(['A.F', 'B.F'], s1)
|
||||||
|
|
||||||
|
# Iterate using foreach()
|
||||||
|
var s2 = []
|
||||||
|
foreach(objlist, (k, v) => add(s2, v.F()))
|
||||||
|
assert_equal(['A.F', 'B.F'], s2)
|
||||||
|
|
||||||
|
# Add a new list item
|
||||||
|
objlist->add(B.new('b2'))
|
||||||
|
assert_equal('b2', objlist[2].name)
|
||||||
|
END
|
||||||
|
v9.CheckSourceSuccess(lines)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class B
|
||||||
|
endclass
|
||||||
|
|
||||||
|
var objlist = [A.new(), B.new()]
|
||||||
|
def Fn()
|
||||||
|
objlist->add(10)
|
||||||
enddef
|
enddef
|
||||||
endclass
|
|
||||||
|
|
||||||
var obj1 = C.new()
|
try
|
||||||
var obj2 = D.new('a')
|
Fn()
|
||||||
|
catch
|
||||||
|
assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
|
||||||
|
endtry
|
||||||
|
|
||||||
def CheckObjectList()
|
try
|
||||||
var items = [obj1, obj2]
|
objlist->add(10)
|
||||||
assert_equal('list<any>', typename(items))
|
catch
|
||||||
assert_equal('C.F', items[0].F())
|
assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
|
||||||
assert_equal('D.F', items[1].F())
|
endtry
|
||||||
enddef
|
END
|
||||||
|
v9.CheckSourceSuccess(lines)
|
||||||
|
|
||||||
CheckObjectList()
|
# Adding an enum to a List of objects should fail
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
class B
|
||||||
|
endclass
|
||||||
|
enum C
|
||||||
|
Red,
|
||||||
|
Green,
|
||||||
|
endenum
|
||||||
|
var items = [A.new(), B.new()]
|
||||||
|
def Fn()
|
||||||
|
items->add(C.Red)
|
||||||
|
enddef
|
||||||
|
|
||||||
var items2 = [obj1, obj2]
|
try
|
||||||
assert_equal('list<any>', typename(items2))
|
Fn()
|
||||||
assert_equal('C.F', items2[0].F())
|
catch
|
||||||
assert_equal('D.F', items2[1].F())
|
assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got enum<C>')
|
||||||
|
endtry
|
||||||
|
|
||||||
|
try
|
||||||
|
items->add(C.Green)
|
||||||
|
catch
|
||||||
|
assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got enum<C>')
|
||||||
|
endtry
|
||||||
|
|
||||||
|
var items2 = [C.Red, C.Green]
|
||||||
|
def Fn2()
|
||||||
|
items2->add(A.new())
|
||||||
|
enddef
|
||||||
|
try
|
||||||
|
Fn2()
|
||||||
|
catch
|
||||||
|
assert_exception('Vim(eval):E1012: Type mismatch; expected enum<C> but got object<A>')
|
||||||
|
endtry
|
||||||
|
|
||||||
|
try
|
||||||
|
items2->add(B.new())
|
||||||
|
catch
|
||||||
|
assert_exception('Vim(eval):E1012: Type mismatch; expected enum<C> but got object<B>')
|
||||||
|
endtry
|
||||||
|
END
|
||||||
|
v9.CheckSourceSuccess(lines)
|
||||||
|
enddef
|
||||||
|
|
||||||
|
" Test for using a dict of objects
|
||||||
|
def Test_dict_of_objects()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
class A
|
||||||
|
var n: list<number> = [100, 101]
|
||||||
|
def F(): string
|
||||||
|
return 'A.F'
|
||||||
|
enddef
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class B
|
||||||
|
var name: string
|
||||||
|
var n: list<number> = [200, 201]
|
||||||
|
def new(this.name)
|
||||||
|
enddef
|
||||||
|
def F(): string
|
||||||
|
return 'B.F'
|
||||||
|
enddef
|
||||||
|
endclass
|
||||||
|
|
||||||
|
var obj1 = A.new()
|
||||||
|
var obj2 = B.new('b1')
|
||||||
|
|
||||||
|
def CheckObjectDict()
|
||||||
|
var objdict = {o_a: obj1, o_b: obj2}
|
||||||
|
assert_equal('dict<object<any>>', typename(objdict))
|
||||||
|
|
||||||
|
# Use a member function
|
||||||
|
assert_equal('A.F', objdict.o_a.F())
|
||||||
|
assert_equal('B.F', objdict.o_b.F())
|
||||||
|
|
||||||
|
# Use a member variable on the RHS
|
||||||
|
assert_equal([100, 101], objdict.o_a.n)
|
||||||
|
assert_equal([200, 201], objdict.o_b.n)
|
||||||
|
|
||||||
|
# Use a member variable on the LHS
|
||||||
|
objdict.o_a.n[1] = 110
|
||||||
|
objdict.o_b.n[1] = 210
|
||||||
|
assert_equal([100, 110], objdict.o_a.n)
|
||||||
|
assert_equal([200, 210], objdict.o_b.n)
|
||||||
|
|
||||||
|
# Iterate using a for loop
|
||||||
|
var l = []
|
||||||
|
for v in values(objdict)
|
||||||
|
add(l, v.F())
|
||||||
|
endfor
|
||||||
|
assert_equal(['A.F', 'B.F'], l)
|
||||||
|
|
||||||
|
# Iterate using foreach()
|
||||||
|
l = []
|
||||||
|
foreach(objdict, (k, v) => add(l, v.F()))
|
||||||
|
assert_equal(['A.F', 'B.F'], l)
|
||||||
|
|
||||||
|
# Add a new dict item
|
||||||
|
objdict['o_b2'] = B.new('b2')
|
||||||
|
assert_equal('b2', objdict.o_b2.name)
|
||||||
|
enddef
|
||||||
|
|
||||||
|
CheckObjectDict()
|
||||||
|
|
||||||
|
var objdict = {o_a: A.new(), o_b: B.new('b2')}
|
||||||
|
assert_equal('dict<object<any>>', typename(objdict))
|
||||||
|
assert_equal('A.F', objdict.o_a.F())
|
||||||
|
assert_equal('B.F', objdict.o_b.F())
|
||||||
|
assert_equal([100, 101], objdict.o_a.n)
|
||||||
|
assert_equal([200, 201], objdict.o_b.n)
|
||||||
|
|
||||||
|
var l = []
|
||||||
|
for v in values(objdict)
|
||||||
|
add(l, v.F())
|
||||||
|
endfor
|
||||||
|
assert_equal(['A.F', 'B.F'], l)
|
||||||
|
|
||||||
|
# Add a new dict item
|
||||||
|
objdict['o_b2'] = B.new('b2')
|
||||||
|
assert_equal('b2', objdict.o_b2.name)
|
||||||
|
END
|
||||||
|
v9.CheckSourceSuccess(lines)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
class B
|
||||||
|
endclass
|
||||||
|
class C
|
||||||
|
endclass
|
||||||
|
var objdict = {a: A.new(), b: B.new()}
|
||||||
|
def Fn()
|
||||||
|
objdict['c'] = C.new()
|
||||||
|
enddef
|
||||||
|
|
||||||
|
try
|
||||||
|
Fn()
|
||||||
|
catch
|
||||||
|
assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
|
||||||
|
endtry
|
||||||
|
|
||||||
|
try
|
||||||
|
objdict['c'] = C.new()
|
||||||
|
catch
|
||||||
|
assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
|
||||||
|
endtry
|
||||||
|
END
|
||||||
|
v9.CheckSourceSuccess(lines)
|
||||||
|
|
||||||
|
# Adding an enum to a Dict of objects should fail
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
class B
|
||||||
|
endclass
|
||||||
|
enum C
|
||||||
|
Red,
|
||||||
|
Green,
|
||||||
|
endenum
|
||||||
|
var items = {o_a: A.new(), o_b: B.new()}
|
||||||
|
def Fn()
|
||||||
|
items['o_c'] = C.Red
|
||||||
|
enddef
|
||||||
|
|
||||||
|
try
|
||||||
|
Fn()
|
||||||
|
catch
|
||||||
|
assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got enum<C>')
|
||||||
|
endtry
|
||||||
|
|
||||||
|
try
|
||||||
|
items['o_c'] = C.Green
|
||||||
|
catch
|
||||||
|
assert_exception('Vim(var):E1012: Type mismatch; expected object<any> but got enum<C>')
|
||||||
|
endtry
|
||||||
|
|
||||||
|
var items2 = {red: C.Red, green: C.Green}
|
||||||
|
def Fn2()
|
||||||
|
items2['o_a'] = A.new()
|
||||||
|
enddef
|
||||||
|
try
|
||||||
|
Fn2()
|
||||||
|
catch
|
||||||
|
assert_exception('Vim(eval):E1012: Type mismatch; expected enum<C> but got object<A>')
|
||||||
|
endtry
|
||||||
|
|
||||||
|
try
|
||||||
|
items2['o_a'] = B.new()
|
||||||
|
catch
|
||||||
|
assert_exception('Vim(var):E1012: Type mismatch; expected enum<C> but got object<B>')
|
||||||
|
endtry
|
||||||
END
|
END
|
||||||
v9.CheckSourceSuccess(lines)
|
v9.CheckSourceSuccess(lines)
|
||||||
enddef
|
enddef
|
||||||
|
@ -5180,7 +5180,7 @@ def Test_null_values()
|
|||||||
[null_dict, 1, '{}', 4, 'dict<any>'],
|
[null_dict, 1, '{}', 4, 'dict<any>'],
|
||||||
[null_function, 1, "function('')", 2, 'func(...): unknown'],
|
[null_function, 1, "function('')", 2, 'func(...): unknown'],
|
||||||
[null_list, 1, '[]', 3, 'list<any>'],
|
[null_list, 1, '[]', 3, 'list<any>'],
|
||||||
[null_object, 1, 'object of [unknown]', 13, 'object<Unknown>'],
|
[null_object, 1, 'object of [unknown]', 13, 'object<any>'],
|
||||||
[null_partial, 1, "function('')", 2, 'func(...): unknown'],
|
[null_partial, 1, "function('')", 2, 'func(...): unknown'],
|
||||||
[null_string, 1, "''", 1, 'string']
|
[null_string, 1, "''", 1, 'string']
|
||||||
]
|
]
|
||||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1267,
|
||||||
/**/
|
/**/
|
||||||
1266,
|
1266,
|
||||||
/**/
|
/**/
|
||||||
|
@ -2498,7 +2498,8 @@ compile_load_lhs(
|
|||||||
: get_type_on_stack(cctx, 0);
|
: get_type_on_stack(cctx, 0);
|
||||||
|
|
||||||
if (lhs->lhs_type->tt_type == VAR_CLASS
|
if (lhs->lhs_type->tt_type == VAR_CLASS
|
||||||
|| lhs->lhs_type->tt_type == VAR_OBJECT)
|
|| (lhs->lhs_type->tt_type == VAR_OBJECT
|
||||||
|
&& lhs->lhs_type != &t_object_any))
|
||||||
{
|
{
|
||||||
// Check whether the class or object variable is modifiable
|
// Check whether the class or object variable is modifiable
|
||||||
if (!lhs_class_member_modifiable(lhs, var_start, cctx))
|
if (!lhs_class_member_modifiable(lhs, var_start, cctx))
|
||||||
@ -2522,7 +2523,7 @@ compile_load_lhs(
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return generate_loadvar(cctx, lhs);
|
return generate_loadvar(cctx, lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2684,7 +2684,8 @@ compile_subscript(
|
|||||||
type = get_type_on_stack(cctx, 0);
|
type = get_type_on_stack(cctx, 0);
|
||||||
if (type != &t_unknown
|
if (type != &t_unknown
|
||||||
&& (type->tt_type == VAR_CLASS
|
&& (type->tt_type == VAR_CLASS
|
||||||
|| type->tt_type == VAR_OBJECT))
|
|| (type->tt_type == VAR_OBJECT
|
||||||
|
&& type != &t_object_any)))
|
||||||
{
|
{
|
||||||
// class member: SomeClass.varname
|
// class member: SomeClass.varname
|
||||||
// class method: SomeClass.SomeMethod()
|
// class method: SomeClass.SomeMethod()
|
||||||
|
@ -756,7 +756,7 @@ generate_SETTYPE(
|
|||||||
generate_PUSHOBJ(cctx_T *cctx)
|
generate_PUSHOBJ(cctx_T *cctx)
|
||||||
{
|
{
|
||||||
RETURN_OK_IF_SKIP(cctx);
|
RETURN_OK_IF_SKIP(cctx);
|
||||||
if (generate_instr_type(cctx, ISN_PUSHOBJ, &t_object) == NULL)
|
if (generate_instr_type(cctx, ISN_PUSHOBJ, &t_object_any) == NULL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -2142,7 +2142,8 @@ generate_PCALL(
|
|||||||
|
|
||||||
RETURN_OK_IF_SKIP(cctx);
|
RETURN_OK_IF_SKIP(cctx);
|
||||||
|
|
||||||
if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN)
|
if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN
|
||||||
|
|| type == &t_object_any)
|
||||||
ret_type = &t_any;
|
ret_type = &t_any;
|
||||||
else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
|
else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
|
||||||
{
|
{
|
||||||
@ -2213,7 +2214,9 @@ generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len)
|
|||||||
// check for dict type
|
// check for dict type
|
||||||
type = get_type_on_stack(cctx, 0);
|
type = get_type_on_stack(cctx, 0);
|
||||||
if (type->tt_type != VAR_DICT
|
if (type->tt_type != VAR_DICT
|
||||||
&& type->tt_type != VAR_ANY && type->tt_type != VAR_UNKNOWN)
|
&& type->tt_type != VAR_OBJECT
|
||||||
|
&& type->tt_type != VAR_ANY
|
||||||
|
&& type->tt_type != VAR_UNKNOWN)
|
||||||
{
|
{
|
||||||
char *tofree;
|
char *tofree;
|
||||||
|
|
||||||
|
@ -764,7 +764,7 @@ oc_typval2type(typval_T *tv)
|
|||||||
if (tv->vval.v_object != NULL)
|
if (tv->vval.v_object != NULL)
|
||||||
return &tv->vval.v_object->obj_class->class_object_type;
|
return &tv->vval.v_object->obj_class->class_object_type;
|
||||||
|
|
||||||
return &t_object;
|
return &t_object_any;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1307,8 +1307,11 @@ check_type_maybe(
|
|||||||
return MAYBE; // use runtime type check
|
return MAYBE; // use runtime type check
|
||||||
if (actual->tt_type != VAR_OBJECT)
|
if (actual->tt_type != VAR_OBJECT)
|
||||||
return FAIL; // don't use tt_class
|
return FAIL; // don't use tt_class
|
||||||
if (actual->tt_class == NULL)
|
if (actual->tt_class == NULL) // null object
|
||||||
return OK; // A null object matches
|
return OK;
|
||||||
|
// t_object_any matches any object except for an enum item
|
||||||
|
if (expected == &t_object_any && !IS_ENUM(actual->tt_class))
|
||||||
|
return OK;
|
||||||
|
|
||||||
// For object method arguments, do a invariant type check in
|
// For object method arguments, do a invariant type check in
|
||||||
// an extended class. For all others, do a covariance type check.
|
// an extended class. For all others, do a covariance type check.
|
||||||
@ -2122,6 +2125,11 @@ common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
|
|||||||
common_type_var_func(type1, type2, dest, type_gap);
|
common_type_var_func(type1, type2, dest, type_gap);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (type1->tt_type == VAR_OBJECT)
|
||||||
|
{
|
||||||
|
*dest = &t_object_any;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*dest = &t_any;
|
*dest = &t_any;
|
||||||
@ -2428,7 +2436,7 @@ type_name_class_or_obj(char *name, type_T *type, char **tofree)
|
|||||||
name = "enum";
|
name = "enum";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
class_name = (char_u *)"Unknown";
|
class_name = (char_u *)"any";
|
||||||
|
|
||||||
size_t len = STRLEN(name) + STRLEN(class_name) + 3;
|
size_t len = STRLEN(name) + STRLEN(class_name) + 3;
|
||||||
*tofree = alloc(len);
|
*tofree = alloc(len);
|
||||||
|
Reference in New Issue
Block a user