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

checker: check generic interface declaration (#15108)

This commit is contained in:
yuyi 2022-07-18 06:36:37 +08:00 committed by GitHub
parent 706a922e0c
commit 5462d4aebf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 0 deletions

View File

@ -40,6 +40,18 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
embed.pos)
continue
}
// Ensure each generic type of the embed was declared in the interface'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 {
interface_generic_names := node_generic_names.join(', ')
c.error('generic type name `$name` is not mentioned in interface `$node.name<$interface_generic_names>`',
embed.pos)
}
}
}
isym_info := isym.info as ast.Interface
for f in isym_info.fields {
if !efnames_ds_info[f.name] {
@ -115,6 +127,18 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
}
if method.return_type.has_flag(.generic) {
has_generic_types = true
// Ensure each generic type of the method was declared in the interface's definition
if node.generic_types.len > 0 {
method_generic_names := c.table.generic_type_names(method.return_type)
node_generic_names := node.generic_types.map(c.table.type_to_str(it))
for name in method_generic_names {
if name !in node_generic_names {
interface_generic_names := node_generic_names.join(', ')
c.error('generic type name `$name` is not mentioned in interface `$node.name<$interface_generic_names>`',
method.return_type_pos)
}
}
}
}
for j, param in method.params {
if j == 0 && is_js {
@ -128,6 +152,18 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
c.error('invalid use of reserved type `$param.name` as a parameter name',
param.pos)
}
// Ensure each generic type of the method was declared in the interface's definition
if node.generic_types.len > 0 && param.typ.has_flag(.generic) {
method_generic_names := c.table.generic_type_names(param.typ)
node_generic_names := node.generic_types.map(c.table.type_to_str(it))
for name in method_generic_names {
if name !in node_generic_names {
interface_generic_names := node_generic_names.join(', ')
c.error('generic type name `$name` is not mentioned in interface `$node.name<$interface_generic_names>`',
param.type_pos)
}
}
}
if is_js {
ptyp := c.table.sym(param.typ)
if !ptyp.is_js_compatible() && !(j == method.params.len - 1

View File

@ -0,0 +1,21 @@
vlib/v/checker/tests/generics_interface_decl_no_mention_err.vv:4:2: error: generic type name `T` is not mentioned in interface `Foo<U>`
2 |
3 | interface Foo<U> {
4 | Bar<T>
| ~~~
5 | foo(u U, p P)
6 | bar(u U) []P
vlib/v/checker/tests/generics_interface_decl_no_mention_err.vv:5:13: error: generic type name `P` is not mentioned in interface `Foo<U>`
3 | interface Foo<U> {
4 | Bar<T>
5 | foo(u U, p P)
| ^
6 | bar(u U) []P
7 | }
vlib/v/checker/tests/generics_interface_decl_no_mention_err.vv:6:11: error: generic type name `P` is not mentioned in interface `Foo<U>`
4 | Bar<T>
5 | foo(u U, p P)
6 | bar(u U) []P
| ~~~
7 | }
8 |

View File

@ -0,0 +1,10 @@
fn main() {}
interface Foo<U> {
Bar<T>
foo(u U, p P)
bar(u U) []P
}
interface Bar<T> {
}