Skip to content

Commit a9d01da

Browse files
h-eastchrisbra
authored andcommitted
patch 9.2.0292: E340 internal error when using method call on void value
Problem: E340 internal error when using method call on void value (Peter Kenny) Solution: Check for void value (Hirohito Higashi) Using a method call on a void return value (e.g. "echo F()->empty()" where F() returns void) caused an internal error E340. Now it properly reports E1031 or E1186 depending on the context. Changes: - eval.c: check for void value before -> method call at runtime - vim9expr.c: check for void type before -> method call at compile time - vim9execute.c: check for void value in builtin function arguments and in ISN_STORE fixes: #19897 closes: #19912 Signed-off-by: Hirohito Higashi <h.east.727@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent cb51add commit a9d01da

7 files changed

Lines changed: 174 additions & 5 deletions

File tree

src/eval.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7566,7 +7566,13 @@ handle_subscript(
75667566
*arg = skipwhite(p + 2);
75677567
else
75687568
*arg = p + 2;
7569-
if (VIM_ISWHITE(**arg))
7569+
if (ret == OK && evaluate && rettv->v_type == VAR_VOID)
7570+
{
7571+
if (verbose)
7572+
emsg(_(e_cannot_use_void_value));
7573+
ret = FAIL;
7574+
}
7575+
else if (VIM_ISWHITE(**arg))
75707576
{
75717577
emsg(_(e_no_white_space_allowed_before_parenthesis));
75727578
ret = FAIL;

src/testdir/test_vim9_builtin.vim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ enddef
402402

403403
def Test_bufload()
404404
assert_fails('bufload([])', 'E1220:')
405-
bufload('')->assert_equal(0)
405+
bufload('')
406406
enddef
407407

408408
def Test_bufloaded()
@@ -647,7 +647,7 @@ def Test_ch_logfile()
647647
else
648648
assert_fails('ch_logfile(true)', 'E1174:')
649649
assert_fails('ch_logfile("foo", true)', 'E1174:')
650-
ch_logfile('', '')->assert_equal(0)
650+
ch_logfile('', '')
651651

652652
v9.CheckSourceDefAndScriptFailure(['ch_logfile(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1'])
653653
v9.CheckSourceDefAndScriptFailure(['ch_logfile("a", true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1174: String required for argument 2'])

src/testdir/test_vim9_expr.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3996,7 +3996,7 @@ def Test_expr9_method_call()
39963996
enddef
39973997
RetVoid()->byteidx(3)
39983998
END
3999-
v9.CheckDefExecFailure(lines, 'E1013:')
3999+
v9.CheckDefExecFailure(lines, 'E1031: Cannot use void value')
40004000

40014001
lines =<< trim END
40024002
const SetList = [function('len')]

src/testdir/test_vim9_func.vim

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4864,4 +4864,144 @@ if has('perl')
48644864
endif
48654865

48664866

4867+
def Test_void_method_chain()
4868+
#### Case 1: Echo, method chain source is void ####
4869+
# outside def: runtime error
4870+
var lines =<< trim END
4871+
vim9script
4872+
var Fn1a: func = (): void => {
4873+
}
4874+
echo Fn1a()->empty()
4875+
END
4876+
v9.CheckScriptFailure(lines, 'E1031: Cannot use void value')
4877+
4878+
# inside def, compile-time error (known void return)
4879+
lines =<< trim END
4880+
vim9script
4881+
def Fn1b(): void
4882+
enddef
4883+
def TestFunc()
4884+
echo Fn1b()->empty()
4885+
enddef
4886+
defcompile TestFunc
4887+
END
4888+
v9.CheckScriptFailure(lines, 'E1031: Cannot use void value')
4889+
4890+
# inside def, runtime error (untyped func)
4891+
lines =<< trim END
4892+
vim9script
4893+
def TestFunc()
4894+
var Fn1c: func = (): void => {
4895+
}
4896+
echo Fn1c()->empty()
4897+
enddef
4898+
TestFunc()
4899+
END
4900+
v9.CheckScriptFailure(lines, 'E1031: Cannot use void value')
4901+
4902+
# inside def, compile-time error (func(): void)
4903+
lines =<< trim END
4904+
vim9script
4905+
def TestFunc()
4906+
var Fn1d: func(): void = () => {
4907+
}
4908+
echo Fn1d()->empty()
4909+
enddef
4910+
defcompile TestFunc
4911+
END
4912+
v9.CheckScriptFailure(lines, 'E1031: Cannot use void value')
4913+
4914+
#### Case 2: Echo, method chain destination is void ####
4915+
# outside def: runtime error
4916+
lines =<< trim END
4917+
vim9script
4918+
var Fn2a: func = (s: string): void => {
4919+
}
4920+
echo "x"->Fn2a()
4921+
END
4922+
v9.CheckScriptFailure(lines, 'E1186: Expression does not result in a value: "x"->Fn2a()')
4923+
4924+
# inside def, compile-time error (known void return)
4925+
lines =<< trim END
4926+
vim9script
4927+
def Fn2b(s: string): void
4928+
enddef
4929+
def TestFunc()
4930+
echo "x"->Fn2b()
4931+
enddef
4932+
defcompile TestFunc
4933+
END
4934+
v9.CheckScriptFailure(lines, 'E1186: Expression does not result in a value: "x"->Fn2b()')
4935+
4936+
# inside def, runtime error (untyped func)
4937+
lines =<< trim END
4938+
vim9script
4939+
def TestFunc()
4940+
var Fn2c: func = (s: string): void => {
4941+
}
4942+
echo "x"->Fn2c()
4943+
enddef
4944+
TestFunc()
4945+
END
4946+
v9.CheckScriptFailure(lines, 'E1031: Cannot use void value')
4947+
4948+
# inside def, compile-time error (func(string): void)
4949+
lines =<< trim END
4950+
vim9script
4951+
def TestFunc()
4952+
var Fn2d: func(string): void = (s: string): void => {
4953+
}
4954+
echo "x"->Fn2d()
4955+
enddef
4956+
defcompile TestFunc
4957+
END
4958+
v9.CheckScriptFailure(lines, 'E1186: Expression does not result in a value: "x"->Fn2d()')
4959+
4960+
#### Case 3: Assignment, RHS is void ####
4961+
# outside def: runtime error
4962+
lines =<< trim END
4963+
vim9script
4964+
var Fn3a: func = (): void => {
4965+
}
4966+
var x = Fn3a()
4967+
END
4968+
v9.CheckScriptFailure(lines, 'E1031: Cannot use void value')
4969+
4970+
# inside def, compile-time error (known void return)
4971+
lines =<< trim END
4972+
vim9script
4973+
def Fn3b(): void
4974+
enddef
4975+
def TestFunc()
4976+
var x = Fn3b()
4977+
enddef
4978+
defcompile TestFunc
4979+
END
4980+
v9.CheckScriptFailure(lines, 'E1031: Cannot use void value')
4981+
4982+
# inside def, runtime error (untyped func)
4983+
lines =<< trim END
4984+
vim9script
4985+
def TestFunc()
4986+
var Fn3c: func = (): void => {
4987+
}
4988+
var x = Fn3c()
4989+
enddef
4990+
TestFunc()
4991+
END
4992+
v9.CheckScriptFailure(lines, 'E1031: Cannot use void value')
4993+
4994+
# inside def, compile-time error (func(): void)
4995+
lines =<< trim END
4996+
vim9script
4997+
def TestFunc()
4998+
var Fn3d: func(): void = () => {
4999+
}
5000+
var x = Fn3d()
5001+
enddef
5002+
defcompile TestFunc
5003+
END
5004+
v9.CheckScriptFailure(lines, 'E1031: Cannot use void value')
5005+
enddef
5006+
48675007
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ static char *(features[]) =
734734

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
292,
737739
/**/
738740
291,
739741
/**/

src/vim9execute.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,17 @@ call_bfunc(int func_idx, int argcount, ectx_T *ectx)
14121412

14131413
if (call_prepare(argcount, argvars, ectx) == FAIL)
14141414
return FAIL;
1415+
1416+
// Check for void value being passed as an argument.
1417+
for (idx = 0; idx < argcount; ++idx)
1418+
if (argvars[idx].v_type == VAR_VOID)
1419+
{
1420+
emsg(_(e_cannot_use_void_value));
1421+
for (idx = 0; idx < argcount; ++idx)
1422+
clear_tv(&argvars[idx]);
1423+
return FAIL;
1424+
}
1425+
14151426
ectx->ec_where.wt_func_name = internal_func_name(func_idx);
14161427

14171428
// Call the builtin function. Set "current_ectx" so that when it
@@ -4307,8 +4318,11 @@ exec_instructions(ectx_T *ectx)
43074318
case ISN_STORE:
43084319
--ectx->ec_stack.ga_len;
43094320
tv = STACK_TV_VAR(iptr->isn_arg.number);
4310-
if (check_typval_is_value(STACK_TV_BOT(0)) == FAIL)
4321+
if (check_typval_is_value(STACK_TV_BOT(0)) == FAIL
4322+
|| STACK_TV_BOT(0)->v_type == VAR_VOID)
43114323
{
4324+
if (STACK_TV_BOT(0)->v_type == VAR_VOID)
4325+
emsg(_(e_cannot_use_void_value));
43124326
clear_tv(STACK_TV_BOT(0));
43134327
goto on_error;
43144328
}

src/vim9expr.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2568,6 +2568,13 @@ compile_subscript(
25682568
return FAIL;
25692569
ppconst->pp_is_const = FALSE;
25702570

2571+
type = get_type_on_stack(cctx, 0);
2572+
if (type->tt_type == VAR_VOID)
2573+
{
2574+
emsg(_(e_cannot_use_void_value));
2575+
return FAIL;
2576+
}
2577+
25712578
// Apply the '!', '-' and '+' first:
25722579
// -1.0->func() works like (-1.0)->func()
25732580
if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)

0 commit comments

Comments
 (0)