From a51ce07ac92dcae986b546f2ff8307226945baad Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 30 May 2026 22:01:42 +0300 Subject: [PATCH] cgen: fix bound interface method values (#27293) --- vlib/v/gen/c/cgen.v | 15 +++-- ..._bound_mut_method_value_issue_26986_test.v | 56 +++++++++++++++++++ 2 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 vlib/v/tests/interfaces/interface_bound_mut_method_value_issue_26986_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index a22e346cb..57a27d013 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -7675,6 +7675,11 @@ fn (mut g Gen) gen_closure_fn(expr_styp string, m ast.Fn, name string) { if rec_sym.info is ast.Interface && rec_sym.info.get_methods().contains(method_name) { methods_struct_name := g.interface_methods_struct_name(receiver.typ) sb.write_string('((${methods_struct_name}*)a0->_methods)->_method_${method_name}(') + sb.write_string('a0->_object') + for i in 1 .. m.params.len { + sb.write_string(', ') + sb.write_string('a${i}') + } } else { mut full_method_name := '${expr_styp}_${method_name}' if !expr_styp.starts_with('builtin__') { @@ -7690,12 +7695,12 @@ fn (mut g Gen) gen_closure_fn(expr_styp string, m ast.Fn, name string) { if !receiver.typ.is_ptr() { sb.write_string('*') } - } - for i in 0 .. m.params.len { - if i != 0 { - sb.write_string(', ') + for i in 0 .. m.params.len { + if i != 0 { + sb.write_string(', ') + } + sb.write_string('a${i}') } - sb.write_string('a${i}') } sb.writeln(');') sb.writeln('}') diff --git a/vlib/v/tests/interfaces/interface_bound_mut_method_value_issue_26986_test.v b/vlib/v/tests/interfaces/interface_bound_mut_method_value_issue_26986_test.v new file mode 100644 index 000000000..ea132c5a8 --- /dev/null +++ b/vlib/v/tests/interfaces/interface_bound_mut_method_value_issue_26986_test.v @@ -0,0 +1,56 @@ +struct ProtoReader { + value string +} + +fn (pr &ProtoReader) read() string { + return pr.value +} + +struct Conn { + rd &ProtoReader +} + +fn (c &Conn) with_proto_reader(f fn (rd &ProtoReader) !) ! { + f(c.rd)! +} + +interface Cmder { +mut: + read_reply(rd &ProtoReader) ! +} + +struct SomeCmd { +mut: + value string +} + +fn (mut sc SomeCmd) read_reply(rd &ProtoReader) ! { + sc.value = rd.read() +} + +fn process_via_interface_pointer(mut cmd Cmder) ! { + c := &Conn{ + rd: &ProtoReader{ + value: 'from pointer' + } + } + mut cmd_ref := unsafe { &cmd } + c.with_proto_reader(cmd_ref.read_reply)! +} + +fn process_via_interface_value(mut cmd Cmder) ! { + c := &Conn{ + rd: &ProtoReader{ + value: 'from value' + } + } + c.with_proto_reader(cmd.read_reply)! +} + +fn test_bound_mut_interface_method_value_mutates_underlying_object() ! { + mut cmd := &SomeCmd{} + process_via_interface_pointer(mut cmd)! + assert cmd.value == 'from pointer' + process_via_interface_value(mut cmd)! + assert cmd.value == 'from value' +} -- 2.39.5