Skip to content

cgen: fix "initializer element is not constant" for const fixed arrays with struct const elements#27852

Open
CG-SS wants to merge 1 commit into
vlang:masterfrom
CG-SS:master
Open

cgen: fix "initializer element is not constant" for const fixed arrays with struct const elements#27852
CG-SS wants to merge 1 commit into
vlang:masterfrom
CG-SS:master

Conversation

@CG-SS

@CG-SS CG-SS commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Fixes C compilation of fixed-array constants whose elements reference other
struct constants:

struct Info {
	code i16
	name string
}

const first = Info{1, 'first'}
const second = Info{2, 'second'}

const all = [first, second]!

Before this change, cgen emits a static C initializer for all:

static Array_fixed_main__Info_2 _const_main__all = {_const_main__first, _const_main__second}; // fixed array const

which fails to compile with gcc (and tcc):

error: initializer element is not constant

because struct consts like _const_main__first are runtime-initialized C
globals, not C constant expressions.

Why it happens

check_expr_is_const in vlib/v/gen/c/cgen.v decides whether a const
fixed-array initializer can be emitted as a static C initializer. Its
ast.Ident arm classifies any ident naming a V const as C-constant,
excluding only consts that are themselves fixed arrays:

return expr.kind == .function || g.table.final_sym(expr.obj.typ).kind != .array_fixed

The != .array_fixed exclusion patches one symptom of the underlying
misclassification. Struct consts (and string consts) hit exactly the same
hole: they are also runtime-initialized globals and are equally invalid in
static initializers.

The fix

Replace the type-based special case with the correct general predicate that
the AST already provides:

return expr.obj.is_simple_define_const()

An ident naming a V const is a valid C constant expression only when that
const is emitted as a simple #define'd literal (char/float/int literal
consts). Everything else routes to the existing runtime-init fallback
(const_decl_init_later_msvc_string_fixed_array), which already handles
ident elements via element-wise assignment in _vinit with dependency-
ordered initialization (dep_names), so no other changes are needed. The
emitted C for the example becomes:

static Array_fixed_main__Info_2 _const_main__all; // inited later
// in _vinit, after _const_main__first/_const_main__second:
_const_main__all[0] = _const_main__first;
_const_main__all[1] = _const_main__second;

This also closes the sibling latent hole where a struct literal element
containing a string-const ident field would pass the ast.StructInit
check and hit the same C error.

Behavior is preserved for the cases that work today: const arr = [a, b]!
with int/float literal consts still compiles to a static initializer, since
those consts are #define'd literals (covered by the added test).

Test

Adds vlib/v/tests/consts/const_fixed_array_of_struct_const_refs_test.v
covering:

  • a fixed-array const of struct-const references (fails to C-compile before
    this PR, passes after),
  • mixing const references and struct literals in one fixed array,
  • int-literal const references staying statically initialized.

Validation done

  • The new test fails on the unpatched compiler and passes on the patched
    one, with both tcc and gcc (no cc fallback needed).
  • v test vlib/v/tests/consts/ passes (the only failure in my environment
    is const_resolution_test.v, which needs X11 headers for sokol.sapp
    and fails identically on the unpatched compiler).

@GGRei

GGRei commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: db90b57298

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants