summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErnie Rael <errael@raelity.com>2023-08-27 18:40:26 +0200
committerChristian Brabandt <cb@256bit.org>2023-08-27 18:40:26 +0200
commit5c018bee0e1e272774584cfb1577327fbb67254a (patch)
tree8ac0883f1e7b9ea2fea36e27d4a293a0223af2d0
parentd4e4ecbb3793cd45b645471966c1ac703be52f4a (diff)
patch 9.0.1796: Vim9 problems with null_objectsv9.0.1796
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 <cb@256bit.org> Co-authored-by: Ernie Rael <errael@raelity.com>
-rw-r--r--src/proto/vim9instr.pro1
-rw-r--r--src/testdir/test_vim9_class.vim42
-rw-r--r--src/typval.c3
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c4
-rw-r--r--src/vim9instr.c4
-rw-r--r--src/vim9type.c2
7 files changed, 54 insertions, 4 deletions
diff --git a/src/proto/vim9instr.pro b/src/proto/vim9instr.pro
index 6850948289..1ba5639a56 100644
--- 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
index a650cc2509..2c6a501b45 100644
--- 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<Background> but got object<Unknown>')
+ 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<Unknown>', 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
index e8aebee546..c159cc99ab 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -1578,12 +1578,15 @@ typval_compare_null(typval_T *tv1, typval_T *tv2)
#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
index fed588e577..a41fc69855 100644
--- 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
index 7427f258f8..add9eda60b 100644
--- 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
index 941adf8897..3e9c6b6e8e 100644
--- 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
index c42e4f4931..3955ce2f65 100644
--- 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;