From 4c22007562897229865c7e00d564cace0b34b348 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 14 Apr 2026 04:12:45 +0300 Subject: [PATCH] all: fix more tests --- vlib/fasthttp/fasthttp.v | 2 +- vlib/v/checker/checker.v | 5 ++- .../{ => drawlib}/drawlib.v | 0 .../enum_from_string_in_different_mods.out | 14 +++---- .../src/{ => mod}/mod.v | 0 .../modules/implement_private_interface.out | 2 +- .../{ => baz}/baz.v | 0 .../{ => underscore}/underscore.v | 0 .../tests/modules/module_struct_noinit.out | 8 ++-- .../module_struct_noinit/src/{ => mod}/mod.v | 0 .../overload_return_type/{ => point}/point.v | 0 .../params_private_struct_visibility.out | 8 ++-- .../{ => mod}/mod.v | 0 .../checker/tests/modules/private_symbol.out | 6 +-- .../private_symbol/{ => priv_sym}/priv_sym.v | 0 .../pub_fn_private_c_struct_return.out | 2 +- .../{ => wrapper}/wrapper.c.v | 0 vlib/v/gen/c/auto_str_methods.v | 34 +++++++++++++++- vlib/v/gen/c/cgen.v | 8 ++++ .../c/testdata/sumtype_pass_by_reference.out | 40 +++++++++++++++---- .../path4/hunam6/voak/foo/foo.v | 1 - vlib/v2/gen/cleanc/consts_and_globals.v | 14 ++++++- vlib/veb/context.v | 8 ++-- 23 files changed, 113 insertions(+), 39 deletions(-) rename vlib/v/checker/tests/modules/embedded_private_method_visibility/{ => drawlib}/drawlib.v (100%) rename vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/{ => mod}/mod.v (100%) rename vlib/v/checker/tests/modules/implement_private_interface/{ => baz}/baz.v (100%) rename vlib/v/checker/tests/modules/module_alias_started_with_underscore/{ => underscore}/underscore.v (100%) rename vlib/v/checker/tests/modules/module_struct_noinit/src/{ => mod}/mod.v (100%) rename vlib/v/checker/tests/modules/overload_return_type/{ => point}/point.v (100%) rename vlib/v/checker/tests/modules/params_private_struct_visibility/{ => mod}/mod.v (100%) rename vlib/v/checker/tests/modules/private_symbol/{ => priv_sym}/priv_sym.v (100%) rename vlib/v/checker/tests/modules/pub_fn_private_c_struct_return/{ => wrapper}/wrapper.c.v (100%) delete mode 100644 vlib/v/tests/multiple_paths_in_vmodules/path4/hunam6/voak/foo/foo.v diff --git a/vlib/fasthttp/fasthttp.v b/vlib/fasthttp/fasthttp.v index d5a720daa..67e206d5f 100644 --- a/vlib/fasthttp/fasthttp.v +++ b/vlib/fasthttp/fasthttp.v @@ -7,10 +7,10 @@ import runtime import net import time -#include #include $if !windows { + #include #include #include #include diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 605346529..b31973099 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2395,7 +2395,8 @@ fn (mut c Checker) check_or_last_stmt(mut stmt ast.Stmt, ret_type ast.Type, defa if last_stmt_typ.has_flag(.option) || last_stmt_typ == ast.none_type { if stmt.expr in [ast.Ident, ast.SelectorExpr, ast.CallExpr, ast.None, ast.CastExpr] && !(last_stmt_typ == ast.none_type && allow_none_as_option_value - && default_or_type.has_flag(.option)) { + && default_or_type.has_flag(.option)) && !(last_stmt_typ == ast.none_type + && c.inside_return && ret_type.has_flag(.option)) { expected_type_name := c.table.type_to_str(default_or_type) got_type_name := c.table.type_to_str(last_stmt_typ) c.error('`or` block must provide a value of type `${expected_type_name}`, not `${got_type_name}`', @@ -6113,7 +6114,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type { } c_name := node.name.all_after('C.') if !c.pref.translated && !c.file.is_translated && c_name.len > 0 && c_name[0] >= `a` - && c_name[0] <= `z` { + && c_name[0] <= `z` && c_name !in c.table.export_names.values() { c.error('undefined C identifier: `${node.name}`', node.pos) return ast.int_type } diff --git a/vlib/v/checker/tests/modules/embedded_private_method_visibility/drawlib.v b/vlib/v/checker/tests/modules/embedded_private_method_visibility/drawlib/drawlib.v similarity index 100% rename from vlib/v/checker/tests/modules/embedded_private_method_visibility/drawlib.v rename to vlib/v/checker/tests/modules/embedded_private_method_visibility/drawlib/drawlib.v diff --git a/vlib/v/checker/tests/modules/enum_from_string_in_different_mods.out b/vlib/v/checker/tests/modules/enum_from_string_in_different_mods.out index 9a5cc8986..04a2780ad 100644 --- a/vlib/v/checker/tests/modules/enum_from_string_in_different_mods.out +++ b/vlib/v/checker/tests/modules/enum_from_string_in_different_mods.out @@ -1,25 +1,25 @@ -vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:3:14: error: module `mod` type `MyEnum` is private +vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:3:14: error: module `enum_from_string_in_different_mods.mod` type `MyEnum` is private 1 | module main - 2 | + 2 | 3 | import mod { MyEnum, MyStruct } | ~~~~~~ - 4 | + 4 | 5 | fn main() { -vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:6:7: error: module `mod` type `mod.MyEnum` is private - 4 | +vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:6:7: error: module `enum_from_string_in_different_mods.mod` type `enum_from_string_in_different_mods.mod.MyEnum` is private + 4 | 5 | fn main() { 6 | _ := MyEnum.from_string('item1') | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 | _ := MyStruct.from_string('item1') 8 | } vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:6:4: error: assignment mismatch: 1 variable but `MyEnum.from_string()` returns 0 values - 4 | + 4 | 5 | fn main() { 6 | _ := MyEnum.from_string('item1') | ~~ 7 | _ := MyStruct.from_string('item1') 8 | } -vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:7:7: error: expected enum, but `mod.MyStruct` is struct +vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:7:7: error: expected enum, but `enum_from_string_in_different_mods.mod.MyStruct` is struct 5 | fn main() { 6 | _ := MyEnum.from_string('item1') 7 | _ := MyStruct.from_string('item1') diff --git a/vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/mod.v b/vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/mod/mod.v similarity index 100% rename from vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/mod.v rename to vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/mod/mod.v diff --git a/vlib/v/checker/tests/modules/implement_private_interface.out b/vlib/v/checker/tests/modules/implement_private_interface.out index f05842ac0..45ba2ea74 100644 --- a/vlib/v/checker/tests/modules/implement_private_interface.out +++ b/vlib/v/checker/tests/modules/implement_private_interface.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/modules/implement_private_interface/main.v:7:16: error: `Bar` cannot implement private interface `baz.Foo` of other module +vlib/v/checker/tests/modules/implement_private_interface/main.v:7:16: error: `Bar` cannot implement private interface `implement_private_interface.baz.Foo` of other module 5 | fn main() { 6 | b := Bar{10} 7 | baz.print_foo(b) // prints 10 diff --git a/vlib/v/checker/tests/modules/implement_private_interface/baz.v b/vlib/v/checker/tests/modules/implement_private_interface/baz/baz.v similarity index 100% rename from vlib/v/checker/tests/modules/implement_private_interface/baz.v rename to vlib/v/checker/tests/modules/implement_private_interface/baz/baz.v diff --git a/vlib/v/checker/tests/modules/module_alias_started_with_underscore/underscore.v b/vlib/v/checker/tests/modules/module_alias_started_with_underscore/underscore/underscore.v similarity index 100% rename from vlib/v/checker/tests/modules/module_alias_started_with_underscore/underscore.v rename to vlib/v/checker/tests/modules/module_alias_started_with_underscore/underscore/underscore.v diff --git a/vlib/v/checker/tests/modules/module_struct_noinit.out b/vlib/v/checker/tests/modules/module_struct_noinit.out index 2c5a8f15b..a5b80d2ab 100644 --- a/vlib/v/checker/tests/modules/module_struct_noinit.out +++ b/vlib/v/checker/tests/modules/module_struct_noinit.out @@ -1,11 +1,11 @@ -vlib/v/checker/tests/modules/module_struct_noinit/src/main.v:12:9: error: struct `mod.Foo` is declared with a `@[noinit]` attribute, so it cannot be initialized with `mod.Foo{}` - 10 | +vlib/v/checker/tests/modules/module_struct_noinit/src/main.v:12:9: error: struct `module_struct_noinit.src.mod.Foo` is declared with a `@[noinit]` attribute, so it cannot be initialized with `module_struct_noinit.src.mod.Foo{}` + 10 | 11 | fn default_value[T]() T { 12 | return T{} | ~~~ 13 | } -vlib/v/checker/tests/modules/module_struct_noinit/src/main.v:12:9: error: struct `mod.Foo2[int]` is declared with a `@[noinit]` attribute, so it cannot be initialized with `mod.Foo2[int]{}` - 10 | +vlib/v/checker/tests/modules/module_struct_noinit/src/main.v:12:9: error: struct `module_struct_noinit.src.mod.Foo2[int]` is declared with a `@[noinit]` attribute, so it cannot be initialized with `module_struct_noinit.src.mod.Foo2[int]{}` + 10 | 11 | fn default_value[T]() T { 12 | return T{} | ~~~ diff --git a/vlib/v/checker/tests/modules/module_struct_noinit/src/mod.v b/vlib/v/checker/tests/modules/module_struct_noinit/src/mod/mod.v similarity index 100% rename from vlib/v/checker/tests/modules/module_struct_noinit/src/mod.v rename to vlib/v/checker/tests/modules/module_struct_noinit/src/mod/mod.v diff --git a/vlib/v/checker/tests/modules/overload_return_type/point.v b/vlib/v/checker/tests/modules/overload_return_type/point/point.v similarity index 100% rename from vlib/v/checker/tests/modules/overload_return_type/point.v rename to vlib/v/checker/tests/modules/overload_return_type/point/point.v diff --git a/vlib/v/checker/tests/modules/params_private_struct_visibility.out b/vlib/v/checker/tests/modules/params_private_struct_visibility.out index 1cce960d1..eccfbb4dc 100644 --- a/vlib/v/checker/tests/modules/params_private_struct_visibility.out +++ b/vlib/v/checker/tests/modules/params_private_struct_visibility.out @@ -1,11 +1,11 @@ -vlib/v/checker/tests/modules/params_private_struct_visibility/main.v:6:6: error: struct `mod.Param` was declared as private to module `mod`, so it can not be used inside module `main` - 4 | +vlib/v/checker/tests/modules/params_private_struct_visibility/main.v:6:6: error: struct `params_private_struct_visibility.mod.Param` was declared as private to module `params_private_struct_visibility.mod`, so it can not be used inside module `main` + 4 | 5 | fn main() { 6 | mod.foo() | ~~~~~ 7 | } -vlib/v/checker/tests/modules/params_private_struct_visibility/main.v:6:6: error: type `mod.Param` is private - 4 | +vlib/v/checker/tests/modules/params_private_struct_visibility/main.v:6:6: error: type `params_private_struct_visibility.mod.Param` is private + 4 | 5 | fn main() { 6 | mod.foo() | ~~~~~ diff --git a/vlib/v/checker/tests/modules/params_private_struct_visibility/mod.v b/vlib/v/checker/tests/modules/params_private_struct_visibility/mod/mod.v similarity index 100% rename from vlib/v/checker/tests/modules/params_private_struct_visibility/mod.v rename to vlib/v/checker/tests/modules/params_private_struct_visibility/mod/mod.v diff --git a/vlib/v/checker/tests/modules/private_symbol.out b/vlib/v/checker/tests/modules/private_symbol.out index 9fa9da022..38f87c35a 100644 --- a/vlib/v/checker/tests/modules/private_symbol.out +++ b/vlib/v/checker/tests/modules/private_symbol.out @@ -1,11 +1,11 @@ -vlib/v/checker/tests/modules/private_symbol/main.v:10:11: error: function `priv_sym.priv` is private +vlib/v/checker/tests/modules/private_symbol/main.v:10:11: error: function `private_symbol.priv_sym.priv` is private 8 | 9 | fn main() { 10 | priv_sym.priv() | ~~~~~~ 11 | a := priv_sym.Foo(0) 12 | dump(a) -vlib/v/checker/tests/modules/private_symbol/main.v:11:16: error: unknown type `priv_sym.Foo`. +vlib/v/checker/tests/modules/private_symbol/main.v:11:16: error: unknown type `private_symbol.priv_sym.Foo`. Did you mean `priv_sym.PubFoo`? 9 | fn main() { 10 | priv_sym.priv() @@ -13,7 +13,7 @@ Did you mean `priv_sym.PubFoo`? | ~~~~~~ 12 | dump(a) 13 | b := priv_sym.BarFn(t) -vlib/v/checker/tests/modules/private_symbol/main.v:13:16: error: unknown type `priv_sym.BarFn`. +vlib/v/checker/tests/modules/private_symbol/main.v:13:16: error: unknown type `private_symbol.priv_sym.BarFn`. Did you mean `priv_sym.PubFoo`? 11 | a := priv_sym.Foo(0) 12 | dump(a) diff --git a/vlib/v/checker/tests/modules/private_symbol/priv_sym.v b/vlib/v/checker/tests/modules/private_symbol/priv_sym/priv_sym.v similarity index 100% rename from vlib/v/checker/tests/modules/private_symbol/priv_sym.v rename to vlib/v/checker/tests/modules/private_symbol/priv_sym/priv_sym.v diff --git a/vlib/v/checker/tests/modules/pub_fn_private_c_struct_return.out b/vlib/v/checker/tests/modules/pub_fn_private_c_struct_return.out index 55718ccc8..693b27355 100644 --- a/vlib/v/checker/tests/modules/pub_fn_private_c_struct_return.out +++ b/vlib/v/checker/tests/modules/pub_fn_private_c_struct_return.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/modules/pub_fn_private_c_struct_return/main.v:6:21: error: struct `C.Hidden` was declared as private to module `wrapper`, so it can not be used inside module `main` +vlib/v/checker/tests/modules/pub_fn_private_c_struct_return/main.v:6:21: error: struct `C.Hidden` was declared as private to module `pub_fn_private_c_struct_return.wrapper`, so it can not be used inside module `main` 4 | 5 | fn main() { 6 | _ = wrapper.leak().value diff --git a/vlib/v/checker/tests/modules/pub_fn_private_c_struct_return/wrapper.c.v b/vlib/v/checker/tests/modules/pub_fn_private_c_struct_return/wrapper/wrapper.c.v similarity index 100% rename from vlib/v/checker/tests/modules/pub_fn_private_c_struct_return/wrapper.c.v rename to vlib/v/checker/tests/modules/pub_fn_private_c_struct_return/wrapper/wrapper.c.v diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index f1f4148a5..b53e32d03 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -1028,6 +1028,11 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, lang ast.Language, styp strin fn_builder.writeln('}') return } + if !allow_circular { + fn_builder.writeln('\tif (indent_count > 20) {') + fn_builder.writeln('\t\treturn _S("");') + fn_builder.writeln('\t}') + } fn_builder.writeln('\tstring indents = builtin__string_repeat(_S(" "), indent_count);') mut fn_body_surrounder := util.new_surrounder(info.fields.len) @@ -1176,8 +1181,10 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, lang ast.Language, styp strin if field.typ in ast.charptr_types { fn_body.write_string('builtin__tos4((byteptr)${func})') } else { - if field.typ.is_ptr() && !field.typ.has_flag(.option) - && sym.kind in [.struct, .interface] { + is_ptr_field := field.typ.is_ptr() && sym.kind in [.struct, .interface] + is_opt_ptr_field := field.typ.has_flag(.option) && field.typ.is_ptr() + && sym.kind in [.struct, .interface] + if is_ptr_field && !field.typ.has_flag(.option) { // Use address-based circular reference detection for pointer fields. // This correctly detects actual circular references (same instance) // without false positives from different instances of the same type. @@ -1196,6 +1203,29 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, lang ast.Language, styp strin } fn_body_surrounder.add(before, after) fn_body.write_string(tmpvar) + } else if is_opt_ptr_field { + // Use address-based circular reference detection for option pointer fields (?&Struct). + // Extract the pointer from the option struct's data field. + tmpvar := g.new_tmp_var() + mut before := '\tstring ${tmpvar};\n' + before += '\tif (${it_field_name}.state != 0) {\n' + before += '\t\t${tmpvar} = ${funcprefix}_S("Option(none)");\n' + before += '\t} else {\n' + before += '\t\tvoidptr ${tmpvar}_addr = *(voidptr*)${it_field_name}.data;\n' + before += '\t\tif (builtin__isnil(${tmpvar}_addr) || builtin__autostr_addr_in_stack(${tmpvar}_addr)) {\n' + before += '\t\t\t${tmpvar} = ${funcprefix}builtin__isnil(${tmpvar}_addr) ? _S("Option(nil)") : _S("");\n' + before += '\t\t} else {\n' + before += '\t\t\tbuiltin__autostr_addr_push(${tmpvar}_addr);\n' + before += '\t\t\t${tmpvar} = ${funcprefix}${func};\n' + before += '\t\t\tbuiltin__autostr_addr_pop();\n' + before += '\t\t}\n' + before += '\t}' + mut after := '' + if caller_should_free { + after = '\tbuiltin__string_free(&${tmpvar});' + } + fn_body_surrounder.add(before, after) + fn_body.write_string(tmpvar) } else if caller_should_free { tmpvar := g.new_tmp_var() fn_body_surrounder.add('\tstring ${tmpvar} = ${funcprefix}${func};', diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 286bef88e..c58612075 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -8987,6 +8987,10 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) { if sym.name.starts_with('C.') { if sym.info is ast.Struct && sym.info.is_anon { // For `C___VAnonStruct`, we need to create a new struct to make auto_str work. + } else if sym.info is ast.Struct && g.should_emit_private_c_struct(sym, sym.info) { + // Private C tags like `C._gpgme_key` are often only forward-declared in headers. + // When they are defined in a plain `.v` file, cgen needs to emit the backing + // struct body instead of assuming the C headers will provide it. } else { continue } @@ -8998,6 +9002,10 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) { g.typedefs.writeln('typedef struct none none;') } mut name := sym.scoped_cname() + if sym.name.starts_with('C.') && sym.info is ast.Struct + && g.should_emit_private_c_struct(sym, sym.info) { + name = sym.name.all_after('C.') + } if g.pref.skip_unused && g.table.used_features.used_maps == 0 { if name in ['map', 'mapnode', 'SortedMap', 'MapMode', 'DenseArray'] { continue diff --git a/vlib/v/gen/c/testdata/sumtype_pass_by_reference.out b/vlib/v/gen/c/testdata/sumtype_pass_by_reference.out index 5c540a757..cf5c166e2 100644 --- a/vlib/v/gen/c/testdata/sumtype_pass_by_reference.out +++ b/vlib/v/gen/c/testdata/sumtype_pass_by_reference.out @@ -1,20 +1,44 @@ &Expr(ParExpr{ expr: Expr(InfixExpr{ - left: Expr() - right: Expr() + left: Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value + }) + right: Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value + }) }) }) &Expr(ParExpr{ expr: Expr(InfixExpr{ - left: Expr() - right: Expr() + left: Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value + }) + right: Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value + }) }) }) &Expr(InfixExpr{ - left: Expr() - right: Expr() + left: Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value + }) + right: Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value + }) }) &Expr(InfixExpr{ - left: Expr() - right: Expr() + left: Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value + }) + right: Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value + }) }) diff --git a/vlib/v/tests/multiple_paths_in_vmodules/path4/hunam6/voak/foo/foo.v b/vlib/v/tests/multiple_paths_in_vmodules/path4/hunam6/voak/foo/foo.v deleted file mode 100644 index 49525808b..000000000 --- a/vlib/v/tests/multiple_paths_in_vmodules/path4/hunam6/voak/foo/foo.v +++ /dev/null @@ -1 +0,0 @@ -module foo diff --git a/vlib/v2/gen/cleanc/consts_and_globals.v b/vlib/v2/gen/cleanc/consts_and_globals.v index f31759dbb..2ada81d62 100644 --- a/vlib/v2/gen/cleanc/consts_and_globals.v +++ b/vlib/v2/gen/cleanc/consts_and_globals.v @@ -402,11 +402,16 @@ fn (mut g Gen) gen_const_decl_extern(node ast.ConstDecl) { fn (mut g Gen) gen_global_decl(node ast.GlobalDecl) { for field in node.fields { - name := if g.cur_module != '' && g.cur_module != 'main' && g.cur_module != 'builtin' { + raw_name := if g.cur_module != '' && g.cur_module != 'main' && g.cur_module != 'builtin' { '${g.cur_module}__${field.name}' } else { field.name } + name := if raw_name.starts_with('C.') { raw_name.all_after('C.') } else { raw_name } + // Skip C globals that are already provided by C headers or cheaders. + if field.name.starts_with('C.') { + continue + } key := 'global_${name}' if key in g.emitted_types { continue @@ -461,11 +466,16 @@ fn (mut g Gen) gen_global_decl(node ast.GlobalDecl) { fn (mut g Gen) gen_global_decl_extern(node ast.GlobalDecl) { for field in node.fields { - name := if g.cur_module != '' && g.cur_module != 'main' && g.cur_module != 'builtin' { + raw_name := if g.cur_module != '' && g.cur_module != 'main' && g.cur_module != 'builtin' { '${g.cur_module}__${field.name}' } else { field.name } + name := if raw_name.starts_with('C.') { raw_name.all_after('C.') } else { raw_name } + // Skip C globals that are already provided by C headers or cheaders. + if field.name.starts_with('C.') { + continue + } key := 'extern_global_${name}' if key in g.emitted_types { continue diff --git a/vlib/veb/context.v b/vlib/veb/context.v index a628aa1a0..a489c3cc8 100644 --- a/vlib/veb/context.v +++ b/vlib/veb/context.v @@ -495,9 +495,11 @@ pub fn (mut ctx Context) takeover_conn() { if ctx.conn == unsafe { nil } && ctx.client_fd >= 0 { // Set the fd to blocking mode — fasthttp uses non-blocking sockets, // but TcpConn.write() expects blocking behavior for reliable writes. - flags := C.fcntl(ctx.client_fd, C.F_GETFL, 0) - if flags != -1 { - C.fcntl(ctx.client_fd, C.F_SETFL, flags & ~C.O_NONBLOCK) + $if !windows { + flags := C.fcntl(ctx.client_fd, C.F_GETFL, 0) + if flags != -1 { + C.fcntl(ctx.client_fd, C.F_SETFL, flags & ~C.O_NONBLOCK) + } } ctx.conn = &net.TcpConn{ sock: net.TcpSocket{ -- 2.39.5