cgen: fix optional void return error
parent
d4f0fe12ab
commit
514ee9d396
|
@ -1259,7 +1259,8 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
|||
c.error('too many arguments to return, current function does not return anything',
|
||||
return_stmt.pos)
|
||||
return
|
||||
} else if return_stmt.exprs.len == 0 && c.expected_type != table.void_type {
|
||||
} else if return_stmt.exprs.len == 0 && !(c.expected_type == table.void_type ||
|
||||
c.table.get_type_symbol(c.expected_type).kind == .void) {
|
||||
c.error('too few arguments to return', return_stmt.pos)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -380,7 +380,7 @@ fn (g &Gen) optional_type_text(styp, base string) string {
|
|||
string v_error;
|
||||
int ecode;
|
||||
byte data[sizeof($size)];
|
||||
} '
|
||||
}'
|
||||
return ret
|
||||
}
|
||||
|
||||
|
@ -2309,6 +2309,19 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|||
sym := g.table.get_type_symbol(g.fn_decl.return_type)
|
||||
fn_return_is_multi := sym.kind == .multi_return
|
||||
fn_return_is_optional := g.fn_decl.return_type.has_flag(.optional)
|
||||
|
||||
if node.exprs.len == 0 {
|
||||
if fn_return_is_optional {
|
||||
tmp := g.new_tmp_var()
|
||||
styp := g.typ(g.fn_decl.return_type)
|
||||
g.writeln('$styp $tmp;')
|
||||
g.writeln('${tmp}.ok = true;')
|
||||
g.writeln('return $tmp;')
|
||||
} else {
|
||||
g.writeln('return;')
|
||||
}
|
||||
return
|
||||
}
|
||||
// handle promoting none/error/function returning 'Option'
|
||||
if fn_return_is_optional {
|
||||
optional_none := node.exprs[0] is ast.None
|
||||
|
@ -2317,7 +2330,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|||
tmp := g.new_tmp_var()
|
||||
g.write('/*opt promotion*/ Option $tmp = ')
|
||||
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
||||
g.write(';')
|
||||
g.writeln(';')
|
||||
styp := g.typ(g.fn_decl.return_type)
|
||||
g.writeln('return *($styp*)&$tmp;')
|
||||
return
|
||||
|
|
|
@ -330,7 +330,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
|
|||
}
|
||||
if gen_or {
|
||||
g.or_block(tmp_opt, node.or_block, node.return_type)
|
||||
g.write('\n${cur_line}${tmp_opt}')
|
||||
g.write('\n\t${cur_line}${tmp_opt}')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -274,34 +274,6 @@ fn test_multi_return_opt() {
|
|||
}
|
||||
}
|
||||
*/
|
||||
fn foo() ? {
|
||||
return error('something')
|
||||
}
|
||||
|
||||
fn test_optional_void() {
|
||||
foo() or {
|
||||
println(err)
|
||||
assert err == 'something'
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fn bar() ? {
|
||||
return error('bar error')
|
||||
}
|
||||
|
||||
fn test_optional_void_only_question() {
|
||||
bar() or {
|
||||
println(err)
|
||||
assert err == 'bar error'
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fn test_optional_void_with_empty_or() {
|
||||
foo() or {}
|
||||
assert true
|
||||
}
|
||||
|
||||
fn test_optional_val_with_empty_or() {
|
||||
ret_none() or {}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
fn foo() ? {
|
||||
return error('something')
|
||||
}
|
||||
|
||||
fn test_optional_void() {
|
||||
foo() or {
|
||||
println(err)
|
||||
assert err == 'something'
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fn bar() ? {
|
||||
return error('bar error')
|
||||
}
|
||||
|
||||
fn test_optional_void_only_question() {
|
||||
bar() or {
|
||||
println(err)
|
||||
assert err == 'bar error'
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fn test_optional_void_with_empty_or() {
|
||||
foo() or {}
|
||||
assert true
|
||||
}
|
||||
|
||||
fn option_void(a int) ? {
|
||||
if a != 0 {
|
||||
return
|
||||
} else {
|
||||
return error('zero error')
|
||||
}
|
||||
}
|
||||
|
||||
fn test_optional_void_with_return() {
|
||||
option_void(0) or {
|
||||
println(err)
|
||||
assert err == 'zero error'
|
||||
return
|
||||
}
|
||||
option_void(-1) or {
|
||||
println(err)
|
||||
assert err == 'zero error'
|
||||
return
|
||||
}
|
||||
assert true
|
||||
}
|
Loading…
Reference in New Issue