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

checker: ensure expr is an lvalue with Struct{...expr (#8489)

This commit is contained in:
Nick Treleaven 2021-02-01 14:18:03 +00:00 committed by GitHub
parent d660f2cc6f
commit c537578481
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 12 deletions

View File

@ -680,12 +680,17 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
if struct_init.has_update_expr {
update_type := c.expr(struct_init.update_expr)
struct_init.update_expr_type = update_type
update_sym := c.table.get_type_symbol(update_type)
sym := c.table.get_type_symbol(struct_init.typ)
if update_sym.kind != .struct_ {
c.error('expected struct `$sym.name`, found `$update_sym.name`', struct_init.update_expr.position())
if c.table.type_kind(update_type) != .struct_ {
s := c.table.type_to_str(update_type)
c.error('expected struct, found `$s`', struct_init.update_expr.position())
} else if update_type != struct_init.typ {
sym := c.table.get_type_symbol(struct_init.typ)
update_sym := c.table.get_type_symbol(update_type)
c.error('expected struct `$sym.name`, found struct `$update_sym.name`', struct_init.update_expr.position())
} else if !struct_init.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', struct_init.update_expr.position())
}
}
return struct_init.typ

View File

@ -1,7 +1,28 @@
vlib/v/checker/tests/struct_init_update_type_err.vv:11:6: error: expected struct `Foo`, found `int`
9 | f3 := 2
vlib/v/checker/tests/struct_init_update_type_err.vv:11:6: error: expected struct, found `int`
9 | i := 2
10 | _ := Foo{
11 | ...f3
| ~~
11 | ...i
| ^
12 | name: 'f2'
13 | }
13 | }
vlib/v/checker/tests/struct_init_update_type_err.vv:16:6: error: expected struct, found `&int`
14 | p := &i
15 | _ = Foo{
16 | ...p
| ^
17 | }
18 | f2 := Foo2{}
vlib/v/checker/tests/struct_init_update_type_err.vv:20:6: error: expected struct `Foo`, found struct `Foo2`
18 | f2 := Foo2{}
19 | _ = Foo{
20 | ...f2
| ~~
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 | }

View File

@ -3,13 +3,24 @@ struct Foo {
age int
}
struct Foo2 {}
struct Foo2 {b bool}
fn main() {
f3 := 2
i := 2
_ := Foo{
...f3
...i
name: 'f2'
}
p := &i
_ = Foo{
...p
}
f2 := Foo2{}
_ = Foo{
...f2
}
_ = Foo{
...Foo{}
}
}