From 79819c4fcbe0c476203d615f2cd03b11259ddf31 Mon Sep 17 00:00:00 2001 From: yuyi Date: Mon, 24 Apr 2023 17:03:29 +0800 Subject: [PATCH] parser: check generic fntype declaration without type name (#18033) --- .../checker/tests/generics_fn_called_fntype_arg_mismatch.vv | 4 ++-- vlib/v/parser/parse_type.v | 5 +++++ vlib/v/parser/tests/generic_fn_type_decl_err.out | 5 +++++ vlib/v/parser/tests/generic_fn_type_decl_err.vv | 4 ++++ 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 vlib/v/parser/tests/generic_fn_type_decl_err.out create mode 100644 vlib/v/parser/tests/generic_fn_type_decl_err.vv diff --git a/vlib/v/checker/tests/generics_fn_called_fntype_arg_mismatch.vv b/vlib/v/checker/tests/generics_fn_called_fntype_arg_mismatch.vv index 20412a680..e1712f593 100644 --- a/vlib/v/checker/tests/generics_fn_called_fntype_arg_mismatch.vv +++ b/vlib/v/checker/tests/generics_fn_called_fntype_arg_mismatch.vv @@ -1,9 +1,9 @@ -pub type FnArrayInit = fn (idx int) T +pub type FnArrayInit[T] = fn (idx int) T pub fn new_array[T](len int, initfn FnArrayInit[T]) []T { mut res := []T{len: len} for idx in 0 .. res.len { - res[idx] = initfn(idx) + res[idx] = initfn[T](idx) } return res } diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 2d744d938..19618b649 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -230,6 +230,7 @@ pub fn (mut p Parser) parse_multi_return_type() ast.Type { // given anon name based off signature when `name` is blank pub fn (mut p Parser) parse_fn_type(name string, generic_types []ast.Type) ast.Type { + fn_type_pos := p.peek_token(-2).pos() p.check(.key_fn) for attr in p.attrs { @@ -277,6 +278,10 @@ pub fn (mut p Parser) parse_fn_type(name string, generic_types []ast.Type) ast.T is_method: false attrs: p.attrs } + if has_generic && generic_types.len == 0 && name.len > 0 { + p.error_with_pos('`${name}` type is generic fntype, must specify the generic type names, e.g. ${name}[T]', + fn_type_pos) + } // MapFooFn typedefs are manually added in cheaders.v // because typedefs get generated after the map struct is generated has_decl := p.builtin_mod && name.starts_with('Map') && name.ends_with('Fn') diff --git a/vlib/v/parser/tests/generic_fn_type_decl_err.out b/vlib/v/parser/tests/generic_fn_type_decl_err.out new file mode 100644 index 000000000..e09675ac2 --- /dev/null +++ b/vlib/v/parser/tests/generic_fn_type_decl_err.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/generic_fn_type_decl_err.vv:1:6: error: `Fn` type is generic fntype, must specify the generic type names, e.g. Fn[T] + 1 | type Fn = fn (I) !(O, R) + | ~~ + 2 | + 3 | fn main() { diff --git a/vlib/v/parser/tests/generic_fn_type_decl_err.vv b/vlib/v/parser/tests/generic_fn_type_decl_err.vv new file mode 100644 index 000000000..f0cf74b0b --- /dev/null +++ b/vlib/v/parser/tests/generic_fn_type_decl_err.vv @@ -0,0 +1,4 @@ +type Fn = fn (I) !(O, R) + +fn main() { +} -- 2.39.5