From b5379255da0de77ee5efaccd38500de375cffa64 Mon Sep 17 00:00:00 2001 From: yuyi Date: Sun, 13 Feb 2022 02:55:40 +0800 Subject: [PATCH] checker, cgen: fix error for struct embed with fn type (#13450) --- vlib/v/checker/fn.v | 5 +++- vlib/v/gen/c/fn.v | 10 ++++++++ vlib/v/tests/struct_embed_fn_type_test.v | 29 ++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/struct_embed_fn_type_test.v diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index df56c4e869..72e7501b4b 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1424,7 +1424,7 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type { } // call struct field fn type // TODO: can we use SelectorExpr for all? this dosent really belong here - if field := c.table.find_field(left_sym, method_name) { + if field := c.table.find_field_with_embeds(left_sym, method_name) { field_sym := c.table.sym(c.unwrap_generic(field.typ)) if field_sym.kind == .function { node.is_method = false @@ -1453,6 +1453,9 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type { } node.expected_arg_types = earg_types node.is_method = true + _, node.from_embed_types = c.table.find_field_from_embeds(left_sym, method_name) or { + return info.func.return_type + } return info.func.return_type } } diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index df60db62b3..dbf23844b9 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1118,6 +1118,16 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { } else { g.write('.') } + for embed in node.from_embed_types { + embed_sym := g.table.sym(embed) + embed_name := embed_sym.embed_name() + g.write(embed_name) + if embed.is_ptr() { + g.write('->') + } else { + g.write('.') + } + } is_selector_call = true } if g.inside_comptime_for_field { diff --git a/vlib/v/tests/struct_embed_fn_type_test.v b/vlib/v/tests/struct_embed_fn_type_test.v new file mode 100644 index 0000000000..4fd87349a8 --- /dev/null +++ b/vlib/v/tests/struct_embed_fn_type_test.v @@ -0,0 +1,29 @@ +type FnClick = fn () string + +struct Widget { +mut: + x int + y int + click FnClick = click +} + +fn click() string { + return 'click me' +} + +struct Button { + Widget + title string +} + +fn test_struct_embed_fn_type() { + mut button := Button{ + title: 'Click me' + } + + button.x = 3 + ret := button.click() + + println(ret) + assert ret == 'click me' +}