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:
parent
706a922e0c
commit
5462d4aebf
@ -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
|
||||
|
@ -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 |
|
@ -0,0 +1,10 @@
|
||||
fn main() {}
|
||||
|
||||
interface Foo<U> {
|
||||
Bar<T>
|
||||
foo(u U, p P)
|
||||
bar(u U) []P
|
||||
}
|
||||
|
||||
interface Bar<T> {
|
||||
}
|
Loading…
Reference in New Issue
Block a user