From eed496d0bcd2a5171bbcecc9af5a2764b95891ca Mon Sep 17 00:00:00 2001 From: yuyi Date: Sun, 17 Jul 2022 23:09:15 +0800 Subject: [PATCH] checker: check generic struct declaration (#15106) --- vlib/v/checker/struct.v | 24 +++++++++++++++++++ .../generics_struct_decl_no_mention_err.out | 14 +++++++++++ .../generics_struct_decl_no_mention_err.vv | 10 ++++++++ 3 files changed, 48 insertions(+) create mode 100644 vlib/v/checker/tests/generics_struct_decl_no_mention_err.out create mode 100644 vlib/v/checker/tests/generics_struct_decl_no_mention_err.vv diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index 4ef9b675f5..40f298be5d 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -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', diff --git a/vlib/v/checker/tests/generics_struct_decl_no_mention_err.out b/vlib/v/checker/tests/generics_struct_decl_no_mention_err.out new file mode 100644 index 0000000000..163688e135 --- /dev/null +++ b/vlib/v/checker/tests/generics_struct_decl_no_mention_err.out @@ -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` + 2 | + 3 | struct Foo { + 4 | Bar + | ~~~~~~ + 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` + 4 | Bar + 5 | foo U + 6 | bar P + | ^ + 7 | } + 8 | diff --git a/vlib/v/checker/tests/generics_struct_decl_no_mention_err.vv b/vlib/v/checker/tests/generics_struct_decl_no_mention_err.vv new file mode 100644 index 0000000000..b2573ca46c --- /dev/null +++ b/vlib/v/checker/tests/generics_struct_decl_no_mention_err.vv @@ -0,0 +1,10 @@ +fn main() {} + +struct Foo { + Bar + foo U + bar P +} + +struct Bar { +}