mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: fix defer ident handling & fix defer optional error message (#10975)
This commit is contained in:
parent
a7c2aaf35b
commit
0bb587c8c2
@ -3208,8 +3208,13 @@ pub fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type ast.Type) ast
|
|||||||
if expr is ast.CallExpr {
|
if expr is ast.CallExpr {
|
||||||
if expr.return_type.has_flag(.optional) {
|
if expr.return_type.has_flag(.optional) {
|
||||||
if expr.or_block.kind == .absent {
|
if expr.or_block.kind == .absent {
|
||||||
|
if c.inside_defer {
|
||||||
|
c.error('${expr.name}() returns an option, so it should have an `or {}` block at the end',
|
||||||
|
expr.pos)
|
||||||
|
} else {
|
||||||
c.error('${expr.name}() returns an option, so it should have either an `or {}` block, or `?` at the end',
|
c.error('${expr.name}() returns an option, so it should have either an `or {}` block, or `?` at the end',
|
||||||
expr.pos)
|
expr.pos)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
c.check_or_expr(expr.or_block, ret_type, expr.return_type.clear_flag(.optional))
|
c.check_or_expr(expr.or_block, ret_type, expr.return_type.clear_flag(.optional))
|
||||||
}
|
}
|
||||||
|
7
vlib/v/checker/tests/defer_optional.out
Normal file
7
vlib/v/checker/tests/defer_optional.out
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
vlib/v/checker/tests/defer_optional.vv:5:3: error: opt() returns an option, so it should have an `or {}` block at the end
|
||||||
|
3 | fn thing() ?string {
|
||||||
|
4 | defer {
|
||||||
|
5 | opt()
|
||||||
|
| ~~~~~
|
||||||
|
6 | }
|
||||||
|
7 | return 'ok'
|
8
vlib/v/checker/tests/defer_optional.vv
Normal file
8
vlib/v/checker/tests/defer_optional.vv
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fn opt() ? {}
|
||||||
|
|
||||||
|
fn thing() ?string {
|
||||||
|
defer {
|
||||||
|
opt()
|
||||||
|
}
|
||||||
|
return 'ok'
|
||||||
|
}
|
@ -4902,7 +4902,9 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
|||||||
// `tmp := foo(a, b, c); free(a); free(b); free(c); return tmp;`
|
// `tmp := foo(a, b, c); free(a); free(b); free(c); return tmp;`
|
||||||
// Save return value in a temp var so that all args (a,b,c) can be freed
|
// Save return value in a temp var so that all args (a,b,c) can be freed
|
||||||
// Don't use a tmp var if a variable is simply returned: `return x`
|
// Don't use a tmp var if a variable is simply returned: `return x`
|
||||||
if node.exprs[0] !is ast.Ident {
|
// Just in case of defer statements exists, that the return values cannot
|
||||||
|
// be modified.
|
||||||
|
if node.exprs[0] !is ast.Ident || use_tmp_var {
|
||||||
g.write('$ret_typ $tmpvar = ')
|
g.write('$ret_typ $tmpvar = ')
|
||||||
} else {
|
} else {
|
||||||
use_tmp_var = false
|
use_tmp_var = false
|
||||||
|
@ -142,3 +142,15 @@ fn test_defer_str_interpol() {
|
|||||||
t << '${t[0]}'
|
t << '${t[0]}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_defer_not_change_return_values() {
|
||||||
|
assert num() == 10
|
||||||
|
}
|
||||||
|
|
||||||
|
fn num() int {
|
||||||
|
mut ret := 10
|
||||||
|
defer {
|
||||||
|
ret = 20
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user