1
0
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:
Felipe Pena 2023-07-02 00:54:52 -03:00 committed by GitHub
parent 7ce96b2c41
commit 29c8aaeb89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 6 deletions

View File

@ -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()

View 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
}