diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 3b569657f5..02d52d7078 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -522,8 +522,12 @@ pub fn (mut c Checker) struct_decl(mut decl ast.StructDecl) { c.check_valid_pascal_case(decl.name, 'struct name', decl.pos) } mut struct_sym := c.table.find_type(decl.name) or { ast.TypeSymbol{} } + mut has_generic_types := false if mut struct_sym.info is ast.Struct { for embed in decl.embeds { + if embed.typ.has_flag(.generic) { + has_generic_types = true + } embed_sym := c.table.get_type_symbol(embed.typ) if embed_sym.kind != .struct_ { c.error('`$embed_sym.name` is not a struct', embed.pos) @@ -541,6 +545,9 @@ pub fn (mut c Checker) struct_decl(mut decl ast.StructDecl) { } for i, field in decl.fields { c.ensure_type_exists(field.typ, field.type_pos) or { return } + if field.typ.has_flag(.generic) { + has_generic_types = true + } if decl.language == .v { c.check_valid_snake_case(field.name, 'field name', field.pos) } @@ -592,6 +599,10 @@ pub fn (mut c Checker) struct_decl(mut decl ast.StructDecl) { } } } + if decl.generic_types.len == 0 && has_generic_types { + c.error('generic struct declaration must specify the generic type names, e.g. Foo', + decl.pos) + } } } diff --git a/vlib/v/checker/tests/generics_struct_declaration_err.out b/vlib/v/checker/tests/generics_struct_declaration_err.out new file mode 100644 index 0000000000..bd3b2c3476 --- /dev/null +++ b/vlib/v/checker/tests/generics_struct_declaration_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/generics_struct_declaration_err.vv:5:1: error: generic struct declaration must specify the generic type names, e.g. Foo + 3 | } + 4 | + 5 | struct MyGenericChannelStruct { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 6 | GenericChannelStruct + 7 | msg string diff --git a/vlib/v/checker/tests/generics_struct_declaration_err.vv b/vlib/v/checker/tests/generics_struct_declaration_err.vv new file mode 100644 index 0000000000..4828ea315f --- /dev/null +++ b/vlib/v/checker/tests/generics_struct_declaration_err.vv @@ -0,0 +1,24 @@ +struct GenericChannelStruct { + ch chan T +} + +struct MyGenericChannelStruct { + GenericChannelStruct + msg string +} + +struct Simple { + msg string +} + +fn main() { + new_channel_struct() +} + +pub fn new_channel_struct() GenericChannelStruct { + d := GenericChannelStruct{ + ch: chan T{} + } + + return d +}