diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index 61b30ad5920307..67e7cb90bc426b 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -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[...]...)´ @@ -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 diff --git a/vlib/v/checker/tests/union_init_having_more_fields_err.out b/vlib/v/checker/tests/union_init_having_more_fields_err.out new file mode 100644 index 00000000000000..de7032398d5148 --- /dev/null +++ b/vlib/v/checker/tests/union_init_having_more_fields_err.out @@ -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 diff --git a/vlib/v/checker/tests/union_init_having_more_fields_err.vv b/vlib/v/checker/tests/union_init_having_more_fields_err.vv new file mode 100644 index 00000000000000..87b122edd02b89 --- /dev/null +++ b/vlib/v/checker/tests/union_init_having_more_fields_err.vv @@ -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 + } +}