@@ -927,7 +927,7 @@ fn (mut g FlatGen) gen_fn_in_module(node flat.Node, module_name string) {
927927 g.writeln ('\t _vinit();' )
928928 }
929929 } else {
930- ret_type := g.tc. parse_type (node.typ )
930+ ret_type := g.fn_node_return_type (node, module_name )
931931 g.set_cur_fn_ret (ret_type)
932932 g.write (g.fn_return_type_name (ret_type))
933933 g.write (' ' )
@@ -969,7 +969,7 @@ fn (mut g FlatGen) gen_fn_in_module(node flat.Node, module_name string) {
969969fn (mut g FlatGen) gen_export_wrapper_for_fn (node flat.Node, module_name string ) {
970970 export_name := g.export_fn_name_in_module (module_name, node.value) or { return }
971971 canonical_name := g.fn_c_name_in_module (module_name, node.value)
972- ret_type := g.tc. parse_type (node.typ )
972+ ret_type := g.fn_node_return_type (node, module_name )
973973 ret_ct := g.fn_return_type_name (ret_type)
974974 g.write (ret_ct)
975975 g.write (' ' )
@@ -1192,13 +1192,19 @@ fn (g &FlatGen) collect_test_harness_decl_ids(node flat.Node, mut ids []flat.Nod
11921192}
11931193
11941194fn (g &FlatGen) is_supported_test_fn_decl (node flat.Node) bool {
1195+ if node.generic_params.len > 0 {
1196+ return false
1197+ }
11951198 if g.test_fn_param_count (node) != 0 {
11961199 return false
11971200 }
11981201 return test_harness_fn_return_supported (g.tc.parse_type (node.typ))
11991202}
12001203
12011204fn (g &FlatGen) is_supported_test_hook_decl (node flat.Node) bool {
1205+ if node.generic_params.len > 0 {
1206+ return false
1207+ }
12021208 return g.test_fn_param_count (node) == 0 && g.tc.parse_type (node.typ) is types.Void
12031209}
12041210
@@ -3734,7 +3740,7 @@ fn (mut g FlatGen) forward_decls() {
37343740 forwarded[qfn] = true
37353741 g.tc.cur_file = cur_file
37363742 g.tc.cur_module = cur_module
3737- ret_type := g.tc. parse_type (node.typ )
3743+ ret_type := g.fn_node_return_type (node, cur_module )
37383744 g.write (g.fn_return_type_name (ret_type))
37393745 g.write (' ' )
37403746 g.write (qfn)
@@ -3906,6 +3912,80 @@ fn (mut g FlatGen) implicit_veb_ctx_type() types.Type {
39063912 return g.tc.parse_type ('mut Context' )
39073913}
39083914
3915+ fn (mut g FlatGen) fn_node_return_type (node flat.Node, module_name string ) types.Type {
3916+ for candidate in g.fn_node_signature_names (node, module_name) {
3917+ if rt := g.tc.fn_ret_types[candidate] {
3918+ return rt
3919+ }
3920+ }
3921+ if info := g.generic_receiver_method_call_info (node.value) {
3922+ return info.return_type
3923+ }
3924+ return g.tc.parse_type (node.typ)
3925+ }
3926+
3927+ fn (mut g FlatGen) fn_node_param_types (node flat.Node, module_name string ) []types.Type {
3928+ if g.fn_needs_implicit_veb_ctx (node) {
3929+ return []types.Type{}
3930+ }
3931+ mut explicit_params := 0
3932+ for i in 0 .. node.children_count {
3933+ if g.a.child_node (& node, i).kind == .param {
3934+ explicit_params++
3935+ }
3936+ }
3937+ for candidate in g.fn_node_signature_names (node, module_name) {
3938+ if params := g.tc.fn_param_types[candidate] {
3939+ if params.len == explicit_params {
3940+ return params
3941+ }
3942+ }
3943+ }
3944+ if info := g.generic_receiver_method_call_info (node.value) {
3945+ if info.params.len == explicit_params {
3946+ return info.params.clone ()
3947+ }
3948+ }
3949+ return []types.Type{}
3950+ }
3951+
3952+ fn (g &FlatGen) generic_receiver_method_call_info (name string ) ? types.CallInfo {
3953+ if ! name.contains ('.' ) {
3954+ return none
3955+ }
3956+ receiver := name.all_before_last ('.' )
3957+ if ! receiver.contains ('[' ) || ! receiver.contains (']' ) {
3958+ return none
3959+ }
3960+ return g.tc.resolve_generic_struct_method (receiver, name.all_after_last ('.' ))
3961+ }
3962+
3963+ fn (mut g FlatGen) fn_node_signature_names (node flat.Node, module_name string ) []string {
3964+ dotted_name := qualify_name_in_module (module_name, node.value)
3965+ cname := g.fn_c_name_in_module (module_name, node.value)
3966+ mut names := []string {}
3967+ if module_name.len > 0 && module_name != 'main' && module_name != 'builtin' {
3968+ names << dotted_name
3969+ names << c_name (dotted_name)
3970+ names << cname
3971+ names << node.value
3972+ names << c_name (node.value)
3973+ } else {
3974+ names << node.value
3975+ names << c_name (node.value)
3976+ names << dotted_name
3977+ names << c_name (dotted_name)
3978+ names << cname
3979+ }
3980+ mut deduped := []string {cap: names.len}
3981+ for name in names {
3982+ if name.len > 0 && name ! in deduped {
3983+ deduped << name
3984+ }
3985+ }
3986+ return deduped
3987+ }
3988+
39093989// write_fn_node_params writes fn node params output for c.
39103990fn (mut g FlatGen) write_fn_node_params (node flat.Node) {
39113991 mut params_len := 0
@@ -3923,16 +4003,26 @@ fn (mut g FlatGen) write_fn_node_params(node flat.Node) {
39234003 return
39244004 }
39254005 mut written := 0
4006+ mut param_idx := 0
39264007 mut implicit_ctx_written := false
39274008 insert_implicit_ctx_after_first := needs_implicit_ctx && g.fn_has_receiver_param (node)
4009+ typed_params := g.fn_node_param_types (node, g.tc.cur_module)
4010+ concrete_optional_params := g.is_specialized_generic_fn_node (node)
39284011 for i in 0 .. node.children_count {
39294012 param_id := g.a.child (& node, i)
39304013 p := g.a.node (param_id)
39314014 if p.kind != .param {
39324015 continue
39334016 }
3934- pt := g.tc.parse_type (p.typ)
3935- ct := if pt is types.ArrayFixed {
4017+ pt := if param_idx < typed_params.len {
4018+ typed_params[param_idx]
4019+ } else {
4020+ g.tc.parse_type (p.typ)
4021+ }
4022+ param_idx++
4023+ ct := if concrete_optional_params && (pt is types.OptionType || pt is types.ResultType ) {
4024+ g.concrete_optional_type_name (pt)
4025+ } else if pt is types.ArrayFixed {
39364026 '${g .tc .c_type (pt .elem_type )}*'
39374027 } else if pt is types.OptionType || pt is types.ResultType {
39384028 g.optional_type_name (pt)
@@ -3967,6 +4057,29 @@ fn (mut g FlatGen) write_fn_node_params(node flat.Node) {
39674057 }
39684058}
39694059
4060+ fn (g &FlatGen) is_specialized_generic_fn_node (node flat.Node) bool {
4061+ return node.value.contains ('[' ) || node.value.contains ('_T_' )
4062+ }
4063+
4064+ fn (mut g FlatGen) concrete_optional_type_name (t types.Type) string {
4065+ mut base_type := types.Type (types.void_)
4066+ if t is types.OptionType {
4067+ base_type = t.base_type
4068+ } else if t is types.ResultType {
4069+ base_type = t.base_type
4070+ } else {
4071+ return g.tc.c_type (t)
4072+ }
4073+ mut inner_ct := g.tc.c_type (base_type)
4074+ if inner_ct.starts_with ('fn_ptr:' ) {
4075+ inner_ct = g.resolve_fn_ptr_type (inner_ct)
4076+ }
4077+ safe_name := inner_ct.replace ('*' , 'ptr' ).replace (' ' , '_' )
4078+ opt_name := 'Optional_${safe_name }'
4079+ g.needed_optional_types[opt_name] = inner_ct
4080+ return opt_name
4081+ }
4082+
39704083fn (mut g FlatGen) write_implicit_veb_ctx_param () {
39714084 pt := g.implicit_veb_ctx_type ()
39724085 g.write (g.tc.c_type (pt))
0 commit comments