From ff452cc514b3423eceb752194f9a188fb76809b6 Mon Sep 17 00:00:00 2001 From: yuyi Date: Tue, 19 Sep 2023 04:22:19 +0800 Subject: [PATCH] cgen: fix interface with multiple embedded fields (#19377) --- vlib/v/gen/c/cgen.v | 20 ++++++++--- ...interface_with_multi_nested_embed_3_test.v | 34 +++++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 vlib/v/tests/interface_with_multi_nested_embed_3_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index e307ce0ce721ba..6ad189306c28dd 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -6734,11 +6734,21 @@ fn (mut g Gen) interface_table() string { cast_struct.write_string('/*.... ast.voidptr_type */') } else { if st_sym.kind == .struct_ { - for embed_type in st_sym.struct_info().embeds { - embed_sym := g.table.sym(embed_type) - if _ := embed_sym.find_field(field.name) { - cast_struct.write_string(' + __offsetof_ptr(x, ${cctype}, ${embed_sym.embed_name()}) + __offsetof_ptr(x, ${embed_sym.cname}, ${cname})') - break + if _, embeds := g.table.find_field_from_embeds(st_sym, + field.name) + { + mut typ_name := '' + for i, embed in embeds { + esym := g.table.sym(embed) + if i == 0 { + cast_struct.write_string(' + __offsetof_ptr(x, ${cctype}, ${esym.embed_name()})') + } else { + cast_struct.write_string(' + __offsetof_ptr(x, ${typ_name}, ${esym.embed_name()})') + } + typ_name = esym.cname + } + if embeds.len > 0 { + cast_struct.write_string(' + __offsetof_ptr(x, ${typ_name}, ${cname})') } } } diff --git a/vlib/v/tests/interface_with_multi_nested_embed_3_test.v b/vlib/v/tests/interface_with_multi_nested_embed_3_test.v new file mode 100644 index 00000000000000..4dfcdf8ae18646 --- /dev/null +++ b/vlib/v/tests/interface_with_multi_nested_embed_3_test.v @@ -0,0 +1,34 @@ +interface NodeInterface { +mut: + node_type NodeType + node_name string +} + +enum NodeType { + @none +} + +struct Node { +mut: + // removing this field works makes `InterfaceNode(x).node_name.len` below work as expected + node_type NodeType + node_name string +} + +struct Element { + Node +} + +struct HTMLElement { + Element +} + +fn test_interface_with_multi_nested_embed() { + x := &HTMLElement{} + struct_name_len := x.node_name.len + interface_name_len := NodeInterface(x).node_name.len + println('struct: ${struct_name_len}') + assert struct_name_len == 0 + println('interface: ${interface_name_len}') + assert interface_name_len == 0 +}