From 695dcb2ff8486838b2faf1d25d1ffd0f1230ec23 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 17 Oct 2024 15:09:31 -0300 Subject: [PATCH] fix --- vlib/v/gen/c/assign.v | 11 +++++--- vlib/v/gen/c/auto_free_methods.v | 28 ++++++++++++++++++- .../testdata/interface_auto_free.c.must_have | 20 +++++++++++++ vlib/v/gen/c/testdata/interface_auto_free.vv | 20 +++++++++++++ 4 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 vlib/v/gen/c/testdata/interface_auto_free.c.must_have create mode 100644 vlib/v/gen/c/testdata/interface_auto_free.vv diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index 18e3694cedfe7b..7bfc255c711635 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -723,10 +723,13 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { g.write(', ') } mut cloned := false - if g.is_autofree && right_sym.kind in [.array, .string] - && !unwrapped_val_type.has_flag(.shared_f) { - if g.gen_clone_assignment(var_type, val, unwrapped_val_type, false) { - cloned = true + if g.is_autofree { + if right_sym.kind in [.array, .string] && !unwrapped_val_type.has_flag(.shared_f) { + if g.gen_clone_assignment(var_type, val, unwrapped_val_type, false) { + cloned = true + } + } else if right_sym.kind == .interface { + g.get_free_method(var_type) } } if !cloned { diff --git a/vlib/v/gen/c/auto_free_methods.v b/vlib/v/gen/c/auto_free_methods.v index 18606ce1069ce1..a4cce176424d4c 100644 --- a/vlib/v/gen/c/auto_free_methods.v +++ b/vlib/v/gen/c/auto_free_methods.v @@ -43,7 +43,7 @@ fn (mut g Gen) gen_free_method(typ ast.Type) string { sym = g.table.sym(sym.info.parent_type) } } - if sym.has_method_with_generic_parent('free') { + if sym.kind != .interface && sym.has_method_with_generic_parent('free') { return fn_name } @@ -57,6 +57,9 @@ fn (mut g Gen) gen_free_method(typ ast.Type) string { ast.Map { g.gen_free_for_map(objtyp, sym.info, styp, fn_name) } + ast.Interface { + g.gen_free_for_interface(sym, sym.info, styp, fn_name) + } else { println(g.table.type_str(typ)) // print_backtrace() @@ -67,6 +70,29 @@ fn (mut g Gen) gen_free_method(typ ast.Type) string { return fn_name } +fn (mut g Gen) gen_free_for_interface(sym ast.TypeSymbol, info ast.Interface, styp string, fn_name string) { + g.definitions.writeln('${g.static_modifier} void ${fn_name}(${styp}* it); // auto') + mut fn_builder := strings.new_builder(128) + defer { + g.auto_fn_definitions << fn_builder.str() + } + fn_builder.writeln('${g.static_modifier} void ${fn_name}(${styp}* it) {') + fn_builder.writeln('\tswitch (it->_typ) {') + for t in info.types { + sub_sym := g.table.sym(ast.mktyp(t)) + if sub_sym.kind !in [.string, .array, .map, .struct] { + continue + } + fn_name_typ := g.get_free_method(t) + fn_builder.writeln('\t\tcase _${sym.cname}_${sub_sym.cname}_index:') + fn_builder.writeln('\t\t\t${fn_name_typ}(it);') + fn_builder.writeln('\t\t\tbreak;') + } + fn_builder.writeln('\t\tdefault:') + fn_builder.writeln('\t}') + fn_builder.writeln('}') +} + fn (mut g Gen) gen_free_for_struct(typ ast.Type, info ast.Struct, styp string, fn_name string) { g.definitions.writeln('${g.static_modifier} void ${fn_name}(${styp}* it); // auto') mut fn_builder := strings.new_builder(128) diff --git a/vlib/v/gen/c/testdata/interface_auto_free.c.must_have b/vlib/v/gen/c/testdata/interface_auto_free.c.must_have new file mode 100644 index 00000000000000..8546d66ab5d83e --- /dev/null +++ b/vlib/v/gen/c/testdata/interface_auto_free.c.must_have @@ -0,0 +1,20 @@ + void main__IFoo_free(main__IFoo* it) { + switch (it->_typ) { + case _main__IFoo_main__Foo_index: + main__Foo_free(it); + break; + case _main__IFoo_array_index: + array_free(it); + break; + case _main__IFoo_map_index: + map_free(it); + break; + case _main__IFoo_VAssertMetaInfo_index: + VAssertMetaInfo_free(it); + break; + case _main__IFoo_MessageError_index: + MessageError_free(it); + break; + default: + } +} \ No newline at end of file diff --git a/vlib/v/gen/c/testdata/interface_auto_free.vv b/vlib/v/gen/c/testdata/interface_auto_free.vv new file mode 100644 index 00000000000000..c33f61558eca8f --- /dev/null +++ b/vlib/v/gen/c/testdata/interface_auto_free.vv @@ -0,0 +1,20 @@ +// vtest vflags: -autofree +module main + +interface IFoo { + free() +} + +struct Bar { + a int +} + +struct Foo implements IFoo { + Bar +} + +fn (f &Foo) free() {} + +fn main() { + a := IFoo(Foo{}) +}