Skip to content

Allow C.S{} zero-init for C-imported structs containing reference fields #27170

@eptx

Description

@eptx

Environment

  • V version: V 0.5.1 99f141f74 (verified no relevant commits land between that and current master b6dfae560)
  • OS-agnostic

Reproducer

main.v:

module main

struct C.MyStruct {
mut:
    format       &char
    name         &char
    children     &voidptr
    release      fn (&C.MyStruct)
    private_data voidptr
}

fn main() {
    s := C.MyStruct{}   // ← fails
    _ := s
}

V 0.5.1 (and master b6dfae560) errors:

error: reference field `C.MyStruct.format` must be initialized
error: reference field `C.MyStruct.name` must be initialized
error: reference field `C.MyStruct.children` must be initialized

Why this matters

C-imported structs (struct C.X { … }) frequently match real C ABI shapes where reference-typed fields are expected to start as NULL and be filled in by the caller. The Arrow C-Data interface (ArrowSchema, ArrowArray) is the canonical example: every consumer in every ecosystem allocates the struct, zeroes it, then fills the fields. The C convention assumes {0} initialisation.

V's check is correct for V-native structs (a &T field nil-by-default is unsound). For C-imported structs the check is too strict: the user is opting into C ABI semantics and should be trusted, much as unsafe blocks already trust the user for raw pointer arithmetic.

Workaround used today

CX's vcx/arrow/arrow.v:393-410:

child_struct_size := int(sizeof(C.ArrowSchema))
cs_raw := unsafe { malloc(child_struct_size) }
unsafe { vmemset(cs_raw, 0, child_struct_size) }
mut cs := unsafe { &C.ArrowSchema(cs_raw) }
cs.format = c_string(col_formats[i])
... // fill each field

The memory layout is identical to what C.ArrowSchema{} would produce; V just won't let the type-system express it.

Proposed fixes

In order of disruption:

  1. Skip the check for struct C.… types. They're already in the "trust the C ABI" lane.
  2. Allow unsafe { C.S{} } as a sanctioned escape hatch.
  3. Allow C.S{ ...fields_set_to_unsafe_nil } — verbose but explicit.

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

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions