cgen: fix implicit the optional return value to have .ok = true, in anon `fn()?{}`

pull/8386/head
Delyan Angelov 2021-01-28 02:26:02 +02:00
parent a8f1824e51
commit dceb63b9df
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
2 changed files with 33 additions and 1 deletions

View File

@ -183,7 +183,14 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl, skip bool) {
default_expr := g.type_default(it.return_type)
// TODO: perf?
if default_expr == '{0}' {
if it.return_type.idx() == 1 && it.return_type.has_flag(.optional) {
// The default return for anonymous functions that return `?,
// should have .ok = true set, otherwise calling them with
// optfn() or { panic(err) } will cause a panic:
g.writeln('\treturn (Option_void){.ok = true};')
} else {
g.writeln('\treturn ($type_name)$default_expr;')
}
} else {
g.writeln('\treturn $default_expr;')
}

View File

@ -0,0 +1,25 @@
type FnCb = fn (a string, b int) ?
fn test_calling_an_anon_function_returning_question() {
create_and_call_anon_function() or { panic(err) }
}
fn create_and_call_anon_function() ? {
x := fn (a string, b int) ? {
println('test')
// NB: the anon function does NOT return explicitly,
// so V should generate an implicit "OK" value and
// return it. Previously, it created an implicit optional
// filled with 0s => .ok was false, and that was treated
// as a failure, triggering or blocks.
}
should_not_call_block(x) ?
assert true
}
fn should_not_call_block(func FnCb) ? {
func('abc', 123) or {
println('this should NOT be called')
assert false
}
}