1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: check generic struct declaration (#15106)

This commit is contained in:
yuyi 2022-07-17 23:09:15 +08:00 committed by GitHub
parent 368cccb059
commit eed496d0bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 0 deletions

View File

@ -24,6 +24,18 @@ pub fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
struct_sym.info.is_heap = true
}
}
// Ensure each generic type of the embed was declared in the struct's definition
if node.generic_types.len > 0 && embed.typ.has_flag(.generic) {
embed_generic_names := c.table.generic_type_names(embed.typ)
node_generic_names := node.generic_types.map(c.table.type_to_str(it))
for name in embed_generic_names {
if name !in node_generic_names {
struct_generic_names := node_generic_names.join(', ')
c.error('generic type name `$name` is not mentioned in struct `$node.name<$struct_generic_names>`',
embed.pos)
}
}
}
}
if struct_sym.info.is_minify {
node.fields.sort_with_compare(minify_sort_fn)
@ -122,6 +134,18 @@ pub fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
}
}
}
// Ensure each generic type of the field was declared in the struct's definition
if node.generic_types.len > 0 && field.typ.has_flag(.generic) {
field_generic_names := c.table.generic_type_names(field.typ)
node_generic_names := node.generic_types.map(c.table.type_to_str(it))
for name in field_generic_names {
if name !in node_generic_names {
struct_generic_names := node_generic_names.join(', ')
c.error('generic type name `$name` is not mentioned in struct `$node.name<$struct_generic_names>`',
field.type_pos)
}
}
}
}
if node.generic_types.len == 0 && has_generic_types {
c.error('generic struct declaration must specify the generic type names, e.g. Foo<T>',

View File

@ -0,0 +1,14 @@
vlib/v/checker/tests/generics_struct_decl_no_mention_err.vv:4:2: error: generic type name `T` is not mentioned in struct `Foo<U>`
2 |
3 | struct Foo<U> {
4 | Bar<T>
| ~~~~~~
5 | foo U
6 | bar P
vlib/v/checker/tests/generics_struct_decl_no_mention_err.vv:6:6: error: generic type name `P` is not mentioned in struct `Foo<U>`
4 | Bar<T>
5 | foo U
6 | bar P
| ^
7 | }
8 |

View File

@ -0,0 +1,10 @@
fn main() {}
struct Foo<U> {
Bar<T>
foo U
bar P
}
struct Bar<T> {
}