patch 8.2.1798: Vim9: trinary operator condition is too permissive
Problem: Vim9: trinary operator condition is too permissive.
Solution: Use tv_get_bool_chk().
diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim
index 1086534..754f856 100644
--- a/src/testdir/test_expr.vim
+++ b/src/testdir/test_expr.vim
@@ -42,6 +42,16 @@
call assert_false(has('patch-9.9.1'))
endfunc
+func Test_op_trinary()
+ call assert_equal('yes', 1 ? 'yes' : 'no')
+ call assert_equal('no', 0 ? 'yes' : 'no')
+ call assert_equal('no', 'x' ? 'yes' : 'no')
+ call assert_equal('yes', '1x' ? 'yes' : 'no')
+
+ call assert_fails('echo [1] ? "yes" : "no"', 'E745:')
+ call assert_fails('echo {} ? "yes" : "no"', 'E728:')
+endfunc
+
func Test_op_falsy()
call assert_equal(v:true, v:true ?? 456)
call assert_equal(123, 123 ?? 456)
diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index 82d5f32..599c287 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -68,6 +68,74 @@
CheckScriptSuccess(lines)
enddef
+def Test_condition_types()
+ var lines =<< trim END
+ if 'text'
+ endif
+ END
+ CheckDefAndScriptFailure(lines, 'E1030:', 1)
+
+ lines =<< trim END
+ if [1]
+ endif
+ END
+ CheckDefFailure(lines, 'E1012:', 1)
+ CheckScriptFailure(['vim9script'] + lines, 'E745:', 2)
+
+ lines =<< trim END
+ g:cond = 'text'
+ if g:cond
+ endif
+ END
+ CheckDefExecAndScriptFailure(lines, 'E1030:', 2)
+
+ lines =<< trim END
+ g:cond = 0
+ if g:cond
+ elseif 'text'
+ endif
+ END
+ CheckDefFailure(lines, 'E1012:', 3)
+ CheckScriptFailure(['vim9script'] + lines, 'E1030:', 4)
+
+ lines =<< trim END
+ if g:cond
+ elseif [1]
+ endif
+ END
+ CheckDefFailure(lines, 'E1012:', 2)
+ CheckScriptFailure(['vim9script'] + lines, 'E745:', 3)
+
+ lines =<< trim END
+ g:cond = 'text'
+ if 0
+ elseif g:cond
+ endif
+ END
+ CheckDefExecAndScriptFailure(lines, 'E1030:', 3)
+
+ lines =<< trim END
+ while 'text'
+ endwhile
+ END
+ CheckDefFailure(lines, 'E1012:', 1)
+ CheckScriptFailure(['vim9script'] + lines, 'E1030:', 2)
+
+ lines =<< trim END
+ while [1]
+ endwhile
+ END
+ CheckDefFailure(lines, 'E1012:', 1)
+ CheckScriptFailure(['vim9script'] + lines, 'E745:', 2)
+
+ lines =<< trim END
+ g:cond = 'text'
+ while g:cond
+ endwhile
+ END
+ CheckDefExecAndScriptFailure(lines, 'E1030:', 2)
+enddef
+
def Test_if_linebreak()
var lines =<< trim END
vim9script
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index 5158e10..2cbb285 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -18,27 +18,27 @@
'one' :
'two')
if has('float')
- assert_equal('one', 0.1 ? 'one' : 'two')
+ assert_equal('one', !!0.1 ? 'one' : 'two')
endif
- assert_equal('one', 'x' ? 'one' : 'two')
- assert_equal('one', 'x'
+ assert_equal('one', !!'x' ? 'one' : 'two')
+ assert_equal('one', !!'x'
? 'one'
: 'two')
- assert_equal('one', 0z1234 ? 'one' : 'two')
- assert_equal('one', [0] ? 'one' : 'two')
- assert_equal('one', #{x: 0} ? 'one' : 'two')
+ assert_equal('one', !!0z1234 ? 'one' : 'two')
+ assert_equal('one', !![0] ? 'one' : 'two')
+ assert_equal('one', !!#{x: 0} ? 'one' : 'two')
var name = 1
assert_equal('one', name ? 'one' : 'two')
assert_equal('two', false ? 'one' : 'two')
assert_equal('two', 0 ? 'one' : 'two')
if has('float')
- assert_equal('two', 0.0 ? 'one' : 'two')
+ assert_equal('two', !!0.0 ? 'one' : 'two')
endif
- assert_equal('two', '' ? 'one' : 'two')
- assert_equal('two', 0z ? 'one' : 'two')
- assert_equal('two', [] ? 'one' : 'two')
- assert_equal('two', {} ? 'one' : 'two')
+ assert_equal('two', !!'' ? 'one' : 'two')
+ assert_equal('two', !!0z ? 'one' : 'two')
+ assert_equal('two', !![] ? 'one' : 'two')
+ assert_equal('two', !!{} ? 'one' : 'two')
name = 0
assert_equal('two', name ? 'one' : 'two')
@@ -117,6 +117,24 @@
END
CheckScriptFailure(lines, 'E1004:', 2)
+ lines =<< trim END
+ vim9script
+ var name = 'x' ? 1 : 2
+ END
+ CheckScriptFailure(lines, 'E1030:', 2)
+
+ lines =<< trim END
+ vim9script
+ var name = [] ? 1 : 2
+ END
+ CheckScriptFailure(lines, 'E745:', 2)
+
+ lines =<< trim END
+ vim9script
+ var name = {} ? 1 : 2
+ END
+ CheckScriptFailure(lines, 'E728:', 2)
+
# check after failure eval_flags is reset
lines =<< trim END
vim9script
@@ -152,6 +170,15 @@
call CheckDefFailure(["var x = 1 ? 'one' :'two'"], msg, 1)
call CheckDefFailure(["var x = 1 ? 'one':'two'"], msg, 1)
+ call CheckDefFailure(["var x = 'x' ? 'one' : 'two'"], 'E1030:', 1)
+ call CheckDefFailure(["var x = 0z1234 ? 'one' : 'two'"], 'E974:', 1)
+ call CheckDefExecFailure(["var x = [] ? 'one' : 'two'"], 'E745:', 1)
+ call CheckDefExecFailure(["var x = {} ? 'one' : 'two'"], 'E728:', 1)
+
+ if has('float')
+ call CheckDefFailure(["var x = 0.1 ? 'one' : 'two'"], 'E805:', 1)
+ endif
+
" missing argument detected even when common type is used
call CheckDefFailure([
\ 'var X = FuncOne',
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 6dbabe3..7fc5223 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -543,7 +543,7 @@
CheckDefFailure(['endtry'], 'E602:')
CheckDefFailure(['while 1', 'endtry'], 'E170:')
CheckDefFailure(['for i in range(5)', 'endtry'], 'E170:')
- CheckDefFailure(['if 2', 'endtry'], 'E171:')
+ CheckDefFailure(['if 1', 'endtry'], 'E171:')
CheckDefFailure(['try', 'echo 1', 'endtry'], 'E1032:')
CheckDefFailure(['throw'], 'E1015:')
diff --git a/src/testdir/vim9.vim b/src/testdir/vim9.vim
index 2e4b03f..aeeb5a3 100644
--- a/src/testdir/vim9.vim
+++ b/src/testdir/vim9.vim
@@ -52,3 +52,10 @@
CheckDefFailure(lines, error, lnum)
CheckScriptFailure(['vim9script'] + lines, error, lnum + 1)
enddef
+
+" Check that a command fails both when executed in a :def function and when
+" used in Vim9 script.
+def CheckDefExecAndScriptFailure(lines: list<string>, error: string, lnum = -3)
+ CheckDefExecFailure(lines, error, lnum)
+ CheckScriptFailure(['vim9script'] + lines, error, lnum + 1)
+enddef