From 04ff511e27cf5af69a851a9345412f190c59ad1b Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 10 Jul 2024 06:42:08 -0300 Subject: [PATCH] cgen, checker: fix wrong receiver generic resolution with embed types (#21833) --- vlib/v/checker/fn.v | 10 ++- vlib/v/gen/c/fn.v | 13 ++- vlib/v/tests/generic_receiver_embed_test.v | 100 +++++++++++++++++++++ 3 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 vlib/v/tests/generic_receiver_embed_test.v diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 60241a3218..03d91353d1 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1589,15 +1589,23 @@ fn (mut c Checker) register_trace_call(node ast.CallExpr, func ast.Fn) { fn (mut c Checker) is_generic_expr(node ast.Expr) bool { return match node { ast.Ident { + // variable declared as generic type c.comptime.is_generic_param_var(node) } ast.IndexExpr { + // generic_var[N] c.comptime.is_generic_param_var(node.left) } ast.CallExpr { - node.args.any(c.comptime.is_generic_param_var(it.expr)) + // fn which has any generic dependent expr + if node.args.any(c.comptime.is_generic_param_var(it.expr)) { + return true + } + // fn[T]() or generic_var.fn[T]() + node.concrete_types.any(it.has_flag(.generic)) } ast.SelectorExpr { + // generic_var.property c.comptime.is_generic_param_var(node.expr) } else { diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 352ec4d86a..a579375b11 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1804,13 +1804,22 @@ fn (mut g Gen) method_call(node ast.CallExpr) { g.expr(node.left) } if !is_interface || node.from_embed_types.len == 0 { - for i, embed in node.from_embed_types { + mut node_embed_types := node.from_embed_types.clone() + if node.left is ast.Ident && g.comptime.get_ct_type_var(node.left) == .generic_var { + _, embed_types := g.table.find_method_from_embeds(final_left_sym, node.name) or { + ast.Fn{}, []ast.Type{} + } + if embed_types.len > 0 { + node_embed_types = embed_types.clone() + } + } + for i, embed in node_embed_types { embed_sym := g.table.sym(embed) embed_name := embed_sym.embed_name() is_left_ptr := if i == 0 { left_type.is_ptr() } else { - node.from_embed_types[i - 1].is_ptr() + node_embed_types[i - 1].is_ptr() } if is_left_ptr { g.write('->') diff --git a/vlib/v/tests/generic_receiver_embed_test.v b/vlib/v/tests/generic_receiver_embed_test.v new file mode 100644 index 0000000000..c3da9a260a --- /dev/null +++ b/vlib/v/tests/generic_receiver_embed_test.v @@ -0,0 +1,100 @@ +pub type Entity = u64 +type ComponentType = u16 + +pub struct Context { +pub mut: + ecs &Ecs +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +pub struct EntityManager { +mut: + living_entity_count u64 +} + +fn (mut self EntityManager) create_entity() Entity { + entity := self.living_entity_count + self.living_entity_count++ + return entity +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +pub interface ISystem { + ecs &Ecs +mut: + init() +} + +pub struct System { +pub mut: + ecs &Ecs +} + +pub fn (mut self System) init() { +} + +pub struct SystemManager { +mut: + system_array map[string]ISystem = {} +} + +fn (mut self SystemManager) add_system[T]() &T { + mut t := T{} + self.system_array[typeof[T]().name] = t + return &t +} + +//////////////////////////////////////////////////////////////////////////// + +@[heap] +pub struct Ecs { +mut: + entity_manager EntityManager + system_manager SystemManager +pub mut: + root_entity Entity +} + +pub fn Ecs.new() &Ecs { + mut ecs := &Ecs{} + ecs.root_entity = ecs.create_entity() + return ecs +} + +pub fn (mut self Ecs) create_entity() Entity { + return self.entity_manager.create_entity() +} + +pub fn (mut self Ecs) add_system[T]() { + mut system := self.system_manager.add_system[T]() + system.ecs = &self + system.init() +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +struct NetworkUdpServerComponent { +} + +struct NetworkServerSystemUdp { + System +} + +pub struct ConfigSystem { + System +} + +struct NetworkServerSystemUdpExt { + NetworkServerSystemUdp +} + +fn test_main() { + mut ecs := Ecs.new() + mut root_entity := ecs.create_entity() + + ecs.add_system[ConfigSystem]() + ecs.add_system[NetworkServerSystemUdpExt]() + + assert true +}