# HG changeset patch # User Christian Brabandt # Date 1693154708 -7200 # Node ID ba1b40b520e83810f3128c9698e610244038a001 # Parent e7561ca6e020910d622315764e56e99516b6ca5e patch 9.0.1796: Vim9 problems with null_objects Commit: https://github.com/vim/vim/commit/5c018bee0e1e272774584cfb1577327fbb67254a Author: Ernie Rael Date: Sun Aug 27 18:40:26 2023 +0200 patch 9.0.1796: Vim9 problems with null_objects Problem: Vim9 problems with null_objects Solution: Vim9 improve null_object usage Fix "xvar == null", where xvar might have been assigned null_object. Fix compilation failure: "var o2: C = null_object". closes: #12890 Signed-off-by: Christian Brabandt Co-authored-by: Ernie Rael diff --git a/src/proto/vim9instr.pro b/src/proto/vim9instr.pro --- a/src/proto/vim9instr.pro +++ b/src/proto/vim9instr.pro @@ -28,6 +28,7 @@ int generate_PUSHCHANNEL(cctx_T *cctx); int generate_PUSHJOB(cctx_T *cctx); int generate_PUSHBLOB(cctx_T *cctx, blob_T *blob); int generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type, int may_prefix); +int generate_PUSHOBJ(cctx_T *cctx); int generate_AUTOLOAD(cctx_T *cctx, char_u *name, type_T *type); int generate_GETITEM(cctx_T *cctx, int index, int with_op); int generate_SLICE(cctx_T *cctx, int count); diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -337,7 +337,7 @@ def Test_object_not_set() var bg: Background # UNINITIALIZED echo Colorscheme.new(bg).GetBackground() END - v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object but got object') + v9.CheckScriptFailure(lines, 'E1360:') # TODO: this should not give an error but be handled at runtime lines =<< trim END @@ -359,6 +359,46 @@ def Test_object_not_set() v9.CheckScriptFailure(lines, 'E1363:') enddef +def Test_null_object_assign_compare() + var lines =<< trim END + vim9script + + var nullo = null_object + def F(): any + return nullo + enddef + assert_equal('object', typename(F())) + + var o0 = F() + assert_true(o0 == null_object) + assert_true(o0 == null) + + var o1: any = nullo + assert_true(o1 == null_object) + assert_true(o1 == null) + + def G() + var x = null_object + enddef + + class C + endclass + var o2: C + assert_true(o2 == null_object) + assert_true(o2 == null) + + o2 = null_object + assert_true(o2 == null) + + o2 = C.new() + assert_true(o2 != null) + + o2 = null_object + assert_true(o2 == null) + END + v9.CheckScriptSuccess(lines) +enddef + def Test_class_member_initializer() var lines =<< trim END vim9script diff --git a/src/typval.c b/src/typval.c --- a/src/typval.c +++ b/src/typval.c @@ -1578,12 +1578,15 @@ typval_compare_null(typval_T *tv1, typva #ifdef FEAT_JOB_CHANNEL case VAR_CHANNEL: return tv->vval.v_channel == NULL; #endif + // TODO: null_class handling + // case VAR_CLASS: return tv->vval.v_class == NULL; case VAR_DICT: return tv->vval.v_dict == NULL; case VAR_FUNC: return tv->vval.v_string == NULL; #ifdef FEAT_JOB_CHANNEL case VAR_JOB: return tv->vval.v_job == NULL; #endif case VAR_LIST: return tv->vval.v_list == NULL; + case VAR_OBJECT: return tv->vval.v_object == NULL; case VAR_PARTIAL: return tv->vval.v_partial == NULL; case VAR_STRING: return tv->vval.v_string == NULL; diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -700,6 +700,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1796, +/**/ 1795, /**/ 1794, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2299,6 +2299,9 @@ push_default_value( case VAR_CHANNEL: r = generate_PUSHCHANNEL(cctx); break; + case VAR_OBJECT: + r = generate_PUSHOBJ(cctx); + break; case VAR_NUMBER: case VAR_UNKNOWN: case VAR_ANY: @@ -2306,7 +2309,6 @@ push_default_value( case VAR_VOID: case VAR_INSTR: case VAR_CLASS: - case VAR_OBJECT: case VAR_SPECIAL: // cannot happen // This is skipped for local variables, they are always // initialized to zero. But in a "for" or "while" loop diff --git a/src/vim9instr.c b/src/vim9instr.c --- a/src/vim9instr.c +++ b/src/vim9instr.c @@ -662,11 +662,11 @@ generate_SETTYPE( /* * Generate an ISN_PUSHOBJ instruction. Object is always NULL. */ - static int + int generate_PUSHOBJ(cctx_T *cctx) { RETURN_OK_IF_SKIP(cctx); - if (generate_instr_type(cctx, ISN_PUSHOBJ, &t_any) == NULL) + if (generate_instr_type(cctx, ISN_PUSHOBJ, &t_object) == NULL) return FAIL; return OK; } diff --git a/src/vim9type.c b/src/vim9type.c --- a/src/vim9type.c +++ b/src/vim9type.c @@ -907,6 +907,8 @@ check_type_maybe( return MAYBE; // use runtime type check if (actual->tt_type != VAR_OBJECT) return FAIL; // don't use tt_class + if (actual->tt_class == NULL) + return OK; // A null object matches if (class_instance_of(actual->tt_class, expected->tt_class) == FALSE) ret = FAIL;