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

checker: fix struct init with update expr (fix #9472) (#15460)

This commit is contained in:
yuyi 2022-08-19 00:39:41 +08:00 committed by GitHub
parent 22a79cfa1e
commit 6d399c5116
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 14 deletions

View File

@ -563,11 +563,6 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
node.update_expr.pos())
}
}
if !node.update_expr.is_lvalue() {
// cgen will repeat `update_expr` for each field
// so enforce an lvalue for efficiency
c.error('expression is not an lvalue', node.update_expr.pos())
}
}
return node.typ
}

View File

@ -19,13 +19,6 @@ vlib/v/checker/tests/struct_init_update_type_err.vv:20:6: error: struct `Foo2` i
| ~~
21 | }
22 | _ = Foo{
vlib/v/checker/tests/struct_init_update_type_err.vv:23:6: error: expression is not an lvalue
21 | }
22 | _ = Foo{
23 | ...Foo{}
| ~~~~~
24 | }
25 | }
vlib/v/checker/tests/struct_init_update_type_err.vv:32:6: error: struct `Empty` is not compatible with struct `Foo`
30 | e := Empty{}
31 | _ = Foo{

View File

@ -8,6 +8,20 @@ import v.ast
const skip_struct_init = ['struct stat', 'struct addrinfo']
fn (mut g Gen) struct_init(node ast.StructInit) {
mut is_update_tmp_var := false
mut tmp_update_var := ''
if node.has_update_expr && !node.update_expr.is_lvalue() {
tmp_update_var = g.new_tmp_var()
is_update_tmp_var = true
s := g.go_before_stmt(0)
styp := g.typ(node.update_expr_type)
g.empty_line = true
g.write('$styp $tmp_update_var = ')
g.expr(node.update_expr)
g.writeln(';')
g.empty_line = false
g.write(s)
}
styp := g.typ(node.typ)
mut shared_styp := '' // only needed for shared x := St{...
if styp in c.skip_struct_init {
@ -167,8 +181,8 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
// unions thould have exactly one explicit initializer
continue
}
field_name := c_name(field.name)
if field.typ.has_flag(.optional) {
field_name := c_name(field.name)
g.write('.$field_name = {EMPTY_STRUCT_INITIALIZATION},')
initialized = true
continue
@ -177,7 +191,12 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
continue
}
if node.has_update_expr {
g.expr(node.update_expr)
g.write('.$field_name = ')
if is_update_tmp_var {
g.write(tmp_update_var)
} else {
g.expr(node.update_expr)
}
if node.update_expr_type.is_ptr() {
g.write('->')
} else {

View File

@ -0,0 +1,32 @@
module main
struct Author {
username string
name string
pass string
height int
age int
}
fn cool_author() Author {
return Author{
username: 'Terisback'
name: 'Bob'
pass: '123456'
height: 175
age: 18
}
}
fn test_struct_init_with_update_expr() {
mut o := Author{
...cool_author()
age: 21
}
println(o)
assert o.username == 'Terisback'
assert o.name == 'Bob'
assert o.pass == '123456'
assert o.height == 175
assert o.age == 21
}