mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix selector code to use interface method table on closure when needed (#18736)
This commit is contained in:
parent
7ce96b2c41
commit
29c8aaeb89
@ -3579,9 +3579,6 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||
opt_base_typ := g.base_type(node.expr_type)
|
||||
g.write('(*(${opt_base_typ}*)')
|
||||
}
|
||||
if sym.kind in [.interface_, .sum_type] {
|
||||
g.write('(*(')
|
||||
}
|
||||
if sym.kind == .array_fixed {
|
||||
if node.field_name != 'len' {
|
||||
g.error('field_name should be `len`', node.pos)
|
||||
@ -3601,6 +3598,9 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||
if f := g.table.find_field_with_embeds(sym, node.field_name) {
|
||||
field_sym := g.table.sym(f.typ)
|
||||
field_typ = f.typ
|
||||
if sym.kind in [.interface_, .sum_type] {
|
||||
g.write('(*(')
|
||||
}
|
||||
if field_sym.kind in [.sum_type, .interface_] {
|
||||
if !prevent_sum_type_unwrapping_once {
|
||||
// check first if field is sum type because scope searching is expensive
|
||||
@ -3675,10 +3675,16 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||
method_name = g.generic_fn_name(rec_sym.info.concrete_types, m.name)
|
||||
}
|
||||
}
|
||||
if rec_sym.info is ast.Interface {
|
||||
left_cc_type := g.cc_type(g.table.unaliased_type(receiver.typ), false)
|
||||
left_type_name := util.no_dots(left_cc_type)
|
||||
sb.write_string('${c_name(left_type_name)}_name_table[a0->_typ]._method_${method_name}(')
|
||||
} else {
|
||||
sb.write_string('${expr_styp}_${method_name}(')
|
||||
if !receiver.typ.is_ptr() {
|
||||
sb.write_string('*')
|
||||
}
|
||||
}
|
||||
for i in 0 .. m.params.len {
|
||||
if i != 0 {
|
||||
sb.write_string(', ')
|
||||
@ -3705,6 +3711,10 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||
g.write(')')
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if sym.kind in [.interface_, .sum_type] {
|
||||
g.write('(*(')
|
||||
}
|
||||
}
|
||||
// var?.field_opt
|
||||
field_is_opt := (node.expr is ast.Ident && node.expr.is_auto_heap()
|
||||
|
30
vlib/v/tests/interface_closure_test.v
Normal file
30
vlib/v/tests/interface_closure_test.v
Normal file
@ -0,0 +1,30 @@
|
||||
interface ITest {
|
||||
mut:
|
||||
caller(a Test) !
|
||||
}
|
||||
|
||||
struct Test {
|
||||
}
|
||||
|
||||
struct Test2 {
|
||||
}
|
||||
|
||||
fn (t2 Test2) with_reader(func fn (a Test) !) ! {
|
||||
return func(Test{})
|
||||
}
|
||||
|
||||
fn (t Test) caller(a Test) ! {
|
||||
println('ok')
|
||||
}
|
||||
|
||||
fn get() ITest {
|
||||
return Test{}
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
mut a := get()
|
||||
|
||||
b := Test2{}
|
||||
b.with_reader(a.caller)!
|
||||
assert true
|
||||
}
|
Loading…
Reference in New Issue
Block a user