mirror of
https://github.com/vlang/v.git
synced 2025-09-17 19:36:35 -04:00
cgen: fix fixed array handling, on generic result return, and on or block (#20492)
This commit is contained in:
parent
554f21a29c
commit
0c4611fa4c
@ -4965,7 +4965,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
||||
fn_return_is_multi := sym.kind == .multi_return
|
||||
fn_return_is_option := fn_ret_type.has_flag(.option)
|
||||
fn_return_is_result := fn_ret_type.has_flag(.result)
|
||||
fn_return_is_fixed_array := sym.is_array_fixed() && !fn_ret_type.has_flag(.option)
|
||||
fn_return_is_fixed_array := sym.is_array_fixed() && !fn_ret_type.has_option_or_result()
|
||||
|
||||
mut has_semicolon := false
|
||||
if node.exprs.len == 0 {
|
||||
@ -5306,7 +5306,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
||||
if g.fn_decl.return_type.has_flag(.option) {
|
||||
g.expr_with_opt(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
||||
} else {
|
||||
if fn_return_is_fixed_array && !node.types[0].has_flag(.option) {
|
||||
if fn_return_is_fixed_array && !node.types[0].has_option_or_result() {
|
||||
g.writeln('{0};')
|
||||
if node.exprs[0] is ast.Ident {
|
||||
typ := if expr0.is_auto_deref_var() {
|
||||
@ -6394,15 +6394,27 @@ fn (mut g Gen) gen_or_block_stmts(cvar_name string, cast_typ string, stmts []ast
|
||||
g.writeln(';')
|
||||
g.stmt_path_pos.delete_last()
|
||||
} else {
|
||||
mut is_array_fixed := false
|
||||
if is_option {
|
||||
g.write('*(${cast_typ}*) ${cvar_name}.data = ')
|
||||
is_array_fixed = expr_stmt.expr is ast.ArrayInit
|
||||
&& g.table.final_sym(return_type).kind == .array_fixed
|
||||
if !is_array_fixed {
|
||||
g.write('*(${cast_typ}*) ${cvar_name}.data = ')
|
||||
}
|
||||
} else {
|
||||
g.write('${cvar_name} = ')
|
||||
}
|
||||
|
||||
if is_array_fixed {
|
||||
g.write('memcpy(${cvar_name}.data, (${cast_typ})')
|
||||
}
|
||||
old_inside_opt_data := g.inside_opt_data
|
||||
g.inside_opt_data = true
|
||||
g.expr_with_cast(expr_stmt.expr, expr_stmt.typ, return_type.clear_option_and_result())
|
||||
g.inside_opt_data = old_inside_opt_data
|
||||
if is_array_fixed {
|
||||
g.write(', sizeof(${cast_typ}))')
|
||||
}
|
||||
g.writeln(';')
|
||||
g.stmt_path_pos.delete_last()
|
||||
}
|
||||
|
@ -76,8 +76,8 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
|
||||
g.inside_opt_or_res = old_inside_opt_or_res
|
||||
}
|
||||
g.write(')')
|
||||
if (g.inside_assign || g.expected_fixed_arr) && !expr_type.has_flag(.option)
|
||||
&& g.table.type_kind(expr_type) == .array_fixed {
|
||||
if (g.inside_assign || g.expected_fixed_arr) && !expr_type.has_option_or_result()
|
||||
&& g.table.final_sym(expr_type).kind == .array_fixed {
|
||||
g.write('.ret_arr')
|
||||
}
|
||||
}
|
||||
@ -121,7 +121,7 @@ fn (mut g Gen) dump_expr_definitions() {
|
||||
g.go_back(str_tdef.len)
|
||||
dump_typedefs['typedef ${str_tdef};'] = true
|
||||
str_dumparg_ret_type = str_dumparg_type
|
||||
} else if !typ.has_flag(.option) && dump_sym.is_array_fixed() {
|
||||
} else if !typ.has_option_or_result() && dump_sym.is_array_fixed() {
|
||||
match dump_sym.kind {
|
||||
.array_fixed {
|
||||
if (dump_sym.info as ast.ArrayFixed).is_fn_ret {
|
||||
|
@ -228,10 +228,10 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
|
||||
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_flag(.option)
|
||||
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_flag(.option) {
|
||||
} 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 {
|
||||
@ -1606,8 +1606,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||
g.write(', ${array_depth}')
|
||||
}
|
||||
g.write(')')
|
||||
if node.return_type != 0 && !node.return_type.has_flag(.option)
|
||||
&& !node.return_type.has_flag(.result)
|
||||
if node.return_type != 0 && !node.return_type.has_option_or_result()
|
||||
&& g.table.final_sym(node.return_type).kind == .array_fixed {
|
||||
// it's non-option fixed array, requires accessing .ret_arr member to get the array
|
||||
g.write('.ret_arr')
|
||||
@ -1946,8 +1945,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||
if name != '&' {
|
||||
g.write(')')
|
||||
}
|
||||
if node.return_type != 0 && !node.return_type.has_flag(.option)
|
||||
&& !node.return_type.has_flag(.result)
|
||||
if node.return_type != 0 && !node.return_type.has_option_or_result()
|
||||
&& g.table.final_sym(node.return_type).kind == .array_fixed {
|
||||
// it's non-option fixed array, requires accessing .ret_arr member to get the array
|
||||
g.write('.ret_arr')
|
||||
|
@ -808,7 +808,7 @@ fn (mut g Gen) infix_expr_arithmetic_op(node ast.InfixExpr) {
|
||||
}
|
||||
g.write(')')
|
||||
|
||||
if left.typ != 0 && !left.typ.has_flag(.option) && !left.typ.has_flag(.result)
|
||||
if left.typ != 0 && !left.typ.has_option_or_result()
|
||||
&& g.table.final_sym(left.typ).kind == .array_fixed {
|
||||
// it's non-option fixed array, requires accessing .ret_arr member to get the array
|
||||
g.write('.ret_arr')
|
||||
|
@ -2,9 +2,20 @@ fn example[T]() ?T {
|
||||
return T{}
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
fn test_option() {
|
||||
dump(example[[1]int]())
|
||||
|
||||
a := example[[1]int]()
|
||||
assert a? == [0]!
|
||||
}
|
||||
|
||||
fn example2[T]() !T {
|
||||
return T{}
|
||||
}
|
||||
|
||||
fn test_result() {
|
||||
dump(example2[[1]int]()!)
|
||||
|
||||
a := example2[[1]int]()!
|
||||
assert a == [0]!
|
||||
}
|
||||
|
43
vlib/v/tests/option_or_result_fixed_arr_test.v
Normal file
43
vlib/v/tests/option_or_result_fixed_arr_test.v
Normal file
@ -0,0 +1,43 @@
|
||||
type Abc = [2]int
|
||||
|
||||
// option
|
||||
fn a() ?Abc {
|
||||
return [1, 2]!
|
||||
}
|
||||
|
||||
fn b() ?Abc {
|
||||
return none
|
||||
}
|
||||
|
||||
// result
|
||||
fn aa() !Abc {
|
||||
return [1, 2]!
|
||||
}
|
||||
|
||||
fn bb() !Abc {
|
||||
return error('b')
|
||||
}
|
||||
|
||||
fn test_option() {
|
||||
var_a := dump(a()?)
|
||||
var_b := Abc([1, 2]!)
|
||||
assert var_a == var_b
|
||||
}
|
||||
|
||||
fn test_result() {
|
||||
var_aa := dump(aa()!)
|
||||
var_bb := Abc([1, 2]!)
|
||||
assert var_aa == var_bb
|
||||
}
|
||||
|
||||
fn test_opt_block() {
|
||||
var_a := b() or { [0, 0]! }
|
||||
dump(var_a)
|
||||
assert var_a == Abc([0, 0]!)
|
||||
}
|
||||
|
||||
fn test_res_block() {
|
||||
var_a := bb() or { [0, 0]! }
|
||||
dump(var_a)
|
||||
assert var_a == Abc([0, 0]!)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user