forked from aniani/vim
patch 8.2.4529: Vim9: comparing partial with function fails
Problem: Vim9: comparing partial with function fails. Solution: Support this comparison. Avoid a crash. (closes #9909) Add more test cases.
This commit is contained in:
parent
673bcb10eb
commit
ed0c62e7b1
@ -1687,6 +1687,7 @@ def Test_getenv()
|
|||||||
endif
|
endif
|
||||||
$SOMEENVVAR = 'some'
|
$SOMEENVVAR = 'some'
|
||||||
assert_equal('some', getenv('SOMEENVVAR'))
|
assert_equal('some', getenv('SOMEENVVAR'))
|
||||||
|
assert_notequal(null, getenv('SOMEENVVAR'))
|
||||||
unlet $SOMEENVVAR
|
unlet $SOMEENVVAR
|
||||||
getenv('')->assert_equal(v:null)
|
getenv('')->assert_equal(v:null)
|
||||||
enddef
|
enddef
|
||||||
@ -4398,7 +4399,7 @@ def Test_typename()
|
|||||||
if has('float')
|
if has('float')
|
||||||
assert_equal('func([unknown], [unknown]): float', typename(function('pow')))
|
assert_equal('func([unknown], [unknown]): float', typename(function('pow')))
|
||||||
endif
|
endif
|
||||||
assert_equal('func', test_null_partial()->typename())
|
assert_equal('func(...): unknown', test_null_partial()->typename())
|
||||||
assert_equal('list<unknown>', test_null_list()->typename())
|
assert_equal('list<unknown>', test_null_list()->typename())
|
||||||
assert_equal('dict<unknown>', test_null_dict()->typename())
|
assert_equal('dict<unknown>', test_null_dict()->typename())
|
||||||
if has('job')
|
if has('job')
|
||||||
|
@ -717,21 +717,33 @@ def Test_expr4_compare_null()
|
|||||||
g:not_null_list = []
|
g:not_null_list = []
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
assert_true(test_null_blob() == v:null)
|
assert_true(test_null_blob() == v:null)
|
||||||
|
assert_true(null_blob == null)
|
||||||
assert_true(v:null == test_null_blob())
|
assert_true(v:null == test_null_blob())
|
||||||
|
assert_true(null == null_blob)
|
||||||
assert_false(test_null_blob() != v:null)
|
assert_false(test_null_blob() != v:null)
|
||||||
|
assert_false(null_blob != null)
|
||||||
assert_false(v:null != test_null_blob())
|
assert_false(v:null != test_null_blob())
|
||||||
|
assert_false(null != null_blob)
|
||||||
|
|
||||||
if has('channel')
|
if has('channel')
|
||||||
assert_true(test_null_channel() == v:null)
|
assert_true(test_null_channel() == v:null)
|
||||||
|
assert_true(null_channel == null)
|
||||||
assert_true(v:null == test_null_channel())
|
assert_true(v:null == test_null_channel())
|
||||||
|
assert_true(null == null_channel)
|
||||||
assert_false(test_null_channel() != v:null)
|
assert_false(test_null_channel() != v:null)
|
||||||
|
assert_false(null_channel != null)
|
||||||
assert_false(v:null != test_null_channel())
|
assert_false(v:null != test_null_channel())
|
||||||
|
assert_false(null != null_channel)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
assert_true(test_null_dict() == v:null)
|
assert_true(test_null_dict() == v:null)
|
||||||
|
assert_true(null_dict == null)
|
||||||
assert_true(v:null == test_null_dict())
|
assert_true(v:null == test_null_dict())
|
||||||
|
assert_true(null == null_dict)
|
||||||
assert_false(test_null_dict() != v:null)
|
assert_false(test_null_dict() != v:null)
|
||||||
|
assert_false(null_dict != null)
|
||||||
assert_false(v:null != test_null_dict())
|
assert_false(v:null != test_null_dict())
|
||||||
|
assert_false(null != null_dict)
|
||||||
|
|
||||||
assert_true(g:null_dict == v:null)
|
assert_true(g:null_dict == v:null)
|
||||||
assert_true(v:null == g:null_dict)
|
assert_true(v:null == g:null_dict)
|
||||||
@ -739,21 +751,33 @@ def Test_expr4_compare_null()
|
|||||||
assert_false(v:null != g:null_dict)
|
assert_false(v:null != g:null_dict)
|
||||||
|
|
||||||
assert_true(test_null_function() == v:null)
|
assert_true(test_null_function() == v:null)
|
||||||
|
assert_true(null_function == null)
|
||||||
assert_true(v:null == test_null_function())
|
assert_true(v:null == test_null_function())
|
||||||
|
assert_true(null == null_function)
|
||||||
assert_false(test_null_function() != v:null)
|
assert_false(test_null_function() != v:null)
|
||||||
|
assert_false(null_function != null)
|
||||||
assert_false(v:null != test_null_function())
|
assert_false(v:null != test_null_function())
|
||||||
|
assert_false(null != null_function)
|
||||||
|
|
||||||
if has('job')
|
if has('job')
|
||||||
assert_true(test_null_job() == v:null)
|
assert_true(test_null_job() == v:null)
|
||||||
|
assert_true(null_job == null)
|
||||||
assert_true(v:null == test_null_job())
|
assert_true(v:null == test_null_job())
|
||||||
|
assert_true(null == null_job)
|
||||||
assert_false(test_null_job() != v:null)
|
assert_false(test_null_job() != v:null)
|
||||||
|
assert_false(null_job != null)
|
||||||
assert_false(v:null != test_null_job())
|
assert_false(v:null != test_null_job())
|
||||||
|
assert_false(null != null_job)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
assert_true(test_null_list() == v:null)
|
assert_true(test_null_list() == v:null)
|
||||||
|
assert_true(null_list == null)
|
||||||
assert_true(v:null == test_null_list())
|
assert_true(v:null == test_null_list())
|
||||||
|
assert_true(null == null_list)
|
||||||
assert_false(test_null_list() != v:null)
|
assert_false(test_null_list() != v:null)
|
||||||
|
assert_false(null_list != null)
|
||||||
assert_false(v:null != test_null_list())
|
assert_false(v:null != test_null_list())
|
||||||
|
assert_false(null != null_list)
|
||||||
|
|
||||||
assert_false(g:not_null_list == v:null)
|
assert_false(g:not_null_list == v:null)
|
||||||
assert_false(v:null == g:not_null_list)
|
assert_false(v:null == g:not_null_list)
|
||||||
@ -761,19 +785,33 @@ def Test_expr4_compare_null()
|
|||||||
assert_true(v:null != g:not_null_list)
|
assert_true(v:null != g:not_null_list)
|
||||||
|
|
||||||
assert_true(test_null_partial() == v:null)
|
assert_true(test_null_partial() == v:null)
|
||||||
|
assert_true(null_partial == null)
|
||||||
assert_true(v:null == test_null_partial())
|
assert_true(v:null == test_null_partial())
|
||||||
|
assert_true(null == null_partial)
|
||||||
assert_false(test_null_partial() != v:null)
|
assert_false(test_null_partial() != v:null)
|
||||||
|
assert_false(null_partial != null)
|
||||||
assert_false(v:null != test_null_partial())
|
assert_false(v:null != test_null_partial())
|
||||||
|
assert_false(null != null_partial)
|
||||||
|
|
||||||
assert_true(test_null_string() == v:null)
|
assert_true(test_null_string() == v:null)
|
||||||
|
assert_true(null_string == null)
|
||||||
assert_true(v:null == test_null_string())
|
assert_true(v:null == test_null_string())
|
||||||
|
assert_true(null == null_string)
|
||||||
assert_false(test_null_string() != v:null)
|
assert_false(test_null_string() != v:null)
|
||||||
|
assert_false(null_string != null)
|
||||||
assert_false(v:null != test_null_string())
|
assert_false(v:null != test_null_string())
|
||||||
|
assert_false(null != null_string)
|
||||||
END
|
END
|
||||||
v9.CheckDefAndScriptSuccess(lines)
|
v9.CheckDefAndScriptSuccess(lines)
|
||||||
unlet g:null_dict
|
unlet g:null_dict
|
||||||
unlet g:not_null_list
|
unlet g:not_null_list
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
var d: dict<func> = {f: null_function}
|
||||||
|
assert_equal(null_function, d.f)
|
||||||
|
END
|
||||||
|
v9.CheckDefAndScriptSuccess(lines)
|
||||||
|
|
||||||
v9.CheckDefAndScriptFailure(['echo 123 == v:null'], 'E1072: Cannot compare number with special')
|
v9.CheckDefAndScriptFailure(['echo 123 == v:null'], 'E1072: Cannot compare number with special')
|
||||||
v9.CheckDefAndScriptFailure(['echo v:null == 123'], 'E1072: Cannot compare special with number')
|
v9.CheckDefAndScriptFailure(['echo v:null == 123'], 'E1072: Cannot compare special with number')
|
||||||
v9.CheckDefAndScriptFailure(['echo 123 != v:null'], 'E1072: Cannot compare number with special')
|
v9.CheckDefAndScriptFailure(['echo 123 != v:null'], 'E1072: Cannot compare number with special')
|
||||||
|
@ -3341,7 +3341,7 @@ def Test_partial_null_function()
|
|||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
var d: dict<func> = {f: null_function}
|
var d: dict<func> = {f: null_function}
|
||||||
var Ref = d.f
|
var Ref = d.f
|
||||||
assert_equal('func', typename(Ref))
|
assert_equal('func(...): unknown', typename(Ref))
|
||||||
END
|
END
|
||||||
v9.CheckDefAndScriptSuccess(lines)
|
v9.CheckDefAndScriptSuccess(lines)
|
||||||
enddef
|
enddef
|
||||||
|
@ -6571,6 +6571,9 @@ func Test_type()
|
|||||||
call assert_false(v:true is 1)
|
call assert_false(v:true is 1)
|
||||||
call assert_false(v:true is v:false)
|
call assert_false(v:true is v:false)
|
||||||
call assert_false(v:none is 0)
|
call assert_false(v:none is 0)
|
||||||
|
call assert_false(v:none is [])
|
||||||
|
call assert_false(v:none is {})
|
||||||
|
call assert_false(v:none is 'text')
|
||||||
call assert_false(v:null is 0)
|
call assert_false(v:null is 0)
|
||||||
call assert_false(v:null is v:none)
|
call assert_false(v:null is v:none)
|
||||||
|
|
||||||
|
@ -5730,18 +5730,27 @@ func_has_abort(
|
|||||||
make_partial(dict_T *selfdict_in, typval_T *rettv)
|
make_partial(dict_T *selfdict_in, typval_T *rettv)
|
||||||
{
|
{
|
||||||
char_u *fname;
|
char_u *fname;
|
||||||
ufunc_T *fp;
|
ufunc_T *fp = NULL;
|
||||||
char_u fname_buf[FLEN_FIXED + 1];
|
char_u fname_buf[FLEN_FIXED + 1];
|
||||||
int error;
|
int error;
|
||||||
dict_T *selfdict = selfdict_in;
|
dict_T *selfdict = selfdict_in;
|
||||||
|
|
||||||
if (rettv->v_type == VAR_PARTIAL && rettv->vval.v_partial->pt_func != NULL)
|
if (rettv->v_type == VAR_PARTIAL && rettv->vval.v_partial != NULL
|
||||||
|
&& rettv->vval.v_partial->pt_func != NULL)
|
||||||
fp = rettv->vval.v_partial->pt_func;
|
fp = rettv->vval.v_partial->pt_func;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string
|
fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string
|
||||||
|
: rettv->vval.v_partial == NULL ? NULL
|
||||||
: rettv->vval.v_partial->pt_name;
|
: rettv->vval.v_partial->pt_name;
|
||||||
if (fname != NULL)
|
if (fname == NULL)
|
||||||
|
{
|
||||||
|
// There is no point binding a dict to a NULL function, just create
|
||||||
|
// a function reference.
|
||||||
|
rettv->v_type = VAR_FUNC;
|
||||||
|
rettv->vval.v_string = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
char_u *tofree = NULL;
|
char_u *tofree = NULL;
|
||||||
|
|
||||||
@ -5752,8 +5761,7 @@ make_partial(dict_T *selfdict_in, typval_T *rettv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fp != NULL && (fp->uf_flags & FC_DICT))
|
if (fp != NULL && (fp->uf_flags & FC_DICT))
|
||||||
|| (rettv->v_type == VAR_FUNC && rettv->vval.v_string == NULL))
|
|
||||||
{
|
{
|
||||||
partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
|
partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
|
||||||
|
|
||||||
|
@ -750,6 +750,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 */
|
||||||
|
/**/
|
||||||
|
4529,
|
||||||
/**/
|
/**/
|
||||||
4528,
|
4528,
|
||||||
/**/
|
/**/
|
||||||
|
@ -370,7 +370,9 @@ get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
|
|||||||
}
|
}
|
||||||
else if (type1 == VAR_ANY || type2 == VAR_ANY
|
else if (type1 == VAR_ANY || type2 == VAR_ANY
|
||||||
|| ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
|
|| ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
|
||||||
&& (type2 == VAR_NUMBER || type2 == VAR_FLOAT)))
|
&& (type2 == VAR_NUMBER || type2 == VAR_FLOAT))
|
||||||
|
|| (type1 == VAR_FUNC && type2 == VAR_PARTIAL)
|
||||||
|
|| (type1 == VAR_PARTIAL && type2 == VAR_FUNC))
|
||||||
isntype = ISN_COMPAREANY;
|
isntype = ISN_COMPAREANY;
|
||||||
else if (type1 == VAR_SPECIAL || type2 == VAR_SPECIAL)
|
else if (type1 == VAR_SPECIAL || type2 == VAR_SPECIAL)
|
||||||
{
|
{
|
||||||
|
@ -420,6 +420,8 @@ typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int flags)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
name = tv->vval.v_string;
|
name = tv->vval.v_string;
|
||||||
|
if (name == NULL && ufunc == NULL)
|
||||||
|
return &t_func_unknown;
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
{
|
{
|
||||||
int idx = find_internal_func(name);
|
int idx = find_internal_func(name);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user