diff --git a/vlib/v/checker/interface.v b/vlib/v/checker/interface.v index 0e95f5722938fb..c4d6b849b956e9 100644 --- a/vlib/v/checker/interface.v +++ b/vlib/v/checker/interface.v @@ -141,6 +141,16 @@ fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) { } } } + } else if !method.return_type.has_option_or_result() { + ret_sym := c.table.sym(method.return_type) + if ret_sym.info is ast.ArrayFixed && !ret_sym.info.is_fn_ret { + c.cast_to_fixed_array_ret(method.return_type, ret_sym) + } else if ret_sym.info is ast.Alias { + parent_sym := c.table.sym(ret_sym.info.parent_type) + if parent_sym.info is ast.ArrayFixed && !parent_sym.info.is_fn_ret { + c.cast_to_fixed_array_ret(ret_sym.info.parent_type, parent_sym) + } + } } for j, param in method.params { if j == 0 && is_js { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 472b77af46aad6..23ea0a91badf44 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5473,12 +5473,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { } tmpvar := g.new_tmp_var() g.defer_return_tmp_var = tmpvar - mut ret_typ := g.typ(g.unwrap_generic(fn_ret_type)) - if fn_ret_type.has_flag(.generic) && fn_return_is_fixed_array { - ret_typ = '_v_${ret_typ}' - } else if sym.kind == .alias && fn_return_is_fixed_array { - ret_typ = '_v_' + g.typ((sym.info as ast.Alias).parent_type) - } + ret_typ := g.ret_typ(g.unwrap_generic(fn_ret_type)) if node.exprs.len == 1 { // `return fn_call_opt()` if (fn_return_is_option || fn_return_is_result) && node.exprs[0] is ast.CallExpr @@ -7661,7 +7656,7 @@ fn (mut g Gen) interface_table() string { for k, method_name in inter_methods { method := isym.find_method_with_generic_parent(method_name) or { continue } methodidx[method.name] = k - ret_styp := g.typ(method.return_type) + ret_styp := g.ret_typ(method.return_type) methods_struct_def.write_string('\t${ret_styp} (*_method_${c_fn_name(method.name)})(void* _') // the first param is the receiver, it's handled by `void*` above for i in 1 .. method.params.len { @@ -7847,7 +7842,7 @@ static inline __shared__${interface_name} ${shared_fn_name}(__shared__${cctype}* method_call = '${cctype}_${name}' // inline void Cat_speak_Interface_Animal_method_wrapper(Cat c) { return Cat_speak(*c); } iwpostfix := '_Interface_${interface_name}_method_wrapper' - methods_wrapper.write_string('static inline ${g.typ(method.return_type)} ${cctype}_${name}${iwpostfix}(') + methods_wrapper.write_string('static inline ${g.ret_typ(method.return_type)} ${cctype}_${name}${iwpostfix}(') params_start_pos := g.out.len mut params := method.params.clone() // hack to mutate typ @@ -8036,6 +8031,23 @@ fn (mut g Gen) trace_last_lines(fbase string, params TraceLastLinesParams) { println('`'.repeat(80)) } +// ret_type generates proper type name for return type context +pub fn (mut g Gen) ret_typ(typ ast.Type) string { + mut ret_styp := g.typ(typ) + if !typ.has_option_or_result() { + ret_sym := g.table.sym(typ) + if ret_sym.info is ast.ArrayFixed && !ret_sym.info.is_fn_ret { + ret_styp = '_v_${ret_styp}' + } else if ret_sym.info is ast.Alias { + unalias_sym := g.table.sym(ret_sym.info.parent_type) + if unalias_sym.info is ast.ArrayFixed && !unalias_sym.info.is_fn_ret { + ret_styp = '_v_${g.typ(ret_sym.info.parent_type)}' + } + } + } + return ret_styp +} + pub fn (mut g Gen) get_array_depth(el_typ ast.Type) int { typ := g.unwrap_generic(el_typ) sym := g.table.final_sym(typ) diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 67d44e9b456f65..cac6fdb31d1c88 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -225,21 +225,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) { } mut name := g.c_fn_name(node) - mut type_name := g.typ(g.unwrap_generic(node.return_type)) - - ret_sym := g.table.sym(g.unwrap_generic(node.return_type)) - if node.return_type.has_flag(.generic) && !node.return_type.has_option_or_result() - && ret_sym.kind == .array_fixed { - type_name = '_v_${type_name}' - } else if ret_sym.kind == .alias && !node.return_type.has_option_or_result() { - unalias_typ := g.table.unaliased_type(node.return_type) - unalias_sym := g.table.sym(unalias_typ) - if unalias_sym.kind == .array_fixed { - type_name = if !(unalias_sym.info as ast.ArrayFixed).is_fn_ret { '_v_' } else { '' } + - g.typ(unalias_typ) - } - } - + type_name := g.ret_typ(g.unwrap_generic(node.return_type)) if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__') && !node.is_main && node.name != 'str' { mut key := node.name diff --git a/vlib/v/tests/fns/interface_methods_fixed_arr_test.v b/vlib/v/tests/fns/interface_methods_fixed_arr_test.v new file mode 100644 index 00000000000000..fc0e28219cb7a4 --- /dev/null +++ b/vlib/v/tests/fns/interface_methods_fixed_arr_test.v @@ -0,0 +1,21 @@ +module main + +pub type Mat4 = [16]f32 + +interface IGameObject { + world_transform() Mat4 +} + +struct Foo implements IGameObject { +} + +fn (f Foo) world_transform() Mat4 { + return Mat4{} +} + +fn test_main() { + t := Foo{} + a := t.world_transform() + b := Mat4{} + assert a == b +}