summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-03-08 19:43:55 +0000
committerBram Moolenaar <Bram@vim.org>2022-03-08 19:43:55 +0000
commited0c62e7b16b62655824df28cdd6bd75aadbb8fc (patch)
tree2d912c33146a6ddd65d7877ac8cc9339c9fb953f /src
parent673bcb10ebe87ccf6954dd342d0143eb88cdfbcb (diff)
patch 8.2.4529: Vim9: comparing partial with function failsv8.2.4529
Problem: Vim9: comparing partial with function fails. Solution: Support this comparison. Avoid a crash. (closes #9909) Add more test cases.
Diffstat (limited to 'src')
-rw-r--r--src/testdir/test_vim9_builtin.vim3
-rw-r--r--src/testdir/test_vim9_expr.vim38
-rw-r--r--src/testdir/test_vim9_func.vim2
-rw-r--r--src/testdir/test_vimscript.vim3
-rw-r--r--src/userfunc.c18
-rw-r--r--src/version.c2
-rw-r--r--src/vim9instr.c4
-rw-r--r--src/vim9type.c2
8 files changed, 64 insertions, 8 deletions
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index 7577aecd2a..8b9dbd6051 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -1687,6 +1687,7 @@ def Test_getenv()
endif
$SOMEENVVAR = 'some'
assert_equal('some', getenv('SOMEENVVAR'))
+ assert_notequal(null, getenv('SOMEENVVAR'))
unlet $SOMEENVVAR
getenv('')->assert_equal(v:null)
enddef
@@ -4398,7 +4399,7 @@ def Test_typename()
if has('float')
assert_equal('func([unknown], [unknown]): float', typename(function('pow')))
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('dict<unknown>', test_null_dict()->typename())
if has('job')
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index a38254f7dc..4a3803a8f1 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -717,21 +717,33 @@ def Test_expr4_compare_null()
g:not_null_list = []
var lines =<< trim END
assert_true(test_null_blob() == v:null)
+ assert_true(null_blob == null)
assert_true(v:null == test_null_blob())
+ assert_true(null == null_blob)
assert_false(test_null_blob() != v:null)
+ assert_false(null_blob != null)
assert_false(v:null != test_null_blob())
+ assert_false(null != null_blob)
if has('channel')
assert_true(test_null_channel() == v:null)
+ assert_true(null_channel == null)
assert_true(v:null == test_null_channel())
+ assert_true(null == null_channel)
assert_false(test_null_channel() != v:null)
+ assert_false(null_channel != null)
assert_false(v:null != test_null_channel())
+ assert_false(null != null_channel)
endif
assert_true(test_null_dict() == v:null)
+ assert_true(null_dict == null)
assert_true(v:null == test_null_dict())
+ assert_true(null == null_dict)
assert_false(test_null_dict() != v:null)
+ assert_false(null_dict != null)
assert_false(v:null != test_null_dict())
+ assert_false(null != null_dict)
assert_true(g:null_dict == v:null)
assert_true(v:null == g:null_dict)
@@ -739,21 +751,33 @@ def Test_expr4_compare_null()
assert_false(v:null != g:null_dict)
assert_true(test_null_function() == v:null)
+ assert_true(null_function == null)
assert_true(v:null == test_null_function())
+ assert_true(null == null_function)
assert_false(test_null_function() != v:null)
+ assert_false(null_function != null)
assert_false(v:null != test_null_function())
+ assert_false(null != null_function)
if has('job')
assert_true(test_null_job() == v:null)
+ assert_true(null_job == null)
assert_true(v:null == test_null_job())
+ assert_true(null == null_job)
assert_false(test_null_job() != v:null)
+ assert_false(null_job != null)
assert_false(v:null != test_null_job())
+ assert_false(null != null_job)
endif
assert_true(test_null_list() == v:null)
+ assert_true(null_list == null)
assert_true(v:null == test_null_list())
+ assert_true(null == null_list)
assert_false(test_null_list() != v:null)
+ assert_false(null_list != null)
assert_false(v:null != test_null_list())
+ assert_false(null != null_list)
assert_false(g:not_null_list == v:null)
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(test_null_partial() == v:null)
+ assert_true(null_partial == null)
assert_true(v:null == test_null_partial())
+ assert_true(null == null_partial)
assert_false(test_null_partial() != v:null)
+ assert_false(null_partial != null)
assert_false(v:null != test_null_partial())
+ assert_false(null != null_partial)
assert_true(test_null_string() == v:null)
+ assert_true(null_string == null)
assert_true(v:null == test_null_string())
+ assert_true(null == null_string)
assert_false(test_null_string() != v:null)
+ assert_false(null_string != null)
assert_false(v:null != test_null_string())
+ assert_false(null != null_string)
END
v9.CheckDefAndScriptSuccess(lines)
unlet g:null_dict
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 v:null == 123'], 'E1072: Cannot compare special with number')
v9.CheckDefAndScriptFailure(['echo 123 != v:null'], 'E1072: Cannot compare number with special')
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index 131413b160..85e8e9d3dd 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -3341,7 +3341,7 @@ def Test_partial_null_function()
var lines =<< trim END
var d: dict<func> = {f: null_function}
var Ref = d.f
- assert_equal('func', typename(Ref))
+ assert_equal('func(...): unknown', typename(Ref))
END
v9.CheckDefAndScriptSuccess(lines)
enddef
diff --git a/src/testdir/test_vimscript.vim b/src/testdir/test_vimscript.vim
index 24dfd1b23f..ce3dbca681 100644
--- a/src/testdir/test_vimscript.vim
+++ b/src/testdir/test_vimscript.vim
@@ -6571,6 +6571,9 @@ func Test_type()
call assert_false(v:true is 1)
call assert_false(v:true is v:false)
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 v:none)
diff --git a/src/userfunc.c b/src/userfunc.c
index f0abaee5f0..42e1e89bc3 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -5730,18 +5730,27 @@ func_has_abort(
make_partial(dict_T *selfdict_in, typval_T *rettv)
{
char_u *fname;
- ufunc_T *fp;
+ ufunc_T *fp = NULL;
char_u fname_buf[FLEN_FIXED + 1];
int error;
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;
else
{
fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string
+ : rettv->vval.v_partial == NULL ? NULL
: 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;
@@ -5752,8 +5761,7 @@ make_partial(dict_T *selfdict_in, typval_T *rettv)
}
}
- if ((fp != NULL && (fp->uf_flags & FC_DICT))
- || (rettv->v_type == VAR_FUNC && rettv->vval.v_string == NULL))
+ if (fp != NULL && (fp->uf_flags & FC_DICT))
{
partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
diff --git a/src/version.c b/src/version.c
index f6aaa79554..3e212db88b 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4529,
+/**/
4528,
/**/
4527,
diff --git a/src/vim9instr.c b/src/vim9instr.c
index 7fbf529a64..e36ea16e2e 100644
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -370,7 +370,9 @@ get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
}
else if (type1 == VAR_ANY || type2 == VAR_ANY
|| ((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;
else if (type1 == VAR_SPECIAL || type2 == VAR_SPECIAL)
{
diff --git a/src/vim9type.c b/src/vim9type.c
index fe4dec59f0..6a44c7b7c8 100644
--- a/src/vim9type.c
+++ b/src/vim9type.c
@@ -420,6 +420,8 @@ typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int flags)
}
else
name = tv->vval.v_string;
+ if (name == NULL && ufunc == NULL)
+ return &t_func_unknown;
if (name != NULL)
{
int idx = find_internal_func(name);