Skip to content

Commit

Permalink
checker: allow embed of type alias anon struct
Browse files Browse the repository at this point in the history
  • Loading branch information
Delta456 committed Jul 24, 2024
1 parent f53ba61 commit 3bab5ef
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 7 deletions.
9 changes: 6 additions & 3 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -571,9 +571,12 @@ fn (mut c Checker) alias_type_decl(node ast.AliasTypeDecl) {
}
if parent_typ_sym.info.is_anon {
for field in parent_typ_sym.info.fields {
if c.table.final_sym(field.typ).kind != .struct_ {
c.error('cannot embed non-struct `${c.table.sym(field.typ).name}`',
field.type_pos)
field_sym := c.table.sym(field.typ)
if field_sym.info is ast.Alias {
if c.table.sym(field_sym.info.parent_type).kind != .struct_ {
c.error('cannot embed non-struct `${field_sym.name}`',
field.type_pos)
}
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion vlib/v/checker/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
}
for embed in node.embeds {
embed_sym := c.table.sym(embed.typ)
if embed_sym.kind != .struct_ {
if embed_sym.info is ast.Alias {
parent_sym := c.table.sym(embed_sym.info.parent_type)
if parent_sym.kind != .struct_ {
c.error('`${embed_sym.name}` (alias of `${parent_sym.name}`) is not a struct',
embed.pos)
}
} else if embed_sym.kind != .struct_ {
c.error('`${embed_sym.name}` is not a struct', embed.pos)
} else if (embed_sym.info as ast.Struct).is_heap && !embed.typ.is_ptr() {
struct_sym.info.is_heap = true
Expand Down
6 changes: 3 additions & 3 deletions vlib/v/checker/tests/struct_embed_invalid_type.out
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
vlib/v/checker/tests/struct_embed_invalid_type.vv:4:2: error: `Foo` is not a struct
2 |
vlib/v/checker/tests/struct_embed_invalid_type.vv:4:2: error: `Foo` (alias of `int`) is not a struct
2 |
3 | struct Bar {
4 | Foo
| ~~~
5 | }
5 | }
20 changes: 20 additions & 0 deletions vlib/v/tests/anon_struct_alias_type_decl_embed_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
type AnonStruct = struct {
a int
b int
c int
}

struct Abc {
AnonStruct
}

fn test_anon_struct_type_alias_decl_embed() {
abc := Abc{AnonStruct(struct {10, 20, 30})}
assert abc.a == 10
assert abc.b == 20
assert abc.c == 30

assert abc.AnonStruct.a == 10
assert abc.AnonStruct.b == 20
assert abc.AnonStruct.c == 30
}

0 comments on commit 3bab5ef

Please sign in to comment.