From 8ffcc34224e5e553d697d291cd26188df65fe40e Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 27 Oct 2024 15:43:15 -0300 Subject: [PATCH] checker: fix `f: app.method` field initialisation, for fn fields, initialised with generic methods (#22665) --- vlib/v/checker/checker.v | 6 +++--- vlib/v/gen/c/cgen.v | 2 +- vlib/v/tests/selector_generic_fn_test.v | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 vlib/v/tests/selector_generic_fn_test.v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 959c8e59f9..cc6ae0a697 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1696,7 +1696,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { } return field.typ } - if mut method := sym.find_method_with_generic_parent(field_name) { + if mut method := c.table.sym(c.unwrap_generic(typ)).find_method_with_generic_parent(field_name) { if c.expected_type != 0 && c.expected_type != ast.none_type { fn_type := ast.new_type(c.table.find_or_register_fn_type(method, false, true)) // if the expected type includes the receiver, don't hide it behind a closure @@ -1704,7 +1704,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { return fn_type } } - receiver := method.params[0].typ + receiver := c.unwrap_generic(method.params[0].typ) if receiver.nr_muls() > 0 { if !c.inside_unsafe { rec_sym := c.table.sym(receiver.set_nr_muls(0)) @@ -1723,7 +1723,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { node.has_hidden_receiver = true method.name = '' fn_type := ast.new_type(c.table.find_or_register_fn_type(method, false, true)) - node.typ = fn_type + node.typ = c.unwrap_generic(fn_type) return fn_type } if sym.kind !in [.struct, .aggregate, .interface, .sum_type] { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 53b4682ce0..777b6c1ed1 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4028,7 +4028,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { return } receiver := m.params[0] - expr_styp := g.styp(node.expr_type.idx_type()) + expr_styp := g.styp(g.unwrap_generic(node.expr_type).idx_type()) data_styp := g.styp(receiver.typ.idx_type()) mut sb := strings.new_builder(256) name := '_V_closure_${expr_styp}_${m.name}_${node.pos.pos}' diff --git a/vlib/v/tests/selector_generic_fn_test.v b/vlib/v/tests/selector_generic_fn_test.v new file mode 100644 index 0000000000..fedeb490c8 --- /dev/null +++ b/vlib/v/tests/selector_generic_fn_test.v @@ -0,0 +1,24 @@ +struct Struct { + f fn (f64) f64 = unsafe { nil } +} + +struct App {} + +pub fn (mut a App) frame(dt f64) f64 { + dump(voidptr(a)) + dump(dt) + return dt +} + +fn generic_f[T](mut ctx T) ! { + s := Struct{ + f: unsafe { ctx.frame } + } + assert s.f(1.2) == 1.2 +} + +fn test_main() { + mut app := &App{} + generic_f(mut app)! + assert true +}