diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 2adce55440..dd525ddbc0 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -864,6 +864,11 @@ static inline void __${typ.cname}_pushval($typ.cname ch, $el_stype val) { } // Generating interfaces after all the common types have been defined // to prevent generating interface struct before definition of field types + for typ in g.table.type_symbols { + if typ.kind == .interface_ && typ.name !in c.builtins { + g.write_interface_typedef(typ) + } + } for typ in g.table.type_symbols { if typ.kind == .interface_ && typ.name !in c.builtins { g.write_interface_typesymbol_declaration(typ) @@ -893,13 +898,17 @@ pub fn (mut g Gen) write_alias_typesymbol_declaration(sym ast.TypeSymbol) { g.type_definitions.writeln('typedef $parent_styp $sym.cname;') } +pub fn (mut g Gen) write_interface_typedef(sym ast.TypeSymbol) { + struct_name := c_name(sym.cname) + g.type_definitions.writeln('typedef struct $struct_name $struct_name;') +} + pub fn (mut g Gen) write_interface_typesymbol_declaration(sym ast.TypeSymbol) { info := sym.info as ast.Interface if info.is_generic { return } struct_name := c_name(sym.cname) - g.type_definitions.writeln('typedef struct $struct_name $struct_name;') g.type_definitions.writeln('struct $struct_name {') g.type_definitions.writeln('\tunion {') g.type_definitions.writeln('\t\tvoid* _object;') @@ -5386,6 +5395,7 @@ fn (mut g Gen) write_builtin_types() { for builtin_name in c.builtins { sym := g.table.type_symbols[g.table.type_idxs[builtin_name]] if sym.kind == .interface_ { + g.write_interface_typedef(sym) g.write_interface_typesymbol_declaration(sym) } else { builtin_types << sym diff --git a/vlib/v/tests/interface_nested_field_test.v b/vlib/v/tests/interface_nested_field_test.v index 2a17751dc7..606df66f52 100644 --- a/vlib/v/tests/interface_nested_field_test.v +++ b/vlib/v/tests/interface_nested_field_test.v @@ -37,3 +37,29 @@ fn test_interface_nested_field() { assert ret[0] == 'bar' assert ret[1] == 'subbar' } + +interface Root { + v View +} + +struct MyRoot { + v View +} + +interface View { + render() int +} + +struct MyView {} + +fn (m MyView) render() int { + return 24 +} + +fn receive_root(r Root) int { + return r.v.render() +} + +fn test_nested_interface_fields() { + assert receive_root(MyRoot{MyView{}}) == 24 +}