From caa0e25939493aaae571772dc24072f4726bd716 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sun, 20 Mar 2022 20:23:48 +0200 Subject: [PATCH] cgen: fix struct type dependency sorting, when struct field types, are aliases to struct types from other modules (#13779) --- vlib/v/gen/c/cgen.v | 25 +++++++++++++------ .../modules/alias_to_another_module/alias.v | 9 +++++++ vlib/v/tests/modules/another_module/module.v | 12 +++++++++ ...from_another_module_in_struct_field_test.v | 14 +++++++++++ 4 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 vlib/v/tests/modules/alias_to_another_module/alias.v create mode 100644 vlib/v/tests/modules/another_module/module.v create mode 100644 vlib/v/tests/use_alias_from_another_module_in_struct_field_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index f40d88bc92..b3db40405a 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4524,17 +4524,17 @@ fn (mut g Gen) write_builtin_types() { // Sort the types, make sure types that are referenced by other types // are added before them. fn (mut g Gen) write_sorted_types() { + g.type_definitions.writeln('// #start sorted_symbols') + defer { + g.type_definitions.writeln('// #end sorted_symbols') + } mut symbols := []&ast.TypeSymbol{cap: g.table.type_symbols.len} // structs that need to be sorted for sym in g.table.type_symbols { if sym.name !in c.builtins { symbols << sym } } - // sort structs sorted_symbols := g.sort_structs(symbols) - // Generate C code - g.type_definitions.writeln('// builtin types:') - g.type_definitions.writeln('//------------------ #endbuiltin') g.write_types(sorted_symbols) } @@ -4706,7 +4706,7 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) { } // sort structs by dependant fields -fn (g &Gen) sort_structs(typesa []&ast.TypeSymbol) []&ast.TypeSymbol { +fn (mut g Gen) sort_structs(typesa []&ast.TypeSymbol) []&ast.TypeSymbol { util.timing_start(@METHOD) defer { util.timing_measure(@METHOD) @@ -4742,12 +4742,23 @@ fn (g &Gen) sort_structs(typesa []&ast.TypeSymbol) []&ast.TypeSymbol { field_deps << dep } for field in sym.info.fields { - dep := g.table.sym(field.typ).name + if field.typ.is_ptr() { + continue + } + fsym := g.table.sym(field.typ) + dep := fsym.name // skip if not in types list or already in deps - if dep !in type_names || dep in field_deps || field.typ.is_ptr() { + if dep !in type_names || dep in field_deps { continue } field_deps << dep + if fsym.info is ast.Alias { + xdep := g.table.sym(fsym.info.parent_type).name + if xdep !in type_names || xdep in field_deps { + continue + } + field_deps << xdep + } } } // ast.Interface {} diff --git a/vlib/v/tests/modules/alias_to_another_module/alias.v b/vlib/v/tests/modules/alias_to_another_module/alias.v new file mode 100644 index 0000000000..d92a17ea62 --- /dev/null +++ b/vlib/v/tests/modules/alias_to_another_module/alias.v @@ -0,0 +1,9 @@ +module alias_to_another_module + +import another_module + +pub type MyAlias = another_module.SomeStruct + +pub fn (m MyAlias) alias_method() int { + return 42 +} diff --git a/vlib/v/tests/modules/another_module/module.v b/vlib/v/tests/modules/another_module/module.v new file mode 100644 index 0000000000..a21270ea7c --- /dev/null +++ b/vlib/v/tests/modules/another_module/module.v @@ -0,0 +1,12 @@ +module another_module + +pub struct SomeStruct { +pub mut: + x int + y int + z int +} + +pub fn (s SomeStruct) some_method() int { + return 999 + s.x + s.y + s.z +} diff --git a/vlib/v/tests/use_alias_from_another_module_in_struct_field_test.v b/vlib/v/tests/use_alias_from_another_module_in_struct_field_test.v new file mode 100644 index 0000000000..ed4d194279 --- /dev/null +++ b/vlib/v/tests/use_alias_from_another_module_in_struct_field_test.v @@ -0,0 +1,14 @@ +import alias_to_another_module + +struct MyStruct { + myfield alias_to_another_module.MyAlias +} + +fn test_using_struct_with_alias() { + m := MyStruct{ + myfield: alias_to_another_module.MyAlias{1, 2, 3} + } + dump(m) + assert m.myfield.alias_method() == 42 + assert m.myfield.some_method() == 1005 +}