cgen: fix error for interface with multi nested embed structs (fix #13331) (#13336)

pull/13337/head
yuyi 2022-02-01 20:50:12 +08:00 committed by GitHub
parent 51513ae19a
commit a014844050
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 8 deletions

View File

@ -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')

View File

@ -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) {

View File

@ -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
}
}