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:
parent
28fd17654e
commit
7594157deb
@ -11,6 +11,7 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
|
|||||||
mut decl_sym := c.table.sym(node.typ)
|
mut decl_sym := c.table.sym(node.typ)
|
||||||
is_js := node.language == .js
|
is_js := node.language == .js
|
||||||
if mut decl_sym.info is ast.Interface {
|
if mut decl_sym.info is ast.Interface {
|
||||||
|
mut has_generic_types := false
|
||||||
if node.embeds.len > 0 {
|
if node.embeds.len > 0 {
|
||||||
all_embeds := c.expand_iface_embeds(node, 0, node.embeds)
|
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')
|
// 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 {
|
for embed in all_embeds {
|
||||||
isym := c.table.sym(embed.typ)
|
isym := c.table.sym(embed.typ)
|
||||||
|
if embed.typ.has_flag(.generic) {
|
||||||
|
has_generic_types = true
|
||||||
|
}
|
||||||
if isym.kind != .interface_ {
|
if isym.kind != .interface_ {
|
||||||
c.error('interface `$node.name` tries to embed `$isym.name`, but `$isym.name` is not an interface, but `$isym.kind`',
|
c.error('interface `$node.name` tries to embed `$isym.name`, but `$isym.name` is not an interface, but `$isym.kind`',
|
||||||
embed.pos)
|
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)
|
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 {
|
for j, param in method.params {
|
||||||
if j == 0 && is_js {
|
if j == 0 && is_js {
|
||||||
continue // no need to check first param
|
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 }
|
c.ensure_type_exists(param.typ, param.pos) or { return }
|
||||||
if param.name in reserved_type_names {
|
if param.name in reserved_type_names {
|
||||||
c.error('invalid use of reserved type `$param.name` as a parameter name',
|
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.check_valid_snake_case(field.name, 'field name', field.pos)
|
||||||
}
|
}
|
||||||
c.ensure_type_exists(field.typ, field.pos) or { return }
|
c.ensure_type_exists(field.typ, field.pos) or { return }
|
||||||
|
if field.typ.has_flag(.generic) {
|
||||||
|
has_generic_types = true
|
||||||
|
}
|
||||||
if is_js {
|
if is_js {
|
||||||
tsym := c.table.sym(field.typ)
|
tsym := c.table.sym(field.typ)
|
||||||
if !tsym.is_js_compatible() {
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 | }
|
@ -0,0 +1,9 @@
|
|||||||
|
interface Expr {
|
||||||
|
accept(v Visitor<R>) R
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Visitor<R> {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user