From caea2daece4cb5f435a61f77ce771496fc8c635a Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 24 May 2026 15:57:28 +0300 Subject: [PATCH] checker: allow `C.S{}` zero-init for C structs with reference fields (fix #27170) (#27228) --- vlib/v/checker/struct.v | 3 ++- vlib/v/tests/c_structs/cstruct.h | 11 +++++++++++ .../c_structs/cstruct_ref_zero_init_test.c.v | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/c_structs/cstruct_ref_zero_init_test.c.v diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index aaee12d23..6beb05e83 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -1495,7 +1495,8 @@ fn (mut c Checker) check_uninitialized_struct_fields_and_embeds(node ast.StructI } field_is_option := field.typ.has_flag(.option) if field.typ.is_ptr() && !field.typ.has_flag(.shared_f) && !field_is_option - && !node.has_update_expr && !c.pref.translated && !c.file.is_translated { + && !node.has_update_expr && !c.pref.translated && !c.file.is_translated + && type_sym.language != .c { // Skip this check during generic recheck (concrete instantiation), // because generic code like `T{}` or `Struct[V]{}` cannot provide // initializers for reference fields that only appear after type substitution. diff --git a/vlib/v/tests/c_structs/cstruct.h b/vlib/v/tests/c_structs/cstruct.h index 94156494f..6b7ba3532 100644 --- a/vlib/v/tests/c_structs/cstruct.h +++ b/vlib/v/tests/c_structs/cstruct.h @@ -33,3 +33,14 @@ typedef struct Bar { typedef struct TestAlias { int a; }; + +/// + +typedef struct MyRefStruct MyRefStruct; +struct MyRefStruct { + char* format; + char* name; + void** children; + void (*release)(struct MyRefStruct*); + void* private_data; +}; diff --git a/vlib/v/tests/c_structs/cstruct_ref_zero_init_test.c.v b/vlib/v/tests/c_structs/cstruct_ref_zero_init_test.c.v new file mode 100644 index 000000000..db04d7ebb --- /dev/null +++ b/vlib/v/tests/c_structs/cstruct_ref_zero_init_test.c.v @@ -0,0 +1,18 @@ +#include "@VMODROOT/cstruct.h" + +struct C.MyRefStruct { +mut: + format &char + name &char + children &voidptr + release fn (&C.MyRefStruct) + private_data voidptr +} + +fn test_c_struct_zero_init_with_ref_fields() { + s := C.MyRefStruct{} + assert s.format == unsafe { nil } + assert s.name == unsafe { nil } + assert s.children == unsafe { nil } + assert s.private_data == unsafe { nil } +} -- 2.39.5