From 4c6a6f361f0869216c533d1d5f2e7063014ed10e Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 25 Mar 2026 16:42:17 +0300 Subject: [PATCH] cgen: fix initializer element is not a compile-time constant (fixes #25684) --- vlib/v/gen/c/assign.v | 37 +++++++++++++++++++++++++++++++++ vlib/v/tests/static_vars_test.v | 19 +++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index d734552fd..fa2a106f9 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -278,6 +278,39 @@ fn (mut g Gen) expr_with_opt(expr ast.Expr, expr_typ ast.Type, ret_typ ast.Type) return '' } +fn (g &Gen) static_init_guard_name(pos token.Pos) string { + return '_vstatic_init_${pos.pos}' +} + +fn (mut g Gen) gen_static_decl_runtime_init(node ast.AssignStmt, left ast.Expr, left_type ast.Type, right ast.Expr, right_type ast.Type) bool { + if node.left.len != 1 || node.right.len != 1 || g.inside_ternary != 0 { + return false + } + if left !is ast.Ident { + return false + } + guard_name := g.static_init_guard_name(left.pos()) + g.writeln(';') + g.writeln('static bool ${guard_name};') + g.writeln('if (!${guard_name}) {') + g.indent++ + g.writeln('${guard_name} = true;') + old_is_assign_lhs := g.is_assign_lhs + g.is_assign_lhs = false + g.assign_stmt(ast.AssignStmt{ + op: .assign + pos: node.pos + left: [left] + right: [right] + left_types: [left_type] + right_types: [right_type] + }) + g.is_assign_lhs = old_is_assign_lhs + g.indent-- + g.writeln('}') + return true +} + fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { mut node := unsafe { node_ } if node.is_static { @@ -1487,6 +1520,10 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { g.out.write_string(util.tabs(g.indent)) g.expr(left) } + if is_decl && node.is_static + && g.gen_static_decl_runtime_init(node, left, var_type, val, val_type) { + continue + } g.is_assign_lhs = false if left is ast.IndexExpr && g.cur_indexexpr.len > 0 { cur_indexexpr = g.cur_indexexpr.index(left.pos().pos) diff --git a/vlib/v/tests/static_vars_test.v b/vlib/v/tests/static_vars_test.v index de286afa6..179705b45 100644 --- a/vlib/v/tests/static_vars_test.v +++ b/vlib/v/tests/static_vars_test.v @@ -27,3 +27,22 @@ fn test_static_vars_in_unsafe_blocks() { assert f() == 2 dump(f()) // 3 } + +@[unsafe] +fn next_fib() int { + mut static fibs := []int{} + if fibs.len == 0 { + fibs << 1 + fibs << 1 + } else { + fibs << fibs[fibs.len - 1] + fibs[fibs.len - 2] + } + return fibs[fibs.len - 1] +} + +fn test_static_vars_with_array_initializers() { + assert unsafe { next_fib() } == 1 + assert unsafe { next_fib() } == 2 + assert unsafe { next_fib() } == 3 + assert unsafe { next_fib() } == 5 +} -- 2.39.5