1
0
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:
Louis Schmieder 2021-07-30 19:29:06 +02:00 committed by GitHub
parent a7c2aaf35b
commit 0bb587c8c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 3 deletions

View File

@ -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))
} }

View 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'

View File

@ -0,0 +1,8 @@
fn opt() ? {}
fn thing() ?string {
defer {
opt()
}
return 'ok'
}

View File

@ -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

View File

@ -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
}