]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1796: Vim9 problems with null_objects v9.0.1796
authorErnie Rael <errael@raelity.com>
Sun, 27 Aug 2023 16:40:26 +0000 (18:40 +0200)
committerChristian Brabandt <cb@256bit.org>
Sun, 27 Aug 2023 16:40:26 +0000 (18:40 +0200)
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>
src/proto/vim9instr.pro
src/testdir/test_vim9_class.vim
src/typval.c
src/version.c
src/vim9compile.c
src/vim9instr.c
src/vim9type.c

index 6850948289e84a2526feb653851ae78946b946d2..1ba5639a562bf53db8660b1a0381631a40d9dded 100644 (file)
@@ -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);
index a650cc2509da5422f4a021c5de8f3fd566ce9f93..2c6a501b45df0b0c8c44c2b307ff26fcf10a24ec 100644 (file)
@@ -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
index e8aebee54654ada63cf6d4847a09e202a4e14456..c159cc99ab113e5da8492bfe52766bbeb9185c2d 100644 (file)
@@ -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;
 
index fed588e57787f8e1f544644e9d810b24c59e695e..a41fc69855f5b1f62c72c89335edf41015821204 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1796,
 /**/
     1795,
 /**/
index 7427f258f8724a73b4559882f7f4013465c98467..add9eda60b5ad725617452c6e0c04a1240898304 100644 (file)
@@ -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
index 941adf8897c99dab3f1ec29249473893de161bea..3e9c6b6e8eb35e0668fa5480898d1737ce79ddca 100644 (file)
@@ -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;
 }
index c42e4f4931943f93d06fe8350eca8ff80cc82f5f..3955ce2f656b6ff74a6ac8b4e86d2dce63ee473a 100644 (file)
@@ -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;