checker: check that fns with return values, and matches, do return
parent
6271798ce3
commit
8c241cb745
|
@ -407,6 +407,8 @@ fn (mut m map) get_and_set(key string, zero voidptr) voidptr {
|
||||||
// Key not found, insert key with zero-value
|
// Key not found, insert key with zero-value
|
||||||
m.set(key, zero)
|
m.set(key, zero)
|
||||||
}
|
}
|
||||||
|
assert false
|
||||||
|
return voidptr(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If `key` matches the key of an element in the container,
|
// If `key` matches the key of an element in the container,
|
||||||
|
|
|
@ -325,6 +325,9 @@ fn (mut ch Channel) try_push_priv(src voidptr, no_block bool) ChanState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// this should not happen
|
||||||
|
assert false
|
||||||
|
return .success
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -494,8 +497,9 @@ fn (mut ch Channel) try_pop_priv(dest voidptr, no_block bool) ChanState {
|
||||||
dest2 = dest
|
dest2 = dest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return .success
|
break
|
||||||
}
|
}
|
||||||
|
return .success
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait `timeout` on any of `channels[i]` until one of them can push (`is_push[i] = true`) or pop (`is_push[i] = false`)
|
// Wait `timeout` on any of `channels[i]` until one of them can push (`is_push[i] = true`) or pop (`is_push[i] = false`)
|
||||||
|
|
|
@ -3357,8 +3357,8 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
|
||||||
c.match_exprs(mut node, cond_type_sym)
|
c.match_exprs(mut node, cond_type_sym)
|
||||||
c.expected_type = cond_type
|
c.expected_type = cond_type
|
||||||
mut ret_type := table.void_type
|
mut ret_type := table.void_type
|
||||||
mut require_return := false
|
mut nbranches_with_return := 0
|
||||||
mut branch_without_return := false
|
mut nbranches_without_return := 0
|
||||||
for branch in node.branches {
|
for branch in node.branches {
|
||||||
c.stmts(branch.stmts)
|
c.stmts(branch.stmts)
|
||||||
if node.is_expr && branch.stmts.len > 0 {
|
if node.is_expr && branch.stmts.len > 0 {
|
||||||
|
@ -3392,17 +3392,21 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
|
||||||
}
|
}
|
||||||
if has_return := c.has_return(branch.stmts) {
|
if has_return := c.has_return(branch.stmts) {
|
||||||
if has_return {
|
if has_return {
|
||||||
require_return = true
|
nbranches_with_return++
|
||||||
} else {
|
} else {
|
||||||
branch_without_return = true
|
nbranches_without_return++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if require_return && branch_without_return {
|
if nbranches_with_return > 0 {
|
||||||
c.returns = false
|
if nbranches_with_return == node.branches.len {
|
||||||
} else {
|
// an exhaustive match, and all branches returned
|
||||||
// if inner if branch has not covered all branches but this one
|
c.returns = true
|
||||||
c.returns = true
|
}
|
||||||
|
if nbranches_without_return > 0 {
|
||||||
|
// some of the branches did not return
|
||||||
|
c.returns = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if ret_type != table.void_type {
|
// if ret_type != table.void_type {
|
||||||
// node.is_expr = c.expected_type != table.void_type
|
// node.is_expr = c.expected_type != table.void_type
|
||||||
|
@ -3692,8 +3696,8 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||||
expr_required := c.expected_type != table.void_type
|
expr_required := c.expected_type != table.void_type
|
||||||
former_expected_type := c.expected_type
|
former_expected_type := c.expected_type
|
||||||
node.typ = table.void_type
|
node.typ = table.void_type
|
||||||
mut require_return := false
|
mut nbranches_with_return := 0
|
||||||
mut branch_without_return := false
|
mut nbranches_without_return := 0
|
||||||
mut should_skip := false // Whether the current branch should be skipped
|
mut should_skip := false // Whether the current branch should be skipped
|
||||||
mut found_branch := false // Whether a matching branch was found- skip the rest
|
mut found_branch := false // Whether a matching branch was found- skip the rest
|
||||||
for i in 0 .. node.branches.len {
|
for i in 0 .. node.branches.len {
|
||||||
|
@ -3859,17 +3863,25 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||||
// Also check for returns inside a comp.if's statements, even if its contents aren't parsed
|
// Also check for returns inside a comp.if's statements, even if its contents aren't parsed
|
||||||
if has_return := c.has_return(branch.stmts) {
|
if has_return := c.has_return(branch.stmts) {
|
||||||
if has_return {
|
if has_return {
|
||||||
require_return = true
|
nbranches_with_return++
|
||||||
} else {
|
} else {
|
||||||
branch_without_return = true
|
nbranches_without_return++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if require_return && (!node.has_else || branch_without_return) {
|
if nbranches_with_return > 0 {
|
||||||
c.returns = false
|
if nbranches_with_return == node.branches.len {
|
||||||
} else {
|
// if/else... where all branches returned
|
||||||
// if inner if branch has not covered all branches but this one
|
c.returns = true
|
||||||
c.returns = true
|
}
|
||||||
|
if !node.has_else {
|
||||||
|
// `if cond { return ... }` means that when cond is false, execution continues
|
||||||
|
c.returns = false
|
||||||
|
}
|
||||||
|
if nbranches_without_return > 0 {
|
||||||
|
// some of the branches did not return
|
||||||
|
c.returns = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if only untyped literals were given default to int/f64
|
// if only untyped literals were given default to int/f64
|
||||||
if node.typ == table.any_int_type {
|
if node.typ == table.any_int_type {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
vlib/v/checker/tests/return_missing_match_simple.vv:1:1: error: missing return at end of function `h`
|
||||||
|
1 | fn h() int {
|
||||||
|
| ~~~~~~~~~~
|
||||||
|
2 | a := 1
|
||||||
|
3 | match a {
|
|
@ -0,0 +1,12 @@
|
||||||
|
fn h() int {
|
||||||
|
a := 1
|
||||||
|
match a {
|
||||||
|
else { println('abc') }
|
||||||
|
}
|
||||||
|
println('hello')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
d := h()
|
||||||
|
println('h returned: $d')
|
||||||
|
}
|
|
@ -500,6 +500,7 @@ pub fn (mut s Scanner) buffer_scan() token.Token {
|
||||||
}
|
}
|
||||||
return s.all_tokens[cidx]
|
return s.all_tokens[cidx]
|
||||||
}
|
}
|
||||||
|
return s.new_token(.eof, '', 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
|
Loading…
Reference in New Issue