From a01484405081fa00eb5dd06260ced2acc5289c6d Mon Sep 17 00:00:00 2001 From: yuyi Date: Tue, 1 Feb 2022 20:50:12 +0800 Subject: [PATCH] cgen: fix error for interface with multi nested embed structs (fix #13331) (#13336) --- vlib/v/ast/table.v | 12 +++ vlib/v/gen/c/cgen.v | 13 +-- ...face_struct_with_multi_nested_embed_test.v | 91 +++++++++++++++++++ 3 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 vlib/v/tests/interface_struct_with_multi_nested_embed_test.v diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 127835d15a..62d2493c4d 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -446,6 +446,18 @@ pub fn (t &Table) find_method_with_embeds(sym &TypeSymbol, method_name string) ? } } +pub fn (t &Table) get_embed_methods(sym &TypeSymbol) []Fn { + mut methods := []Fn{} + if sym.info is Struct { + for embed in sym.info.embeds { + embed_sym := t.sym(embed) + methods << embed_sym.methods + methods << t.get_embed_methods(embed_sym) + } + } + return methods +} + fn (t &Table) register_aggregate_field(mut sym TypeSymbol, name string) ?StructField { if sym.kind != .aggregate { t.panic('Unexpected type symbol: $sym.kind') diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index cd153d65e3..add0b4d121 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -6797,16 +6797,13 @@ static inline __shared__$interface_name ${shared_fn_name}(__shared__$cctype* x) } else {} } - if st_sym.info is ast.Struct { - for embed in st_sym.info.embeds { - embed_sym := g.table.sym(embed) - for embed_method in embed_sym.methods { - if embed_method.name !in method_names { - methods << embed_method - } - } + t_methods := g.table.get_embed_methods(st_sym) + for t_method in t_methods { + if t_method.name !in method_names { + methods << t_method } } + for method in methods { mut name := method.name if inter_info.parent_type.has_flag(.generic) { diff --git a/vlib/v/tests/interface_struct_with_multi_nested_embed_test.v b/vlib/v/tests/interface_struct_with_multi_nested_embed_test.v new file mode 100644 index 0000000000..794ee09143 --- /dev/null +++ b/vlib/v/tests/interface_struct_with_multi_nested_embed_test.v @@ -0,0 +1,91 @@ +fn test_interface_struct_with_multi_nested_embed() { + mut win := &Window{} + mut ll := &LinearLayout{} + mut lbl := &Label{ + x: 10 + y: 20 + } + + ll.add(mut lbl) + win.add(mut ll) + + win.init() +} + +[heap] +pub struct Window { +mut: + initables []&Initable +} + +interface Initable { +mut: + init(&Window) +} + +pub fn (mut w Window) add(mut initable Initable) { + w.initables << initable +} + +interface Container { +mut: + layout() +} + +fn (mut w Window) init() { + for wd in w.initables { + if mut wd is Container { + mut c := wd as Container + c.layout() + } + } +} + +pub struct Rect { +mut: + x int + y int +} + +pub fn (r Rect) get_pos() (int, int) { + return r.x, r.y +} + +pub struct LayoutBase { + Rect +} + +pub struct Base { + LayoutBase +} + +pub fn (mut b Base) init(window &Window) {} + +[heap] +pub struct Label { + Base +} + +pub interface Layoutable { + get_pos() (int, int) +} + +[heap] +pub struct LinearLayout { + Base +mut: + layoutables []Layoutable +} + +pub fn (mut ll LinearLayout) add(mut l Layoutable) { + ll.layoutables << l +} + +pub fn (mut ll LinearLayout) layout() { + for mut wl in ll.layoutables { + x, y := wl.get_pos() + println('$x, $y') + assert x == 10 + assert y == 20 + } +}