From 440080a2959590eb4b46c7aa9f0fc86d9d02bcce Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 26 Feb 2026 10:03:20 +0300 Subject: [PATCH] parser: support `.to_fixed_size()` method on array literals (fixes #22849) --- doc/docs.md | 3 ++- vlib/v/ast/ast.v | 25 ++++++++++--------- vlib/v/fmt/fmt.v | 6 ++++- vlib/v/parser/parser.v | 16 ++++++++++++ .../fixed_array_to_fixed_size_method_test.v | 14 +++++++++++ 5 files changed, 50 insertions(+), 14 deletions(-) create mode 100644 vlib/v/tests/builtin_arrays/fixed_array_to_fixed_size_method_test.v diff --git a/doc/docs.md b/doc/docs.md index 890ff741d..52cd8916c 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -1409,7 +1409,8 @@ fnums[2] = 100 println(fnums) // => [1, 10, 100] println(typeof(fnums).name) // => [3]int -fnums2 := [1, 10, 100]! // short init syntax that does the same (the syntax will probably change) +fnums2 := [1, 10, 100].to_fixed_size() // explicit conversion syntax +fnums3 := [1, 10, 100]! // short init syntax, equivalent to `.to_fixed_size()` anums := fnums[..] // same as `anums := fnums[0..fnums.len]` println(anums) // => [1, 10, 100] diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index bcdc55407..a0271c3bd 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -1693,18 +1693,19 @@ pub: @[minify] pub struct ArrayInit { pub: - pos token.Pos // `[]` in []Type{} position - elem_type_pos token.Pos // `Type` in []Type{} position - ecmnts [][]Comment // optional iembed comments after each expr - pre_cmnts []Comment - is_fixed bool - is_option bool // true if it was declared as ?[2]Type or ?[]Type - has_val bool // fixed size literal `[expr, expr]!` - mod string - has_len bool - has_cap bool - has_init bool - has_index bool // true if temp variable index is used + pos token.Pos // `[]` in []Type{} position + elem_type_pos token.Pos // `Type` in []Type{} position + ecmnts [][]Comment // optional iembed comments after each expr + pre_cmnts []Comment + is_fixed bool + is_option bool // true if it was declared as ?[2]Type or ?[]Type + has_val bool // fixed size literal `[expr, expr]!` + from_to_fixed_size bool // lowered from `[expr, expr].to_fixed_size()` + mod string + has_len bool + has_cap bool + has_init bool + has_index bool // true if temp variable index is used pub mut: exprs []Expr // `[expr, expr]` or `[expr]Type{}` for fixed array len_expr Expr // len: expr diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 9364f493d..000f6a273 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -2008,7 +2008,11 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) { // `[100]u8` if node.is_fixed { if node.has_val { - f.write('!') + if node.from_to_fixed_size { + f.write('.to_fixed_size()') + } else { + f.write('!') + } return } f.write(f.type_to_str_using_aliases(node.elem_type, f.mod2alias)) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 8ea0f38c2..640a97e20 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -2255,6 +2255,22 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr { or_block := p.gen_or_block() end_pos := p.prev_tok.pos() pos := name_pos.extend(end_pos) + if field_name == 'to_fixed_size' && left is ast.ArrayInit && args.len == 0 + && or_block.kind == .absent { + left_array := left as ast.ArrayInit + if left_array.is_fixed { + return left_array + } + if left_array.exprs.len > 0 { + return ast.ArrayInit{ + ...left_array + is_fixed: true + has_val: true + from_to_fixed_size: true + pos: left_array.pos.extend(end_pos) + } + } + } comments := p.eat_comments(same_line: true) mut left_node := unsafe { left } if mut left_node is ast.CallExpr { diff --git a/vlib/v/tests/builtin_arrays/fixed_array_to_fixed_size_method_test.v b/vlib/v/tests/builtin_arrays/fixed_array_to_fixed_size_method_test.v new file mode 100644 index 000000000..3e2fa98f7 --- /dev/null +++ b/vlib/v/tests/builtin_arrays/fixed_array_to_fixed_size_method_test.v @@ -0,0 +1,14 @@ +fn make_fixed() ![3]int { + return [1, 10, 110].to_fixed_size() +} + +fn test_array_literal_to_fixed_size_method() { + fnums := [1, 10, 110].to_fixed_size() + assert fnums == [1, 10, 110]! + assert typeof(fnums).name == '[3]int' +} + +fn test_array_literal_to_fixed_size_method_with_result_propagation() ! { + fnums := make_fixed()! + assert fnums == [1, 10, 110]! +} -- 2.39.5