patch 9.1.1274: Vim9: no support for object<type> as variable type

Commit: 
https://github.com/vim/vim/commit/6fa62085ffbfb3c69636da857574a017783f0410
Author: Yegappan Lakshmanan <yegap...@yahoo.com>
Date:   Thu Apr 3 21:26:34 2025 +0200

    patch 9.1.1274: Vim9: no support for object<type> as variable type
    
    Problem:  Vim9: no support for object<type> as variable type
    Solution: add support for object<type> (Yegappan Lakshmanan)
    
    closes: #17041
    
    Signed-off-by: Yegappan Lakshmanan <yegap...@yahoo.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index 0e9a5080f..b7b2bcc5f 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -1,4 +1,4 @@
-*version9.txt*  For Vim version 9.1.  Last change: 2025 Mar 27
+*version9.txt*  For Vim version 9.1.  Last change: 2025 Apr 03
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -41553,6 +41553,8 @@ Enum support for Vim9 script |:enum|
 
 Support for protected _new() method
 
+Add support for object<{type}> as variable data type |vim9-types|
+
 Diff mode ~
 ---------
 Include the "linematch" algorithm for the 'diffopt' setting.  This aligns
diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt
index d06c250a3..54fb8f333 100644
--- a/runtime/doc/vim9.txt
+++ b/runtime/doc/vim9.txt
@@ -1,4 +1,4 @@
-*vim9.txt*     For Vim version 9.1.  Last change: 2025 Mar 23
+*vim9.txt*     For Vim version 9.1.  Last change: 2025 Apr 03
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1467,6 +1467,7 @@ The following builtin types are supported:
        blob
        list<{type}>
        dict<{type}>
+       object<{type}>
        job
        channel
        tuple<{type}>
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index c6d93b2b7..4b6cb81bb 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -12808,4 +12808,178 @@ def Test_dict_of_objects()
   v9.CheckSourceSuccess(lines)
 enddef
 
+" Test for using the type() and typename() functions with a variable of type
+" object
+def Test_type_typename_funcs_with_object_variable()
+  var lines =<< trim END
+    vim9script
+
+    class A
+    endclass
+
+    class B
+    endclass
+
+    var o1: object<any>
+    assert_equal([13, 'object<any>'], [type(o1), typename(o1)])
+
+    var o2: object<A>
+    assert_equal([13, 'object<any>'], [type(o2), typename(o2)])
+
+    var o3: A
+    assert_equal([13, 'object<any>'], [type(o3), typename(o3)])
+
+    var o4 = A.new()
+    assert_equal([13, 'object<A>'], [type(o4), typename(o4)])
+
+    var l = [A.new(), B.new()]
+    assert_equal([13, 'object<B>'], [type(l[1]), typename(l[1])])
+
+    var d = {o_a: A.new(), o_b: B.new()}
+    assert_equal([13, 'object<B>'], [type(d.o_b), typename(d.o_b)])
+  END
+  v9.CheckSourceSuccess(lines)
+enddef
+
+" Test for object<any> type
+def Test_object_any_type()
+  # assigning different objects to variable of type object<any>
+  var lines =<< trim END
+    vim9script
+    class A
+    endclass
+    class B
+    endclass
+    var x: object<any>
+    x = A.new()
+    assert_true(instanceof(x, A))
+    x = B.new()
+    assert_true(instanceof(x, B))
+    x = null_object
+    assert_true(instanceof(x, null_class))
+  END
+  v9.CheckSourceSuccess(lines)
+
+  # Use a list of object<any> variable
+  lines =<< trim END
+    vim9script
+    class A
+    endclass
+    class B
+    endclass
+    var l: list<object<any>>
+    l->add(A.new())
+    l->add(B.new())
+    assert_true(instanceof(l[0], A))
+    assert_true(instanceof(l[1], B))
+  END
+  v9.CheckSourceSuccess(lines)
+
+  # Using object<any> as a function argument type and the return type
+  lines =<< trim END
+    vim9script
+    class A
+    endclass
+    class B
+    endclass
+    def Fn(x: object<any>): object<any>
+      return x
+    enddef
+    assert_true(instanceof(Fn(A.new()), A))
+    assert_true(instanceof(Fn(B.new()), B))
+  END
+
+  # Try assigning a different type of value to a object<any> variable
+  lines =<< trim END
+    var x: object<any> = []
+  END
+  v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected 
object<any> but got list<any>', 'E1012: Type mismatch; expected object<any> but 
got list<any>'])
+
+  # Try assigning a different type of value to a object<any> variable
+  lines =<< trim END
+    var x: object<any>
+    x = 0z10
+  END
+  v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected 
object<any> but got blob', 'E1012: Type mismatch; expected object<any> but got 
blob'])
+
+  # Try adding a different type of value to a list<object<any>> variable
+  lines =<< trim END
+    var x: list<object<any>>
+    x->add({})
+  END
+  v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected 
object<any> but got dict<any>', 'E1012: Type mismatch; expected object<any> but 
got dict<any>'])
+
+  # Try adding a different type of value to a dict<object<any>> variable
+  lines =<< trim END
+    var x: dict<object<any>>
+    x['a'] = {}
+  END
+  v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected 
object<any> but got dict<any>', 'E1012: Type mismatch; expected object<any> but 
got dict<any>'])
+enddef
+
+" Test for object<{class}> type
+def Test_object_of_class_type()
+  var lines =<< trim END
+    vim9script
+    class A
+    endclass
+    var x: object<A>
+    x = A.new()
+    assert_true(instanceof(x, A))
+    var y: object<A> = A.new()
+    assert_true(instanceof(y, A))
+  END
+  v9.CheckSourceSuccess(lines)
+
+  lines =<< trim END
+    vim9script
+    class A
+    endclass
+    class B
+    endclass
+    var x: object<A>
+    x = B.new()
+  END
+  v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but 
got object<B>')
+
+  lines =<< trim END
+    vim9script
+    class A
+    endclass
+    class B
+    endclass
+    def Fn(x: object<A>): object<B>
+      return B.new()
+    enddef
+    assert_true(instanceof(Fn(A.new()), B))
+  END
+  v9.CheckSourceSuccess(lines)
+
+  lines =<< trim END
+    var x: object
+  END
+  v9.CheckSourceDefAndScriptFailure(lines, ['E1008: Missing <type> after 
object', 'E1008: Missing <type> after object'])
+
+  lines =<< trim END
+    var x: object <any>
+  END
+  v9.CheckSourceDefAndScriptFailure(lines, ['E1068: No white space allowed 
before ''<'':  <any>', 'E1068: No white space allowed before ''<'':  <any>'])
+
+  lines =<< trim END
+    var x: object<any
+  END
+  v9.CheckSourceDefAndScriptFailure(lines, ['E1009: Missing > after type: 
<any', 'E1009: Missing > after type: <any'])
+
+  lines =<< trim END
+    var x: object<any,any>
+  END
+  v9.CheckSourceDefFailure(lines, 'E1009: Missing > after type: <any,any>')
+
+  lines =<< trim END
+    vim9script
+    var x: object<any,any>
+  END
+  v9.CheckSourceFailure(lines, 'E488: Trailing characters: ,any>')
+enddef
+
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/version.c b/src/version.c
index e00e0077c..42576d1e8 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1274,
 /**/
     1273,
 /**/
diff --git a/src/vim9class.c b/src/vim9class.c
index 5249f40de..560c5ae28 100644
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -4132,7 +4132,12 @@ f_instanceof(typval_T *argvars, typval_T *rettv)
        return;
 
     if (object_tv->vval.v_object == NULL)
+    {
+       if (classinfo_tv->vval.v_class == NULL)
+           // consider null_object as an instance of null_class
+           rettv->vval.v_number = VVAL_TRUE;
        return;
+    }
 
     for (; classinfo_tv->v_type != VAR_UNKNOWN; ++classinfo_tv)
     {
diff --git a/src/vim9type.c b/src/vim9type.c
index 2f8509587..a3881c9b1 100644
--- a/src/vim9type.c
+++ b/src/vim9type.c
@@ -1784,6 +1784,63 @@ on_err:
     return ret_type;
 }
 
+/*
+ * Parse a "object" type at "*arg" and advance over it.
+ * When "give_error" is TRUE give error messages, otherwise be quiet.
+ * Return NULL for failure.
+ */
+    static type_T *
+parse_type_object(char_u **arg, garray_T *type_gap, int give_error)
+{
+    char_u     *arg_start = *arg;
+    type_T     *object_type;
+    int                prev_called_emsg = called_emsg;
+
+    // object<X> or object<any>
+    if (**arg != '<')
+    {
+       if (give_error)
+       {
+           if (*skipwhite(*arg) == '<')
+               semsg(_(e_no_white_space_allowed_before_str_str), "<", *arg);
+           else
+               semsg(_(e_missing_type_after_str), "object");
+       }
+
+       // only "object" is specified
+       return NULL;
+    }
+
+    // skip spaces following "object<"
+    *arg = skipwhite(*arg + 1);
+
+    object_type = parse_type(arg, type_gap, give_error);
+    if (object_type == NULL)
+       return NULL;
+
+    *arg = skipwhite(*arg);
+    if (**arg != '>' && called_emsg == prev_called_emsg)
+    {
+       if (give_error)
+           semsg(_(e_missing_gt_after_type_str), arg_start);
+       return NULL;
+    }
+    ++*arg;
+
+    if (object_type->tt_type == VAR_ANY)
+       return &t_object_any;
+
+    if (object_type->tt_type != VAR_OBJECT)
+    {
+       // specified type is not a class
+       if (give_error)
+           semsg(_(e_class_name_not_found_str), arg_start);
+       return NULL;
+    }
+
+    return object_type;
+}
+
 /*
  * Parse a user defined type at "*arg" and advance over it.
  * It can be a class or an interface or a typealias name, possibly imported.
@@ -1932,6 +1989,13 @@ parse_type(char_u **arg, garray_T *type_gap, int 
give_error)
                return &t_number;
            }
            break;
+       case 'o':
+           if (len == 6 && STRNCMP(*arg, "object", len) == 0)
+           {
+               *arg += len;
+               return parse_type_object(arg, type_gap, give_error);
+           }
+           break;
        case 's':
            if (len == 6 && STRNCMP(*arg, "string", len) == 0)
            {

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1u0QUq-00G4f0-42%40256bit.org.

Raspunde prin e-mail lui