From 8a2236d3f8ee6feee34bca2cd52b532fbadb3980 Mon Sep 17 00:00:00 2001
From: yuyi <yuyi98@163.com>
Date: Mon, 6 Jun 2022 17:30:48 +0800
Subject: [PATCH] cgen: fix generic interface with non-generic method (#14694)

---
 vlib/v/gen/c/cgen.v                           |  4 +-
 ...s_interface_with_non_generic_method_test.v | 45 +++++++++++++++++++
 2 files changed, 47 insertions(+), 2 deletions(-)
 create mode 100644 vlib/v/tests/generics_interface_with_non_generic_method_test.v

diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v
index e8d177bd0e..b26ad28a6e 100644
--- a/vlib/v/gen/c/cgen.v
+++ b/vlib/v/gen/c/cgen.v
@@ -5743,7 +5743,7 @@ static inline __shared__$interface_name ${shared_fn_name}(__shared__$cctype* x)
 
 			for method in methods {
 				mut name := method.name
-				if inter_info.parent_type.has_flag(.generic) {
+				if method.generic_names.len > 0 && inter_info.parent_type.has_flag(.generic) {
 					parent_sym := g.table.sym(inter_info.parent_type)
 					match parent_sym.info {
 						ast.Struct, ast.Interface, ast.SumType {
@@ -5760,7 +5760,7 @@ static inline __shared__$interface_name ${shared_fn_name}(__shared__$cctype* x)
 				}
 				// .speak = Cat_speak
 				if st_sym.info is ast.Struct {
-					if st_sym.info.parent_type.has_flag(.generic) {
+					if method.generic_names.len > 0 && st_sym.info.parent_type.has_flag(.generic) {
 						name = g.generic_fn_name(st_sym.info.concrete_types, method.name,
 							false)
 					}
diff --git a/vlib/v/tests/generics_interface_with_non_generic_method_test.v b/vlib/v/tests/generics_interface_with_non_generic_method_test.v
new file mode 100644
index 0000000000..3d95b533bf
--- /dev/null
+++ b/vlib/v/tests/generics_interface_with_non_generic_method_test.v
@@ -0,0 +1,45 @@
+module main
+
+interface TypeFactory<T> {
+	get_type(type_name string) T
+}
+
+enum NodeType {
+	unknown
+	expression
+	statement
+	literal
+}
+
+struct EnumTypeFactory {}
+
+fn (f EnumTypeFactory) get_type(type_name string) NodeType {
+	return match type_name {
+		'expression' { NodeType.expression }
+		'statement' { NodeType.statement }
+		'literal' { NodeType.literal }
+		else { NodeType.unknown }
+	}
+}
+
+struct Node<T> {
+	factory   TypeFactory<T>
+	type_name NodeType
+}
+
+fn new_node<T>(type_name string, factory TypeFactory<T>) Node<T> {
+	return Node<T>{
+		factory: factory
+		type_name: factory.get_type(type_name)
+	}
+}
+
+fn test_generic_interface_with_non_generic_method() {
+	root1 := new_node<NodeType>('literal', EnumTypeFactory{})
+	println(root1)
+	assert root1.type_name == .literal
+
+	root2 := new_node<NodeType>('expression', root1.factory)
+	println(root2)
+	assert root2.type_name == .expression
+}