checker: check generic struct declaration (fix #9974) (#9978)

pull/9976/head^2
yuyi 2021-05-04 00:47:02 +08:00 committed by GitHub
parent 0fa9a648ae
commit 035fd052d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 0 deletions

View File

@ -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<T>',
decl.pos)
}
}
}

View File

@ -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<T>
3 | }
4 |
5 | struct MyGenericChannelStruct {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 | GenericChannelStruct<T>
7 | msg string

View File

@ -0,0 +1,24 @@
struct GenericChannelStruct<T> {
ch chan T
}
struct MyGenericChannelStruct {
GenericChannelStruct<T>
msg string
}
struct Simple {
msg string
}
fn main() {
new_channel_struct<Simple>()
}
pub fn new_channel_struct<T>() GenericChannelStruct<T> {
d := GenericChannelStruct{
ch: chan T{}
}
return d
}