diff --git a/vlib/v/checker/tests/struct_required_fn_field.out b/vlib/v/checker/tests/struct_required_fn_field.out new file mode 100644 index 0000000000..25d6ee8a42 --- /dev/null +++ b/vlib/v/checker/tests/struct_required_fn_field.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/struct_required_fn_field.vv:12:6: error: field `Abc.f3` must be initialized + 10 | f3: fn () {} + 11 | } + 12 | _ = Abc{ + | ~~~~ + 13 | f1: 123 + 14 | f2: 789 diff --git a/vlib/v/checker/tests/struct_required_fn_field.vv b/vlib/v/checker/tests/struct_required_fn_field.vv new file mode 100644 index 0000000000..e72cfe6be5 --- /dev/null +++ b/vlib/v/checker/tests/struct_required_fn_field.vv @@ -0,0 +1,16 @@ +struct Abc { + f1 int [required] + f2 int + f3 fn () [attr1; required; attr2] +} + +fn main() { + _ = Abc{ + f1: 123 + f3: fn () {} + } + _ = Abc{ + f1: 123 + f2: 789 + } +} diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 765f641b8f..7bd70320cd 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -212,7 +212,7 @@ pub fn (mut p Parser) parse_fn_type(name string) ast.Type { } mut return_type := ast.void_type mut return_type_pos := token.Position{} - if p.tok.line_nr == line_nr && p.tok.kind.is_start_of_type() { + if p.tok.line_nr == line_nr && p.tok.kind.is_start_of_type() && !p.is_attributes() { return_type_pos = p.tok.position() return_type = p.parse_type() if return_type.has_flag(.generic) { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 3cbcf536de..4f9320729c 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1460,6 +1460,28 @@ fn (mut p Parser) expr_list() ([]ast.Expr, []ast.Comment) { return exprs, comments } +fn (mut p Parser) is_attributes() bool { + if p.tok.kind != .lsbr { + return false + } + mut i := 0 + for { + tok := p.peek_token(i) + if tok.kind == .eof || tok.line_nr != p.tok.line_nr { + return false + } + if tok.kind == .rsbr { + break + } + i++ + } + peek_rsbr_tok := p.peek_token(i + 1) + if peek_rsbr_tok.line_nr == p.tok.line_nr && peek_rsbr_tok.kind != .rcbr { + return false + } + return true +} + // when is_top_stmt is true attrs are added to p.attrs fn (mut p Parser) attributes() { p.check(.lsbr) diff --git a/vlib/v/tests/struct_fields_storing_required_functions_test.v b/vlib/v/tests/struct_fields_storing_required_functions_test.v new file mode 100644 index 0000000000..cb081c2496 --- /dev/null +++ b/vlib/v/tests/struct_fields_storing_required_functions_test.v @@ -0,0 +1,17 @@ +struct Struct { + f1 fn () [required] + f2 fn () [attr1; required] +} + +fn func() { +} + +fn test_struct_fields_storing_required_functions() { + s := Struct{ + f1: func + f2: func + } + + assert s.f1 == func + assert s.f2 == func +}