mirror of
https://github.com/vlang/v.git
synced 2025-09-14 01:47:30 -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 {
|
for j, param in method.params {
|
||||||
if j == 0 && is_js {
|
if j == 0 && is_js {
|
||||||
|
@ -5473,12 +5473,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
|||||||
}
|
}
|
||||||
tmpvar := g.new_tmp_var()
|
tmpvar := g.new_tmp_var()
|
||||||
g.defer_return_tmp_var = tmpvar
|
g.defer_return_tmp_var = tmpvar
|
||||||
mut ret_typ := g.typ(g.unwrap_generic(fn_ret_type))
|
ret_typ := g.ret_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)
|
|
||||||
}
|
|
||||||
if node.exprs.len == 1 {
|
if node.exprs.len == 1 {
|
||||||
// `return fn_call_opt()`
|
// `return fn_call_opt()`
|
||||||
if (fn_return_is_option || fn_return_is_result) && node.exprs[0] is ast.CallExpr
|
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 {
|
for k, method_name in inter_methods {
|
||||||
method := isym.find_method_with_generic_parent(method_name) or { continue }
|
method := isym.find_method_with_generic_parent(method_name) or { continue }
|
||||||
methodidx[method.name] = k
|
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* _')
|
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
|
// the first param is the receiver, it's handled by `void*` above
|
||||||
for i in 1 .. method.params.len {
|
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}'
|
method_call = '${cctype}_${name}'
|
||||||
// inline void Cat_speak_Interface_Animal_method_wrapper(Cat c) { return Cat_speak(*c); }
|
// inline void Cat_speak_Interface_Animal_method_wrapper(Cat c) { return Cat_speak(*c); }
|
||||||
iwpostfix := '_Interface_${interface_name}_method_wrapper'
|
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
|
params_start_pos := g.out.len
|
||||||
mut params := method.params.clone()
|
mut params := method.params.clone()
|
||||||
// hack to mutate typ
|
// hack to mutate typ
|
||||||
@ -8036,6 +8031,23 @@ fn (mut g Gen) trace_last_lines(fbase string, params TraceLastLinesParams) {
|
|||||||
println('`'.repeat(80))
|
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 {
|
pub fn (mut g Gen) get_array_depth(el_typ ast.Type) int {
|
||||||
typ := g.unwrap_generic(el_typ)
|
typ := g.unwrap_generic(el_typ)
|
||||||
sym := g.table.final_sym(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 name := g.c_fn_name(node)
|
||||||
mut type_name := g.typ(g.unwrap_generic(node.return_type))
|
type_name := g.ret_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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__') && !node.is_main
|
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__') && !node.is_main
|
||||||
&& node.name != 'str' {
|
&& node.name != 'str' {
|
||||||
mut key := node.name
|
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