mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parent
22a79cfa1e
commit
6d399c5116
@ -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
|
||||
}
|
||||
|
@ -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{
|
||||
|
@ -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 {
|
||||
|
32
vlib/v/tests/struct_init_with_update_test.v
Normal file
32
vlib/v/tests/struct_init_with_update_test.v
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user