Skip to content

cgen: comptime $for f in T.fields over a generic struct with ?[]T / ?[N]T fields generates invalid C #26903

@enghitalo

Description

@enghitalo

Describe the bug

A generic function that walks the fields of a generic struct containing ?T, ?[]T and ?[N]T fields (where T is the generic parameter) generates invalid C: the codegen emits _option_string and _option_Array_string initializers as if they were raw byte arrays, producing both cannot convert 'struct _option_string' to 'unsigned char *' and incompatible types when initializing 'u8 *' using '_option_Array_string' errors.

Reproduction Steps

pub struct Filter[T] {
pub mut:
	selector  ?T
	selector2 ?[]T
	selector3 ?[1]T
}

fn process_field[T](val T) {
	_ = val
}

fn process_struct[T](val T) {
	$for f in T.fields {
		process_field(val.$(f.name))
	}
}

fn main() {
	t := Filter[string]{
		selector:  'aa'
		selector2: ['a', 'b']
		selector3: ['z']!
	}
	process_struct(t)
}

Expected Behavior

Compiles. The comptime walker visits each field; the per-field generic gets instantiated for ?string, ?[]string, ?[1]string respectively.

Current Behavior

================== C compilation error ==============
error: cannot convert 'struct _option_string' to 'unsigned char *'
        builtin___option_ok(&(Array_fixed_string_1[]) {val }, (_option*)(&_t1), sizeof(Array_fixed_string_1));
                                                       ^~~
error: incompatible types when initializing type 'u8 *' using type '_option_Array_string'
        builtin___option_ok(&(Array_fixed_string_1[]) {val }, (_option*)(&_t1), sizeof(Array_fixed_string_1));
                                                       ^~~
=====================================================
builder error: C error found while compiling generated C code.

Possible Solution

When the comptime $for f in T.fields walker over a generic struct sees field.typ of ?T, ?[]T or ?[N]T, the option's payload-init codegen drops the array layer somewhere on the way from field.typ resolution to the _option_X C struct emission. The result is that _option_string gets initialized through the path that expects an [N]T payload, leading to Array_fixed_string_1[] being assigned a struct value.

The fix is in the comptime/cgen layer that monomorphizes generic structs with option-of-array fields: produce a payload struct whose layout matches the option's payload type, not the surrounding fixed-array shape.

V version

V 0.5.1 (40b3711)

Environment details (OS name and version, etc.)

|V full version      |V 0.5.1 1b3385cc34ff783e793d1a26a8ec5be587c80fe0.40b3711
|:-------------------|:-------------------
|OS                  |linux, Ubuntu 24.04 LTS
|Processor           |16 cpus, 64bit, little endian, AMD Ryzen 7 5800H with Radeon Graphics
|Memory              |10.02GB/30.7GB
|                    |
|V executable        |/home/hitalo/Documents/v/v
|V last modified time|2026-04-18 09:18:00
|                    |
|V home dir          |OK, value: /home/hitalo/Documents/v
|VMODULES            |OK, value: /home/hitalo/.vmodules
|VTMP                |OK, value: /tmp/v_1000
|Current working dir |OK, value: /home/hitalo/Documents/v
|                    |
|Git version         |git version 2.43.0
|V git status        |0.5.1-1006-g40b3711b-dirty
|.git/config present |true
|                    |
|cc version          |cc (GCC) 14.2.0
|gcc version         |gcc (GCC) 14.2.0
|clang version       |Ubuntu clang version 18.1.3 (1)
|tcc version         |tcc version 0.9.28rc 2025-02-13 HEAD@f8bd136d (x86_64 Linux)
|tcc git status      |thirdparty-linux-amd64 696c1d84
|emcc version        |emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.6 ()
|glibc version       |ldd (Ubuntu GLIBC 2.39-0ubuntu8.3) 2.39

Note

You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugThis tag is applied to issues which reports bugs.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions