cgen: fix return with option on orexpr (#20728)

This commit is contained in:
Felipe Pena 2024-02-06 09:05:25 -03:00 committed by GitHub
parent a374d25420
commit e6570ddcf9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 37 additions and 6 deletions

View File

@ -6624,19 +6624,30 @@ fn (mut g Gen) gen_or_block_stmts(cvar_name string, cast_typ string, stmts []ast
is_array_fixed = expr_stmt.expr is ast.ArrayInit is_array_fixed = expr_stmt.expr is ast.ArrayInit
&& g.table.final_sym(return_type).kind == .array_fixed && g.table.final_sym(return_type).kind == .array_fixed
if !is_array_fixed { if !is_array_fixed {
g.write('*(${cast_typ}*) ${cvar_name}.data = ') if g.inside_return && !g.inside_struct_init
&& expr_stmt.expr is ast.CallExpr
&& return_type.has_option_or_result() {
g.write('${cvar_name} = ')
} else {
g.write('*(${cast_typ}*) ${cvar_name}.data = ')
}
} }
} else { } else {
g.write('${cvar_name} = ') g.write('${cvar_name} = ')
} }
if is_array_fixed { if is_array_fixed {
g.write('memcpy(${cvar_name}.data, (${cast_typ})') g.write('memcpy(${cvar_name}.data, (${cast_typ})')
} }
old_inside_opt_data := g.inside_opt_data // return expr or { fn_returns_option() }
g.inside_opt_data = true if is_option && g.inside_return && expr_stmt.expr is ast.CallExpr
g.expr_with_cast(expr_stmt.expr, expr_stmt.typ, return_type.clear_option_and_result()) && return_type.has_option_or_result() {
g.inside_opt_data = old_inside_opt_data g.expr_with_cast(expr_stmt.expr, expr_stmt.typ, return_type)
} else {
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 { if is_array_fixed {
g.write(', sizeof(${cast_typ}))') g.write(', sizeof(${cast_typ}))')
} }

View File

@ -0,0 +1,20 @@
fn find_startswith_string(a []string, search string) ?string {
for s in a {
if s.starts_with(search) {
return s
}
}
return none
}
fn find_any_startswith_string(a []string, b []string, search string) ?string {
// cannot convert 'struct _option_string' to 'struct string'
// V wants the or {} block to return a string, but find_startswith_string returns ?string
return find_startswith_string(a, search) or { find_startswith_string(b, search) }
}
fn test_main() {
deadbeef := find_any_startswith_string(['foobar', 'barfoo'], ['deadbeef', 'beefdead'],
'dead')
assert deadbeef or { panic('unreachable') } == 'deadbeef'
}