From a440b43630a265d53281d49026928dd40ecdaf49 Mon Sep 17 00:00:00 2001 From: yuyi Date: Fri, 20 Aug 2021 06:13:48 +0800 Subject: [PATCH] checker, cgen: fix generic struct with non_generic interface (#11240) --- vlib/v/checker/checker.v | 4 +++ vlib/v/gen/c/cgen.v | 6 +++++ ...s_struct_with_non_generic_interface_test.v | 25 +++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 vlib/v/tests/generics_struct_with_non_generic_interface_test.v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 24398ae92e..718ebd8761 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -845,6 +845,10 @@ pub fn (mut c Checker) generic_insts_to_concrete() { typ.is_public = true typ.kind = parent.kind } + parent_sym := c.table.get_type_symbol(parent_info.parent_type) + for method in parent_sym.methods { + c.table.register_fn_concrete_types(method.name, info.concrete_types) + } } ast.Interface { mut parent_info := parent.info as ast.Interface diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 4c8967af39..d1035ca052 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -6652,6 +6652,12 @@ static inline $interface_name I_${cctype}_to_Interface_${interface_name}($cctype continue } // .speak = Cat_speak + if st_sym.info is ast.Struct { + if st_sym.info.parent_type.has_flag(.generic) { + name = g.generic_fn_name(st_sym.info.concrete_types, method.name, + false) + } + } mut method_call := '${cctype}_$name' if !method.params[0].typ.is_ptr() { // inline void Cat_speak_Interface_Animal_method_wrapper(Cat c) { return Cat_speak(*c); } diff --git a/vlib/v/tests/generics_struct_with_non_generic_interface_test.v b/vlib/v/tests/generics_struct_with_non_generic_interface_test.v new file mode 100644 index 0000000000..e9c22ce370 --- /dev/null +++ b/vlib/v/tests/generics_struct_with_non_generic_interface_test.v @@ -0,0 +1,25 @@ +interface Box { + transform(input int) int +} + +struct Test { + data T + salt int +} + +fn (t Test) transform(input int) int { + return input + t.salt +} + +fn box_transform(b Box) int { + return b.transform(100) +} + +fn test_generic_struct_with_non_generic_interface() { + ret := box_transform(Test{ + data: 'hello' + salt: 6 + }) + println(ret) + assert ret == 106 +}