From a6af3d514b07b08e14562fca3f61f5045ef05567 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 28 Sep 2024 10:20:44 -0300 Subject: [PATCH] cgen: fix interface method call after smartcast (fix #17056) (#22335) --- vlib/v/ast/table.v | 6 ++++++ vlib/v/gen/c/fn.v | 3 +++ .../tests/interfaces/interface_smartcast_call_test.v | 12 ++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 vlib/v/tests/interfaces/interface_smartcast_call_test.v diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 0cb6ac0db..f728acb6a 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -1389,6 +1389,12 @@ pub fn (t &Table) is_interface_var(var ScopeObject) bool { && t.sym(var.smartcasts.last()).kind != .interface_ } +@[inline] +pub fn (t &Table) is_interface_smartcast(var ScopeObject) bool { + return var is Var && var.orig_type != 0 && t.sym(var.orig_type).kind == .interface_ + && var.smartcasts.len > 0 +} + // only used for debugging V compiler type bugs pub fn (t &Table) known_type_names() []string { mut res := []string{cap: t.type_idxs.len} diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 74cfb65ee..6c096166d 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1748,6 +1748,9 @@ fn (mut g Gen) method_call(node ast.CallExpr) { if !node.left.is_lvalue() { g.write('ADDR(${rec_cc_type}, ') cast_n++ + } else if node.left is ast.Ident && g.table.is_interface_smartcast(node.left.obj) { + g.write('ADDR(${rec_cc_type}, ') + cast_n++ } else if !is_array_method_first_last_repeat && !(left_type.has_flag(.shared_f) && g.typ(left_type) == g.typ(node.receiver_type)) { g.write('&') diff --git a/vlib/v/tests/interfaces/interface_smartcast_call_test.v b/vlib/v/tests/interfaces/interface_smartcast_call_test.v new file mode 100644 index 000000000..13d9ecf4c --- /dev/null +++ b/vlib/v/tests/interfaces/interface_smartcast_call_test.v @@ -0,0 +1,12 @@ +interface Foo {} + +fn (f &Foo) func() {} + +struct Bar {} + +fn test_main() { + mut f := Foo(Bar{}) + if mut f is Foo { + f.func() + } +} -- 2.39.5