parser: fix non-void optional fn missing return value (fix #5736) (#5741)

pull/5723/head
yuyi 2020-07-08 22:01:17 +08:00 committed by GitHub
parent ec82fa77c5
commit 64e9bdc213
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 13 deletions

View File

@ -222,7 +222,6 @@ pub struct FnDecl {
pub: pub:
name string name string
mod string mod string
stmts []Stmt
args []table.Arg args []table.Arg
is_deprecated bool is_deprecated bool
is_pub bool is_pub bool
@ -242,6 +241,7 @@ pub:
file string file string
is_generic bool is_generic bool
pub mut: pub mut:
stmts []Stmt
return_type table.Type return_type table.Type
} }

View File

@ -1899,7 +1899,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
// node.typ = c.check_expr_opt_call(node.expr, table.void_type) // node.typ = c.check_expr_opt_call(node.expr, table.void_type)
} }
ast.FnDecl { ast.FnDecl {
c.fn_decl(node) c.fn_decl(mut node)
} }
ast.ForCStmt { ast.ForCStmt {
c.in_for_count++ c.in_for_count++
@ -2988,14 +2988,14 @@ fn (c &Checker) fetch_and_verify_orm_fields(info table.Struct, pos token.Positio
return fields return fields
} }
fn (mut c Checker) fn_decl(node ast.FnDecl) { fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
if node.is_generic && c.cur_generic_type == 0 { // need the cur_generic_type check to avoid inf. recursion if node.is_generic && c.cur_generic_type == 0 { // need the cur_generic_type check to avoid inf. recursion
// loop thru each generic type and generate a function // loop thru each generic type and generate a function
for gen_type in c.table.fn_gen_types[node.name] { for gen_type in c.table.fn_gen_types[node.name] {
c.cur_generic_type = gen_type c.cur_generic_type = gen_type
// sym:=c.table.get_type_symbol(gen_type) // sym:=c.table.get_type_symbol(gen_type)
// println('\ncalling check for $node.name for type $sym.name') // println('\ncalling check for $node.name for type $sym.name')
c.fn_decl(node) c.fn_decl(mut node)
} }
c.cur_generic_type = 0 c.cur_generic_type = 0
return return
@ -3046,7 +3046,24 @@ fn (mut c Checker) fn_decl(node ast.FnDecl) {
} }
} }
c.expected_type = table.void_type c.expected_type = table.void_type
c.cur_fn = &node c.cur_fn = node
// Add return if `fn(...) ? {...}` have no return at end
if node.return_type != table.void_type && node.return_type.has_flag(.optional) &&
(node.stmts.len == 0 || node.stmts[node.stmts.len - 1] !is ast.Return) {
sym := c.table.get_type_symbol(node.return_type)
if sym.kind == .void {
node.stmts << ast.Return{
pos: node.pos
}
} else {
node.stmts << ast.Return{
pos: node.pos
exprs: [ast.Expr(ast.None{pos: node.pos})]
}
}
}
c.stmts(node.stmts) c.stmts(node.stmts)
if node.language == .v && !node.no_body && if node.language == .v && !node.no_body &&
node.return_type != table.void_type && !c.returns && node.return_type != table.void_type && !c.returns &&

View File

@ -284,14 +284,6 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
body_start_pos := p.peek_tok.position() body_start_pos := p.peek_tok.position()
if p.tok.kind == .lcbr { if p.tok.kind == .lcbr {
stmts = p.parse_block_no_scope(true) stmts = p.parse_block_no_scope(true)
// Add return if `fn(...) ? {...}` have no return at end
if return_type != table.void_type &&
p.table.get_type_symbol(return_type).kind == .void && return_type.has_flag(.optional) &&
(stmts.len == 0 || stmts[stmts.len - 1] !is ast.Return) {
stmts << ast.Return{
pos: p.tok.position()
}
}
} }
p.close_scope() p.close_scope()
if !no_body && are_args_type_only { if !no_body && are_args_type_only {

View File

@ -316,3 +316,15 @@ fn test_option_void_return_types_of_anon_fn_in_struct() {
} }
} }
fn get_string(param bool) ?string {
if param {
return 'Hello World'
}
}
fn test_option_auto_add_return_none() {
r := get_string(false) or {
'test'
}
assert r == 'test'
}