From 234691b032365e84c4048a809ec5b0cdc4ef0d34 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 26 Feb 2026 08:38:29 +0300 Subject: [PATCH] parser: fix array init with parenthesized optional elem type (fixes #16515) --- vlib/v/parser/containers.v | 4 +-- vlib/v/parser/expr.v | 25 ++++++++++++++++++- ..._init_parenthesized_optional_elem_type.out | 0 ...y_init_parenthesized_optional_elem_type.vv | 17 +++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 vlib/v/parser/tests/array_init_parenthesized_optional_elem_type.out create mode 100644 vlib/v/parser/tests/array_init_parenthesized_optional_elem_type.vv diff --git a/vlib/v/parser/containers.v b/vlib/v/parser/containers.v index 218f2b4ad..28e1e4b73 100644 --- a/vlib/v/parser/containers.v +++ b/vlib/v/parser/containers.v @@ -29,7 +29,7 @@ fn (mut p Parser) array_init(is_option bool, alias_array_type ast.Type) ast.Arra line_nr := p.tok.line_nr p.next() // []string - if p.tok.kind in [.name, .amp, .lsbr, .question, .key_shared, .not] + if p.tok.kind in [.name, .amp, .lsbr, .lpar, .question, .key_shared, .not] && p.tok.line_nr == line_nr { elem_type_pos = p.tok.pos() elem_type = p.parse_type() @@ -77,7 +77,7 @@ fn (mut p Parser) array_init(is_option bool, alias_array_type ast.Type) ast.Arra last_pos = p.tok.pos() p.check(.rsbr) if exprs.len == 1 && p.tok.line_nr == line_nr - && (p.tok.kind in [.name, .amp, .question, .key_shared] + && (p.tok.kind in [.name, .amp, .lpar, .question, .key_shared] || (p.tok.kind == .lsbr && p.is_array_type())) { // [100]u8 elem_type = p.parse_type() diff --git a/vlib/v/parser/expr.v b/vlib/v/parser/expr.v index 86845959a..c5fc8288f 100644 --- a/vlib/v/parser/expr.v +++ b/vlib/v/parser/expr.v @@ -293,7 +293,30 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr { prev_n_tok = peek_n_tok peek_n_tok = p.peek_token(n) } - if peek_n_tok.kind == .lpar && sbr_level == 0 && peek_n_tok.line_nr == line_nr { + mut is_cast_expr := peek_n_tok.kind == .lpar && sbr_level == 0 + && peek_n_tok.line_nr == line_nr + // `[](?Type){}` (and `[N](?Type){}`) is an array init, not a cast. + if is_cast_expr && prev_n_tok.kind == .rsbr { + mut par_level := 0 + for i := n; true; i++ { + tk := p.peek_token(i) + if tk.kind == .eof { + break + } + if tk.kind == .lpar { + par_level++ + } else if tk.kind == .rpar { + par_level-- + if par_level == 0 { + if p.peek_token(i + 1).kind == .lcbr { + is_cast_expr = false + } + break + } + } + } + } + if is_cast_expr { pos := p.tok.pos() typ := p.parse_type() typname := p.table.sym(typ).name diff --git a/vlib/v/parser/tests/array_init_parenthesized_optional_elem_type.out b/vlib/v/parser/tests/array_init_parenthesized_optional_elem_type.out new file mode 100644 index 000000000..e69de29bb diff --git a/vlib/v/parser/tests/array_init_parenthesized_optional_elem_type.vv b/vlib/v/parser/tests/array_init_parenthesized_optional_elem_type.vv new file mode 100644 index 000000000..c9b785e2d --- /dev/null +++ b/vlib/v/parser/tests/array_init_parenthesized_optional_elem_type.vv @@ -0,0 +1,17 @@ +struct Struc {} + +type StrucOpt = ?Struc + +struct StrucContainer { + a [](?Struc) = [](?Struc){} + b []?Struc = []?Struc{} + c ?[]Struc +} + +fn main() { + a := [](?Struc){} + b := []?Struc{} + c := []StrucOpt{} + d := [](?Struc)(b) + println(a.len + b.len + c.len + d.len) +} -- 2.39.5