1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

parser, cgen: fix option variable error (fix #17460) (#17479)

This commit is contained in:
yuyi 2023-03-04 17:47:49 +08:00 committed by GitHub
parent 30c205ef2c
commit 6944d54257
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 3 deletions

View File

@ -103,8 +103,10 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
mut return_type := ast.void_type
is_decl := node.op == .decl_assign
g.assign_op = node.op
g.inside_assign = true
defer {
g.assign_op = .unknown
g.inside_assign = false
}
op := if is_decl { token.Kind.assign } else { node.op }
right_expr := node.right[0]
@ -597,7 +599,8 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
if val.is_auto_deref_var() {
g.write('*')
}
if var_type.has_flag(.option) || gen_or {
if (var_type.has_flag(.option) && val !in [ast.Ident, ast.SelectorExpr])
|| gen_or {
g.expr_with_opt_or_block(val, val_type, left, var_type)
} else if val is ast.ArrayInit {
g.array_init(val, c_name(ident.name))

View File

@ -120,6 +120,7 @@ mut:
inside_ternary int // ?: comma separated statements on a single line
inside_map_postfix bool // inside map++/-- postfix expr
inside_map_infix bool // inside map<</+=/-= infix expr
inside_assign bool
inside_map_index bool
inside_opt_or_res bool
inside_opt_data bool
@ -4123,7 +4124,7 @@ fn (mut g Gen) ident(node ast.Ident) {
styp := g.base_type(node.info.typ)
g.write('(*(${styp}*)${name}.data)')
}
if node.or_expr.kind != .absent {
if node.or_expr.kind != .absent && !(g.inside_assign && !g.is_assign_lhs) {
stmt_str := g.go_before_stmt(0).trim_space()
g.empty_line = true
g.or_block(name, node.or_expr, node.info.typ)

View File

@ -252,6 +252,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
} else if branch.cond is ast.IfGuardExpr {
mut var_name := guard_vars[i]
mut short_opt := false
g.left_is_opt = true
if var_name == '' {
short_opt = true // we don't need a further tmp, so use the one we'll get later
var_name = g.new_tmp_var()

View File

@ -113,7 +113,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
p.check(.decl_assign)
comments << p.eat_comments()
expr := p.expr(0)
if expr !in [ast.CallExpr, ast.IndexExpr, ast.PrefixExpr, ast.SelectorExpr] {
if expr !in [ast.CallExpr, ast.IndexExpr, ast.PrefixExpr, ast.SelectorExpr, ast.Ident] {
p.error_with_pos('if guard condition expression is illegal, it should return an Option',
expr.pos())
}

View File

@ -0,0 +1,26 @@
struct Foo {
name ?string
}
fn test_option_var() {
foo := Foo{}
other := foo.name
println(typeof(other).name)
if name := other {
println('with name: ${name}')
assert false
} else {
println('without name')
assert true
}
mut counter := 0
val := other or {
counter++
'default'
}
assert val == 'default'
assert counter == 1
}