Skip to content

Commit

Permalink
checker: restrict multiple union fields initialised at once with a ni…
Browse files Browse the repository at this point in the history
…cer checker error, instead of producing an enigmatic error at cgen time (#22196)
  • Loading branch information
Delta456 authored Sep 11, 2024
1 parent 6aeef5e commit 3ee2732
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
22 changes: 22 additions & 0 deletions vlib/v/checker/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
c.cur_struct_concrete_types = old_cur_struct_concrete_types
}
}
if struct_sym.info.is_union && node.init_fields.len > 1 {
c.error('union `${struct_sym.name}` can have only one field initialised',
node.pos)
}
} else if struct_sym.info is ast.Alias {
parent_sym := c.table.sym(struct_sym.info.parent_type)
// e.g. ´x := MyMapAlias{}´, should be a cast to alias type ´x := MyMapAlias(map[...]...)´
Expand Down Expand Up @@ -973,6 +977,24 @@ fn (mut c Checker) check_uninitialized_struct_fields_and_embeds(node ast.StructI
}

for embed in info.embeds {
embed_sym := c.table.sym(embed)
if embed_sym.info is ast.Struct {
if embed_sym.info.is_union {
mut embed_union_fields := c.table.struct_fields(embed_sym)
mut found := false
for init_field in inited_fields {
for union_field in embed_union_fields {
if init_field == union_field.name && found {
c.error('embed union `${embed_sym.name}` can have only one field initialised',
node.pos)
}
if init_field == union_field.name {
found = true
}
}
}
}
}
mut zero_struct_init := ast.StructInit{
pos: node.pos
typ: embed
Expand Down
14 changes: 14 additions & 0 deletions vlib/v/checker/tests/union_init_having_more_fields_err.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
vlib/v/checker/tests/union_init_having_more_fields_err.vv:23:7: error: embed union `Head` can have only one field initialised
21 |
22 | fn union_embed__having_more_fields_used() {
23 | _ := Message{
| ~~~~~~~~
24 | from: 1
25 | src: 1
vlib/v/checker/tests/union_init_having_more_fields_err.vv:30:7: error: union `Head` can have only one field initialised
28 |
29 | fn union_having_more_fields_used() {
30 | _ := Head{
| ~~~~~
31 | from: 1
32 | src: 1
34 changes: 34 additions & 0 deletions vlib/v/checker/tests/union_init_having_more_fields_err.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
pub struct Lines {
pub:
from u8
to u8
dst u8
src u8
}

pub union Head {
Lines
pub:
serial [3]u8
}

pub struct Message {
Head
pub:
cmd u8
payload []u8
}

fn union_embed__having_more_fields_used() {
_ := Message{
from: 1
src: 1
}
}

fn union_having_more_fields_used() {
_ := Head{
from: 1
src: 1
}
}

0 comments on commit 3ee2732

Please sign in to comment.