Skip to content

Commit 4fc224c

Browse files
committed
patch 8.2.1300: Vim9: optional argument type not parsed properly
Problem: Vim9: optional argument type not parsed properly. Solution: Skip over the "?". (issue #6507)
1 parent 2547aa9 commit 4fc224c

6 files changed

Lines changed: 37 additions & 11 deletions

File tree

src/evalvars.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ skip_var_one(char_u *arg, int include_type)
10131013
if (end == arg + 2 && end[-1] == ':')
10141014
--end;
10151015
if (*end == ':')
1016-
end = skip_type(skipwhite(end + 1));
1016+
end = skip_type(skipwhite(end + 1), FALSE);
10171017
}
10181018
return end;
10191019
}

src/proto/vim9compile.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap);
66
int check_typval_type(type_T *expected, typval_T *actual_tv);
77
int check_type(type_T *expected, type_T *actual, int give_msg);
88
int check_compare_types(exptype_T type, typval_T *tv1, typval_T *tv2);
9-
char_u *skip_type(char_u *start);
9+
char_u *skip_type(char_u *start, int optional);
1010
type_T *parse_type(char_u **arg, garray_T *type_gap);
1111
char *vartype_name(vartype_T type);
1212
char *type_name(type_T *type, char **tofree);

src/testdir/test_vim9_func.vim

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,19 @@ def Test_call_funcref()
350350
let Funcref: func(string) = function('UseNumber')
351351
END
352352
CheckScriptFailure(lines, 'E1013: type mismatch, expected func(string) but got func(number)')
353+
354+
lines =<< trim END
355+
vim9script
356+
def EchoNr(nr = 34)
357+
g:echo = nr
358+
enddef
359+
let Funcref: func(?number) = function('EchoNr')
360+
Funcref()
361+
assert_equal(34, g:echo)
362+
Funcref(123)
363+
assert_equal(123, g:echo)
364+
END
365+
CheckScriptSuccess(lines)
353366
enddef
354367

355368
let SomeFunc = function('len')

src/userfunc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ one_function_arg(char_u *arg, garray_T *newargs, garray_T *argtypes, int skip)
123123
return arg;
124124
}
125125
type = skipwhite(p);
126-
p = skip_type(type);
126+
p = skip_type(type, TRUE);
127127
type = vim_strnsave(type, p - type);
128128
}
129129
else if (*skipwhite(p) != '=')
@@ -2778,7 +2778,7 @@ def_function(exarg_T *eap, char_u *name_arg)
27782778
if (*p == ':')
27792779
{
27802780
ret_type = skipwhite(p + 1);
2781-
p = skip_type(ret_type);
2781+
p = skip_type(ret_type, FALSE);
27822782
if (p > ret_type)
27832783
{
27842784
ret_type = vim_strnsave(ret_type, p - ret_type);

src/version.c

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

755755
static int included_patches[] =
756756
{ /* Add new patch number below this line */
757+
/**/
758+
1300,
757759
/**/
758760
1299,
759761
/**/

src/vim9compile.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,16 @@ typval2type(typval_T *tv, garray_T *type_gap)
534534
if (name != NULL)
535535
// TODO: how about a builtin function?
536536
ufunc = find_func(name, FALSE, NULL);
537-
if (ufunc != NULL && ufunc->uf_func_type != NULL)
538-
return ufunc->uf_func_type;
537+
if (ufunc != NULL)
538+
{
539+
// May need to get the argument types from default values by
540+
// compiling the function.
541+
if (ufunc->uf_def_status == UF_TO_BE_COMPILED
542+
&& compile_def_function(ufunc, TRUE, NULL) == FAIL)
543+
return NULL;
544+
if (ufunc->uf_func_type != NULL)
545+
return ufunc->uf_func_type;
546+
}
539547
}
540548

541549
actual = alloc_type(type_gap);
@@ -1916,20 +1924,23 @@ free_locals(cctx_T *cctx)
19161924

19171925
/*
19181926
* Skip over a type definition and return a pointer to just after it.
1927+
* When "optional" is TRUE then a leading "?" is accepted.
19191928
*/
19201929
char_u *
1921-
skip_type(char_u *start)
1930+
skip_type(char_u *start, int optional)
19221931
{
19231932
char_u *p = start;
19241933

1934+
if (optional && *p == '?')
1935+
++p;
19251936
while (ASCII_ISALNUM(*p) || *p == '_')
19261937
++p;
19271938

19281939
// Skip over "<type>"; this is permissive about white space.
19291940
if (*skipwhite(p) == '<')
19301941
{
19311942
p = skipwhite(p);
1932-
p = skip_type(skipwhite(p + 1));
1943+
p = skip_type(skipwhite(p + 1), FALSE);
19331944
p = skipwhite(p);
19341945
if (*p == '>')
19351946
++p;
@@ -1945,7 +1956,7 @@ skip_type(char_u *start)
19451956
{
19461957
char_u *sp = p;
19471958

1948-
p = skip_type(p);
1959+
p = skip_type(p, TRUE);
19491960
if (p == sp)
19501961
return p; // syntax error
19511962
if (*p == ',')
@@ -1954,15 +1965,15 @@ skip_type(char_u *start)
19541965
if (*p == ')')
19551966
{
19561967
if (p[1] == ':')
1957-
p = skip_type(skipwhite(p + 2));
1968+
p = skip_type(skipwhite(p + 2), FALSE);
19581969
else
19591970
++p;
19601971
}
19611972
}
19621973
else
19631974
{
19641975
// handle func: return_type
1965-
p = skip_type(skipwhite(p + 1));
1976+
p = skip_type(skipwhite(p + 1), FALSE);
19661977
}
19671978
}
19681979

0 commit comments

Comments
 (0)