patch 9.1.2106: Vim9: class, enum and type alias can be used as value

Commit: 
https://github.com/vim/vim/commit/7d22f84f0b8107fb2eb7edb5665f08daa5dae12a
Author: Yegappan Lakshmanan <[email protected]>
Date:   Fri Jan 23 19:17:29 2026 +0000

    patch 9.1.2106: Vim9: class, enum and type alias can be used as value
    
    Problem:  Vim9: class, enum and type alias can be used as value in an
              expression (kennypete)
    Solution: Abort expression evaluation if class, enum or type alias is
              used in an expression (Yegappan Lakshmanan)
    
    related: #19173
    closes:  #19238
    
    Signed-off-by: Yegappan Lakshmanan <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/src/eval.c b/src/eval.c
index 4a9f5821b..9678ea7f6 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3646,7 +3646,15 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
            int         error = FALSE;
 
            if (op_falsy)
+           {
+               // Is this typeval supported with the falsy operator?
+               if (check_typval_is_value(rettv) == FAIL)
+               {
+                   clear_tv(rettv);
+                   return FAIL;
+               }
                result = tv2bool(rettv);
+           }
            else if (vim9script)
                result = tv_get_bool_chk(rettv, &error);
            else if (tv_get_number_chk(rettv, &error) != 0)
@@ -5376,7 +5384,15 @@ eval9_leader(
        while (VIM_ISWHITE(end_leader[-1]))
            --end_leader;
        if (vim9script && end_leader[-1] == '!')
+       {
+           // Is this typeval supported with the ! operator?
+           if (check_typval_is_value(rettv) == FAIL)
+           {
+               clear_tv(rettv);
+               return FAIL;
+           }
            val = tv2bool(rettv);
+       }
        else
            val = tv_get_number_chk(rettv, &error);
     }
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index b66372884..4551ea5eb 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -280,6 +280,69 @@ def Test_expr1_falsy()
   END
   v9.CheckSourceScriptFailure(lines, 'E1405: Class "B" cannot be used as a 
value')
 
+  # Expression evaluation should stop after using a class with the falsy
+  # operator
+  lines =<< trim END
+    vim9script
+    class C
+    endclass
+    var output: string = 'pass'
+    try
+      echo C ?? 'falsy' !! execute("output = 'fail'")
+    catch /E1405:/
+    endtry
+    assert_equal('pass', output)
+  END
+  v9.CheckSourceScriptSuccess(lines)
+
+  # When using a class with the falsy operator, expression evaluation should
+  # be aborted in a function
+  g:falsy_output = 'pass'
+  lines =<< trim END
+    vim9script
+    class C
+    endclass
+    g:falsy_output = 'pass'
+    def Fn()
+      echo C ?? 'falsy' !! execute('g:falsy_output = "fail"')
+    enddef
+    Fn()
+  END
+  v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a 
value', 1)
+  assert_equal('pass', g:falsy_output)
+  unlet g:falsy_output
+
+  # When using a class with the "!" operator, expression evaluation should be
+  # aborted
+  lines =<< trim END
+    vim9script
+    class C
+    endclass
+    var output: string = 'pass'
+    try
+      echo !C !! execute("output = 'fail'")
+    catch /E1405:/
+    endtry
+    assert_equal('pass', output)
+  END
+  v9.CheckSourceScriptSuccess(lines)
+
+  # When using a class with the "!" operator, expression evaluation should be
+  # aborted in a function
+  g:falsy_output = 'pass'
+  lines =<< trim END
+    vim9script
+    class C
+    endclass
+    def Fn()
+      echo !C !! execute('g:falsy_output = "fail"')
+    enddef
+    Fn()
+  END
+  v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a 
value', 1)
+  assert_equal('pass', g:falsy_output)
+  unlet g:falsy_output
+
   lines =<< trim END
     vim9script
     echo null_class ?? 'falsy'
@@ -309,6 +372,68 @@ def Test_expr1_falsy()
   END
   v9.CheckSourceScriptFailure(lines, 'E1421: Enum "E2" cannot be used as a 
value')
 
+  # Expression evaluation should stop after using an enum with the falsy
+  # operator
+  lines =<< trim END
+    vim9script
+    enum E
+    endenum
+    var output: string = 'pass'
+    try
+      echo E ?? 'falsy' !! execute("output = 'fail'")
+    catch /E1421:/
+    endtry
+    assert_equal('pass', output)
+  END
+  v9.CheckSourceScriptSuccess(lines)
+
+  # When using a enum with the falsy operator, expression evaluation should
+  # be aborted in a function
+  g:falsy_output = 'pass'
+  lines =<< trim END
+    vim9script
+    enum E3
+    endenum
+    g:falsy_output = 'pass'
+    def Fn()
+      echo E3 ?? 'falsy' !! execute('g:falsy_output = "fail"')
+    enddef
+    Fn()
+  END
+  v9.CheckSourceScriptFailure(lines, 'E1421: Enum "E3" cannot be used as a 
value', 1)
+  assert_equal('pass', g:falsy_output)
+  unlet g:falsy_output
+
+  # Expression evaluation should stop after using an enum with the ! operator
+  lines =<< trim END
+    vim9script
+    enum E
+    endenum
+    var output: string = 'pass'
+    try
+      echo !E !! execute("output = 'fail'")
+    catch /E1421:/
+    endtry
+    assert_equal('pass', output)
+  END
+  v9.CheckSourceScriptSuccess(lines)
+
+  # When using a enum with the "!" operator, expression evaluation should be
+  # aborted in a function
+  g:falsy_output = 'pass'
+  lines =<< trim END
+    vim9script
+    enum E4
+    endenum
+    def Fn()
+      echo !E4 !! execute('g:falsy_output = "fail"')
+    enddef
+    Fn()
+  END
+  v9.CheckSourceScriptFailure(lines, 'E1421: Enum "E4" cannot be used as a 
value', 1)
+  assert_equal('pass', g:falsy_output)
+  unlet g:falsy_output
+
   # typealias cannot be used with the falsy operator
   lines =<< trim END
     vim9script
@@ -324,6 +449,65 @@ def Test_expr1_falsy()
   END
   v9.CheckSourceScriptFailure(lines, 'E1403: Type alias "T2" cannot be used as 
a value')
 
+  # Expression evaluation should stop after using a typealias with the falsy
+  # operator
+  lines =<< trim END
+    vim9script
+    type T3 = dict<string>
+    var output: string = 'pass'
+    try
+      echo T3 ?? 'falsy' !! execute("output = 'fail'")
+    catch /E1403:/
+    endtry
+    assert_equal('pass', output)
+  END
+  v9.CheckSourceScriptSuccess(lines)
+
+  # When using a typealias with the falsy operator, expression evaluation
+  # should be aborted in a function
+  g:falsy_output = 'pass'
+  lines =<< trim END
+    vim9script
+    type T3 = dict<job>
+    g:falsy_output = 'pass'
+    def Fn()
+      echo T3 ?? 'falsy' !! execute('g:falsy_output = "fail"')
+    enddef
+    Fn()
+  END
+  v9.CheckSourceScriptFailure(lines, 'E1407: Cannot use a Typealias as a 
variable or value', 1)
+  assert_equal('pass', g:falsy_output)
+  unlet g:falsy_output
+
+  # Expression evaluation should stop after using a typealias with the !
+  # operator
+  lines =<< trim END
+    vim9script
+    type T3 = dict<string>
+    var output: string = 'pass'
+    try
+      echo !T3 !! execute("output = 'fail'")
+    catch /E1403:/
+    endtry
+    assert_equal('pass', output)
+  END
+  v9.CheckSourceScriptSuccess(lines)
+
+  # When using a typealias with the "!" operator, expression evaluation should
+  # be aborted in a function
+  g:falsy_output = 'pass'
+  lines =<< trim END
+    vim9script
+    type T4 = list<number>
+    def Fn()
+      echo !T4 !! execute('g:falsy_output = "fail"')
+    enddef
+    Fn()
+  END
+  v9.CheckSourceScriptFailure(lines, 'E1407: Cannot use a Typealias as a 
variable or value', 1)
+  assert_equal('pass', g:falsy_output)
+  unlet g:falsy_output
+
   var msg = "White space required before and after '??'"
   call v9.CheckDefAndScriptFailure(["var x = 1?? 'one' : 'two'"], msg, 1)
   call v9.CheckDefAndScriptFailure(["var x = 1 ??'one' : 'two'"], msg, 1)
diff --git a/src/version.c b/src/version.c
index 1852977ac..5017e1d7b 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2106,
 /**/
     2105,
 /**/
diff --git a/src/vim9expr.c b/src/vim9expr.c
index c8353ab98..ebab9ec13 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -2430,6 +2430,8 @@ compile_leader(cctx_T *cctx, int numeric_only, char_u 
*start, char_u **end)
                    invert = !invert;
                --p;
            }
+           if (check_type_is_value(get_type_on_stack(cctx, 0)) == FAIL)
+               return FAIL;
            if (generate_2BOOL(cctx, invert, -1) == FAIL)
                return FAIL;
        }
@@ -3948,7 +3950,11 @@ compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T 
*ppconst)
            generate_JUMP(cctx, op_falsy
                                   ? JUMP_AND_KEEP_IF_TRUE : JUMP_IF_FALSE, 0);
            if (op_falsy)
+           {
                type1 = get_type_on_stack(cctx, -1);
+               if (check_type_is_value(type1) == FAIL)
+                   return FAIL;
+           }
        }
 
        // evaluate the second expression; any type is accepted

-- 
-- 
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 [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1vjMr5-00AHI7-TW%40256bit.org.

Raspunde prin e-mail lui