To: vim_dev@googlegroups.com Subject: Patch 8.2.4529 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.4529 Problem: Vim9: comparing partial with function fails. Solution: Support this comparison. Avoid a crash. (closes #9909) Add more test cases. Files: src/vim9instr.c, src/userfunc.c, src/vim9type.c, src/testdir/test_vim9_builtin.vim, src/testdir/test_vim9_expr.vim, src/testdir/test_vim9_func.vim, src/testdir/test_vimscript.vim *** ../vim-8.2.4528/src/vim9instr.c 2022-03-08 13:18:10.809020782 +0000 --- src/vim9instr.c 2022-03-08 18:58:21.949496564 +0000 *************** *** 370,376 **** } else if (type1 == VAR_ANY || type2 == VAR_ANY || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT) ! && (type2 == VAR_NUMBER || type2 == VAR_FLOAT))) isntype = ISN_COMPAREANY; else if (type1 == VAR_SPECIAL || type2 == VAR_SPECIAL) { --- 370,378 ---- } else if (type1 == VAR_ANY || type2 == VAR_ANY || ((type1 == VAR_NUMBER || type1 == 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) { *** ../vim-8.2.4528/src/userfunc.c 2022-03-08 16:52:18.807756958 +0000 --- src/userfunc.c 2022-03-08 19:16:32.579191126 +0000 *************** *** 5730,5747 **** make_partial(dict_T *selfdict_in, typval_T *rettv) { char_u *fname; ! ufunc_T *fp; 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) fp = rettv->vval.v_partial->pt_func; else { fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string : rettv->vval.v_partial->pt_name; ! if (fname != NULL) { char_u *tofree = NULL; --- 5730,5756 ---- make_partial(dict_T *selfdict_in, typval_T *rettv) { char_u *fname; ! 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 != 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) ! { ! // 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,5759 **** } } ! 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); --- 5761,5767 ---- } } ! if (fp != NULL && (fp->uf_flags & FC_DICT)) { partial_T *pt = ALLOC_CLEAR_ONE(partial_T); *** ../vim-8.2.4528/src/vim9type.c 2022-03-08 13:18:10.809020782 +0000 --- src/vim9type.c 2022-03-08 19:38:42.740545016 +0000 *************** *** 420,425 **** --- 420,427 ---- } else name = tv->vval.v_string; + if (name == NULL && ufunc == NULL) + return &t_func_unknown; if (name != NULL) { int idx = find_internal_func(name); *** ../vim-8.2.4528/src/testdir/test_vim9_builtin.vim 2022-02-23 21:03:28.913442583 +0000 --- src/testdir/test_vim9_builtin.vim 2022-03-08 19:40:04.756387254 +0000 *************** *** 1687,1692 **** --- 1687,1693 ---- endif $SOMEENVVAR = 'some' assert_equal('some', getenv('SOMEENVVAR')) + assert_notequal(null, getenv('SOMEENVVAR')) unlet $SOMEENVVAR getenv('')->assert_equal(v:null) enddef *************** *** 4398,4404 **** if has('float') assert_equal('func([unknown], [unknown]): float', typename(function('pow'))) endif ! assert_equal('func', test_null_partial()->typename()) assert_equal('list', test_null_list()->typename()) assert_equal('dict', test_null_dict()->typename()) if has('job') --- 4399,4405 ---- if has('float') assert_equal('func([unknown], [unknown]): float', typename(function('pow'))) endif ! assert_equal('func(...): unknown', test_null_partial()->typename()) assert_equal('list', test_null_list()->typename()) assert_equal('dict', test_null_dict()->typename()) if has('job') *** ../vim-8.2.4528/src/testdir/test_vim9_expr.vim 2022-03-01 19:23:20.544357315 +0000 --- src/testdir/test_vim9_expr.vim 2022-03-08 19:19:38.126801608 +0000 *************** *** 717,737 **** --- 717,749 ---- 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,759 **** --- 751,783 ---- 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,779 **** --- 785,817 ---- 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 = {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') *** ../vim-8.2.4528/src/testdir/test_vim9_func.vim 2022-03-08 16:52:18.807756958 +0000 --- src/testdir/test_vim9_func.vim 2022-03-08 19:27:47.821817178 +0000 *************** *** 3341,3347 **** var lines =<< trim END var d: dict = {f: null_function} var Ref = d.f ! assert_equal('func', typename(Ref)) END v9.CheckDefAndScriptSuccess(lines) enddef --- 3341,3347 ---- var lines =<< trim END var d: dict = {f: null_function} var Ref = d.f ! assert_equal('func(...): unknown', typename(Ref)) END v9.CheckDefAndScriptSuccess(lines) enddef *** ../vim-8.2.4528/src/testdir/test_vimscript.vim 2022-03-02 13:13:26.475857972 +0000 --- src/testdir/test_vimscript.vim 2022-03-02 14:46:33.321695479 +0000 *************** *** 6571,6576 **** --- 6571,6579 ---- 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) *** ../vim-8.2.4528/src/version.c 2022-03-08 16:52:18.807756958 +0000 --- src/version.c 2022-03-08 19:00:28.957245068 +0000 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 4529, /**/ -- hundred-and-one symptoms of being an internet addict: 207. You're given one phone call in prison and you ask them for a laptop. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///