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

checker: check generic interface declaration (#15047)

This commit is contained in:
yuyi 2022-07-13 14:43:54 +08:00 committed by GitHub
parent 28fd17654e
commit 7594157deb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 0 deletions

View File

@ -11,6 +11,7 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
mut decl_sym := c.table.sym(node.typ)
is_js := node.language == .js
if mut decl_sym.info is ast.Interface {
mut has_generic_types := false
if node.embeds.len > 0 {
all_embeds := c.expand_iface_embeds(node, 0, node.embeds)
// eprintln('> node.name: $node.name | node.embeds.len: $node.embeds.len | all_embeds: $all_embeds.len')
@ -31,6 +32,9 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
}
for embed in all_embeds {
isym := c.table.sym(embed.typ)
if embed.typ.has_flag(.generic) {
has_generic_types = true
}
if isym.kind != .interface_ {
c.error('interface `$node.name` tries to embed `$isym.name`, but `$isym.name` is not an interface, but `$isym.kind`',
embed.pos)
@ -109,10 +113,16 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
c.error('method $method.name returns non JS type', method.pos)
}
}
if method.return_type.has_flag(.generic) {
has_generic_types = true
}
for j, param in method.params {
if j == 0 && is_js {
continue // no need to check first param
}
if param.typ.has_flag(.generic) {
has_generic_types = true
}
c.ensure_type_exists(param.typ, param.pos) or { return }
if param.name in reserved_type_names {
c.error('invalid use of reserved type `$param.name` as a parameter name',
@ -145,6 +155,9 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
c.check_valid_snake_case(field.name, 'field name', field.pos)
}
c.ensure_type_exists(field.typ, field.pos) or { return }
if field.typ.has_flag(.generic) {
has_generic_types = true
}
if is_js {
tsym := c.table.sym(field.typ)
if !tsym.is_js_compatible() {
@ -161,6 +174,10 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
}
}
}
if node.generic_types.len == 0 && has_generic_types {
c.error('generic interface declaration must specify the generic type names, e.g. Foo<T>',
node.pos)
}
}
}

View File

@ -0,0 +1,5 @@
vlib/v/checker/tests/generics_interface_declaration_err.vv:1:1: error: generic interface declaration must specify the generic type names, e.g. Foo<T>
1 | interface Expr {
| ~~~~~~~~~~~~~~~~
2 | accept(v Visitor<R>) R
3 | }

View File

@ -0,0 +1,9 @@
interface Expr {
accept(v Visitor<R>) R
}
interface Visitor<R> {
}
fn main() {
}