mirror of
https://github.com/vlang/v.git
synced 2025-09-13 09:25:45 -04:00
cgen, checker: fix array fixed return type for interface methods (#22320)
This commit is contained in:
parent
861bbe68f2
commit
1cac0c3ce1
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
21
vlib/v/tests/fns/interface_methods_fixed_arr_test.v
Normal file
21
vlib/v/tests/fns/interface_methods_fixed_arr_test.v
Normal file
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user