To: vim_dev@googlegroups.com Subject: Patch 8.2.4642 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.4642 Problem: Vim9: in :def function script var cannot be null. Solution: Only initialize a script variable when not set to a null value. (closes #10034) Files: src/vim9execute.c, src/vim9type.c, src/globals.h, src/evalvars.c, src/vim.h, src/vim9script.c, src/testdir/test_vim9_expr.vim *** ../vim-8.2.4641/src/vim9execute.c 2022-03-27 16:29:49.880153368 +0100 --- src/vim9execute.c 2022-03-28 14:19:53.145273413 +0100 *************** *** 1336,1355 **** * When the value of "sv" is a null list of dict, allocate it. */ static void ! allocate_if_null(typval_T *tv) { switch (tv->v_type) { case VAR_LIST: ! if (tv->vval.v_list == NULL) (void)rettv_list_alloc(tv); break; case VAR_DICT: ! if (tv->vval.v_dict == NULL) (void)rettv_dict_alloc(tv); break; case VAR_BLOB: ! if (tv->vval.v_blob == NULL) (void)rettv_blob_alloc(tv); break; default: --- 1336,1357 ---- * When the value of "sv" is a null list of dict, allocate it. */ static void ! allocate_if_null(svar_T *sv) { + typval_T *tv = sv->sv_tv; + switch (tv->v_type) { case VAR_LIST: ! if (tv->vval.v_list == NULL && sv->sv_type != &t_list_empty) (void)rettv_list_alloc(tv); break; case VAR_DICT: ! if (tv->vval.v_dict == NULL && sv->sv_type != &t_dict_empty) (void)rettv_dict_alloc(tv); break; case VAR_BLOB: ! if (tv->vval.v_blob == NULL && sv->sv_type != &t_blob_null) (void)rettv_blob_alloc(tv); break; default: *************** *** 2891,2897 **** sv = get_script_svar(sref, ectx->ec_dfunc_idx); if (sv == NULL) goto theend; ! allocate_if_null(sv->sv_tv); if (GA_GROW_FAILS(&ectx->ec_stack, 1)) goto theend; copy_tv(sv->sv_tv, STACK_TV_BOT(0)); --- 2893,2899 ---- sv = get_script_svar(sref, ectx->ec_dfunc_idx); if (sv == NULL) goto theend; ! allocate_if_null(sv); if (GA_GROW_FAILS(&ectx->ec_stack, 1)) goto theend; copy_tv(sv->sv_tv, STACK_TV_BOT(0)); *** ../vim-8.2.4641/src/vim9type.c 2022-03-12 21:28:18.528257721 +0000 --- src/vim9type.c 2022-03-28 14:15:16.026051733 +0100 *************** *** 337,343 **** --- 337,347 ---- if (tv->v_type == VAR_STRING) return &t_string; if (tv->v_type == VAR_BLOB) + { + if (tv->vval.v_blob == NULL) + return &t_blob_null; return &t_blob; + } if (tv->v_type == VAR_LIST) { *** ../vim-8.2.4641/src/globals.h 2022-03-27 20:04:16.025188554 +0100 --- src/globals.h 2022-03-28 14:16:23.977844545 +0100 *************** *** 405,410 **** --- 405,411 ---- EXTERN type_T t_float INIT6(VAR_FLOAT, 0, 0, TTFLAG_STATIC, NULL, NULL); EXTERN type_T t_string INIT6(VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL); EXTERN type_T t_blob INIT6(VAR_BLOB, 0, 0, TTFLAG_STATIC, NULL, NULL); + EXTERN type_T t_blob_null INIT6(VAR_BLOB, 0, 0, TTFLAG_STATIC, &t_void, NULL); EXTERN type_T t_job INIT6(VAR_JOB, 0, 0, TTFLAG_STATIC, NULL, NULL); EXTERN type_T t_channel INIT6(VAR_CHANNEL, 0, 0, TTFLAG_STATIC, NULL, NULL); *** ../vim-8.2.4641/src/evalvars.c 2022-03-27 16:50:58.925557951 +0100 --- src/evalvars.c 2022-03-28 14:59:44.060297207 +0100 *************** *** 2823,2829 **** { if (tv->v_type == VAR_DICT && tv->vval.v_dict == NULL && ((type != NULL && type != &t_dict_empty) ! || !in_vim9script())) { tv->vval.v_dict = dict_alloc(); if (tv->vval.v_dict != NULL) --- 2823,2829 ---- { if (tv->v_type == VAR_DICT && tv->vval.v_dict == NULL && ((type != NULL && type != &t_dict_empty) ! || !in_vim9script())) { tv->vval.v_dict = dict_alloc(); if (tv->vval.v_dict != NULL) *************** *** 2843,2848 **** --- 2843,2856 ---- tv->vval.v_list->lv_type = alloc_type(type); } } + else if (tv->v_type == VAR_BLOB && tv->vval.v_blob == NULL + && ((type != NULL && type != &t_blob_null) + || !in_vim9script())) + { + tv->vval.v_blob = blob_alloc(); + if (tv->vval.v_blob != NULL) + ++tv->vval.v_blob->bv_refcount; + } } copy_tv(tv, rettv); } *** ../vim-8.2.4641/src/vim.h 2022-03-27 20:04:16.029188564 +0100 --- src/vim.h 2022-03-28 14:59:26.124294565 +0100 *************** *** 2229,2234 **** --- 2229,2235 ---- #define ASSIGN_UNPACK 0x10 // using [a, b] = list #define ASSIGN_NO_MEMBER_TYPE 0x20 // use "any" for list and dict member type #define ASSIGN_FOR_LOOP 0x40 // assigning to loop variable + #define ASSIGN_INIT 0x80 // not assigning a value, just a declaration #include "ex_cmds.h" // Ex command defines #include "spell.h" // spell checking stuff *** ../vim-8.2.4641/src/vim9script.c 2022-03-22 12:13:49.147376718 +0000 --- src/vim9script.c 2022-03-28 14:59:55.024298561 +0100 *************** *** 822,828 **** init_tv.v_type = VAR_NUMBER; else init_tv.v_type = type->tt_type; ! set_var_const(name, 0, type, &init_tv, FALSE, 0, 0); vim_free(name); return p; --- 822,828 ---- init_tv.v_type = VAR_NUMBER; else init_tv.v_type = type->tt_type; ! set_var_const(name, 0, type, &init_tv, FALSE, ASSIGN_INIT, 0); vim_free(name); return p; *************** *** 925,930 **** --- 925,937 ---- if (*type == NULL) *type = typval2type(tv, get_copyID(), &si->sn_type_list, do_member ? TVTT_DO_MEMBER : 0); + else if ((flags & ASSIGN_INIT) == 0 + && (*type)->tt_type == VAR_BLOB && tv->v_type == VAR_BLOB + && tv->vval.v_blob == NULL) + { + // "var b: blob = null_blob" has a different type. + *type = &t_blob_null; + } if (sv->sv_type_allocated) free_type(sv->sv_type); if (*type != NULL && ((*type)->tt_type == VAR_FUNC *** ../vim-8.2.4641/src/testdir/test_vim9_expr.vim 2022-03-27 16:29:49.880153368 +0100 --- src/testdir/test_vim9_expr.vim 2022-03-28 14:20:34.405170440 +0100 *************** *** 890,895 **** --- 890,982 ---- unlet g:null_dict unlet g:not_null_list + # variables declared at script level used in a :def function + lines =<< trim END + vim9script + + var l_decl: list + var l_empty = [] + var l_null = null_list + + def TestList() + assert_false(l_decl == null) + assert_false(l_decl is null_list) + assert_false(l_empty == null) + assert_false(l_empty is null_list) + assert_true(l_null == null) + assert_true(l_null is null_list) + assert_true(l_null == null_list) + + add(l_decl, 6) + assert_equal([6], l_decl) + add(l_empty, 7) + assert_equal([7], l_empty) + var caught = false + try + add(l_null, 9) + catch /E1130:/ + caught = true + endtry + assert_true(caught) + enddef + TestList() + + var b_decl: blob + var b_empty = 0z + var b_null = null_blob + + def TestBlob() + assert_false(b_decl == null) + assert_false(b_decl is null_blob) + assert_false(b_empty == null) + assert_false(b_empty is null_blob) + assert_true(b_null == null) + assert_true(b_null is null_blob) + assert_true(b_null == null_blob) + + add(b_decl, 6) + assert_equal(0z06, b_decl) + add(b_empty, 7) + assert_equal(0z07, b_empty) + var caught = false + try + add(b_null, 9) + catch /E1131:/ + caught = true + endtry + assert_true(caught) + enddef + TestBlob() + + var d_decl: dict + var d_empty = {} + var d_null = null_dict + + def TestDict() + assert_false(d_decl == null) + assert_false(d_decl is null_dict) + assert_false(d_empty == null) + assert_false(d_empty is null_dict) + assert_true(d_null == null) + assert_true(d_null is null_dict) + assert_true(d_null == null_dict) + + d_decl['a'] = 6 + assert_equal({a: 6}, d_decl) + d_empty['b'] = 7 + assert_equal({b: 7}, d_empty) + var caught = false + try + d_null['c'] = 9 + catch /E1103:/ + caught = true + endtry + assert_true(caught) + enddef + TestDict() + END + v9.CheckScriptSuccess(lines) + lines =<< trim END var d: dict = {f: null_function} assert_equal(null_function, d.f) *** ../vim-8.2.4641/src/version.c 2022-03-28 12:41:14.406200360 +0100 --- src/version.c 2022-03-28 15:21:26.974698823 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 4642, /**/ -- 5 out of 4 people have trouble with fractions. /// 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 ///