mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix generic interface call with reference argument (#15345)
This commit is contained in:
parent
d7a3b866ee
commit
e034b35144
|
@ -689,6 +689,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
if node.receiver_type == 0 {
|
if node.receiver_type == 0 {
|
||||||
g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos)
|
g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos)
|
||||||
}
|
}
|
||||||
|
left_type := g.unwrap_generic(node.left_type)
|
||||||
mut unwrapped_rec_type := node.receiver_type
|
mut unwrapped_rec_type := node.receiver_type
|
||||||
if unsafe { g.cur_fn != 0 } && g.cur_fn.generic_names.len > 0 { // in generic fn
|
if unsafe { g.cur_fn != 0 } && g.cur_fn.generic_names.len > 0 { // in generic fn
|
||||||
unwrapped_rec_type = g.unwrap_generic(node.receiver_type)
|
unwrapped_rec_type = g.unwrap_generic(node.receiver_type)
|
||||||
|
@ -722,13 +723,13 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
eprintln('>>> interface typ_sym.name: $typ_sym.name | receiver_type_name: $receiver_type_name | pos: $node.pos')
|
eprintln('>>> interface typ_sym.name: $typ_sym.name | receiver_type_name: $receiver_type_name | pos: $node.pos')
|
||||||
}
|
}
|
||||||
|
|
||||||
left_is_shared := node.left_type.has_flag(.shared_f)
|
left_is_shared := left_type.has_flag(.shared_f)
|
||||||
left_cc_type := g.cc_type(g.table.unaliased_type(node.left_type), false)
|
left_cc_type := g.cc_type(g.table.unaliased_type(left_type), false)
|
||||||
left_type_name := util.no_dots(left_cc_type)
|
left_type_name := util.no_dots(left_cc_type)
|
||||||
g.write('${c_name(left_type_name)}_name_table[')
|
g.write('${c_name(left_type_name)}_name_table[')
|
||||||
if node.left.is_auto_deref_var() && node.left_type.nr_muls() > 1 {
|
if node.left.is_auto_deref_var() && left_type.nr_muls() > 1 {
|
||||||
g.write('(')
|
g.write('(')
|
||||||
g.write('*'.repeat(node.left_type.nr_muls() - 1))
|
g.write('*'.repeat(left_type.nr_muls() - 1))
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else {
|
} else {
|
||||||
|
@ -736,16 +737,16 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
dot := if left_is_shared {
|
dot := if left_is_shared {
|
||||||
'->val.'
|
'->val.'
|
||||||
} else if node.left_type.is_ptr() {
|
} else if left_type.is_ptr() {
|
||||||
'->'
|
'->'
|
||||||
} else {
|
} else {
|
||||||
'.'
|
'.'
|
||||||
}
|
}
|
||||||
mname := c_name(node.name)
|
mname := c_name(node.name)
|
||||||
g.write('${dot}_typ]._method_${mname}(')
|
g.write('${dot}_typ]._method_${mname}(')
|
||||||
if node.left.is_auto_deref_var() && node.left_type.nr_muls() > 1 {
|
if node.left.is_auto_deref_var() && left_type.nr_muls() > 1 {
|
||||||
g.write('(')
|
g.write('(')
|
||||||
g.write('*'.repeat(node.left_type.nr_muls() - 1))
|
g.write('*'.repeat(left_type.nr_muls() - 1))
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else {
|
} else {
|
||||||
|
@ -759,8 +760,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
left_sym := g.table.sym(node.left_type)
|
left_sym := g.table.sym(left_type)
|
||||||
final_left_sym := g.table.final_sym(node.left_type)
|
final_left_sym := g.table.final_sym(left_type)
|
||||||
if left_sym.kind == .array {
|
if left_sym.kind == .array {
|
||||||
match node.name {
|
match node.name {
|
||||||
'filter' {
|
'filter' {
|
||||||
|
@ -784,7 +785,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
'contains' {
|
'contains' {
|
||||||
g.gen_array_contains(node.left_type, node.left, node.args[0].expr)
|
g.gen_array_contains(left_type, node.left, node.args[0].expr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
'index' {
|
'index' {
|
||||||
|
@ -811,7 +812,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
left_info := left_sym.info as ast.Map
|
left_info := left_sym.info as ast.Map
|
||||||
elem_type_str := g.typ(left_info.key_type)
|
elem_type_str := g.typ(left_info.key_type)
|
||||||
g.write('map_delete(')
|
g.write('map_delete(')
|
||||||
if node.left_type.is_ptr() {
|
if left_type.is_ptr() {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
} else {
|
} else {
|
||||||
g.write('&')
|
g.write('&')
|
||||||
|
@ -823,7 +824,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
return
|
return
|
||||||
} else if left_sym.kind == .array && node.name == 'delete' {
|
} else if left_sym.kind == .array && node.name == 'delete' {
|
||||||
g.write('array_delete(')
|
g.write('array_delete(')
|
||||||
if node.left_type.is_ptr() {
|
if left_type.is_ptr() {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
} else {
|
} else {
|
||||||
g.write('&')
|
g.write('&')
|
||||||
|
@ -968,7 +969,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
// if so, then instead of calling array_clone(&array_slice(...))
|
// if so, then instead of calling array_clone(&array_slice(...))
|
||||||
// call array_clone_static(array_slice(...))
|
// call array_clone_static(array_slice(...))
|
||||||
mut is_range_slice := false
|
mut is_range_slice := false
|
||||||
if node.receiver_type.is_ptr() && !node.left_type.is_ptr() {
|
if node.receiver_type.is_ptr() && !left_type.is_ptr() {
|
||||||
if node.left is ast.IndexExpr {
|
if node.left is ast.IndexExpr {
|
||||||
idx := node.left.index
|
idx := node.left.index
|
||||||
if idx is ast.RangeExpr {
|
if idx is ast.RangeExpr {
|
||||||
|
@ -982,11 +983,11 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
name = g.generic_fn_name(node.concrete_types, name, false)
|
name = g.generic_fn_name(node.concrete_types, name, false)
|
||||||
// TODO2
|
// TODO2
|
||||||
// g.generate_tmp_autofree_arg_vars(node, name)
|
// g.generate_tmp_autofree_arg_vars(node, name)
|
||||||
if !node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name == 'str' {
|
if !node.receiver_type.is_ptr() && left_type.is_ptr() && node.name == 'str' {
|
||||||
g.write('ptr_str(')
|
g.write('ptr_str(')
|
||||||
} else if node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name == 'str'
|
} else if node.receiver_type.is_ptr() && left_type.is_ptr() && node.name == 'str'
|
||||||
&& !left_sym.has_method('str') {
|
&& !left_sym.has_method('str') {
|
||||||
g.gen_expr_to_string(node.left, node.left_type)
|
g.gen_expr_to_string(node.left, left_type)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
if left_sym.kind == .array {
|
if left_sym.kind == .array {
|
||||||
|
@ -998,10 +999,9 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
g.write('${name}(')
|
g.write('${name}(')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if node.receiver_type.is_ptr()
|
if node.receiver_type.is_ptr() && (!left_type.is_ptr() || left_type.has_flag(.variadic)
|
||||||
&& (!node.left_type.is_ptr() || node.left_type.has_flag(.variadic)
|
|
||||||
|| node.from_embed_types.len != 0
|
|| node.from_embed_types.len != 0
|
||||||
|| (node.left_type.has_flag(.shared_f) && node.name != 'str')) {
|
|| (left_type.has_flag(.shared_f) && node.name != 'str')) {
|
||||||
// The receiver is a reference, but the caller provided a value
|
// The receiver is a reference, but the caller provided a value
|
||||||
// Add `&` automatically.
|
// Add `&` automatically.
|
||||||
// TODO same logic in call_args()
|
// TODO same logic in call_args()
|
||||||
|
@ -1013,13 +1013,13 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
g.write('&')
|
g.write('&')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if !node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name != 'str'
|
} else if !node.receiver_type.is_ptr() && left_type.is_ptr() && node.name != 'str'
|
||||||
&& node.from_embed_types.len == 0 {
|
&& node.from_embed_types.len == 0 {
|
||||||
if !node.left_type.has_flag(.shared_f) {
|
if !left_type.has_flag(.shared_f) {
|
||||||
g.write('/*rec*/*')
|
g.write('/*rec*/*')
|
||||||
}
|
}
|
||||||
} else if !is_range_slice && node.from_embed_types.len == 0 && node.name != 'str' {
|
} else if !is_range_slice && node.from_embed_types.len == 0 && node.name != 'str' {
|
||||||
diff := node.left_type.nr_muls() - node.receiver_type.nr_muls()
|
diff := left_type.nr_muls() - node.receiver_type.nr_muls()
|
||||||
if diff < 0 {
|
if diff < 0 {
|
||||||
// TODO
|
// TODO
|
||||||
// g.write('&')
|
// g.write('&')
|
||||||
|
@ -1050,7 +1050,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
embed_sym := g.table.sym(embed)
|
embed_sym := g.table.sym(embed)
|
||||||
embed_name := embed_sym.embed_name()
|
embed_name := embed_sym.embed_name()
|
||||||
is_left_ptr := if i == 0 {
|
is_left_ptr := if i == 0 {
|
||||||
node.left_type.is_ptr()
|
left_type.is_ptr()
|
||||||
} else {
|
} else {
|
||||||
node.from_embed_types[i - 1].is_ptr()
|
node.from_embed_types[i - 1].is_ptr()
|
||||||
}
|
}
|
||||||
|
@ -1061,7 +1061,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
g.write(embed_name)
|
g.write(embed_name)
|
||||||
}
|
}
|
||||||
if node.left_type.has_flag(.shared_f) {
|
if left_type.has_flag(.shared_f) {
|
||||||
g.write('->val')
|
g.write('->val')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
6
vlib/v/tests/inout/dump_generic_interface_ref_arg.out
Normal file
6
vlib/v/tests/inout/dump_generic_interface_ref_arg.out
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:30] mi.in_(): 1.
|
||||||
|
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:31] mi.out(): 2.
|
||||||
|
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:36] in_put.in_(): 1.
|
||||||
|
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:37] in_put.out(): 2.
|
||||||
|
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:39] in_put.in_(): 1.
|
||||||
|
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:40] in_put.out(): 2.
|
46
vlib/v/tests/inout/dump_generic_interface_ref_arg.vv
Normal file
46
vlib/v/tests/inout/dump_generic_interface_ref_arg.vv
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
interface In {
|
||||||
|
in_() f64
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Out {
|
||||||
|
out() f64
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InOut {
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyImpl {
|
||||||
|
in_ f64
|
||||||
|
out f64
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mi &MyImpl) in_() f64 {
|
||||||
|
return mi.in_
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mi &MyImpl) out() f64 {
|
||||||
|
return mi.out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mi := MyImpl{
|
||||||
|
in_: 1.0
|
||||||
|
out: 2.0
|
||||||
|
}
|
||||||
|
dump(mi.in_())
|
||||||
|
dump(mi.out())
|
||||||
|
run(&mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run<T>(in_put T) {
|
||||||
|
dump(in_put.in_())
|
||||||
|
dump(in_put.out())
|
||||||
|
$if T is InOut {
|
||||||
|
dump(in_put.in_())
|
||||||
|
dump(in_put.out())
|
||||||
|
} $else $if T is In {
|
||||||
|
dump(in_put.in_())
|
||||||
|
} $else $if T is Out {
|
||||||
|
dump(in_put.out())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user