interfaces: error on implemention of own interface method & on duplicate normal methods
parent
0dafdb4cde
commit
a50f2ca5e8
|
@ -5841,9 +5841,17 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
c.error('unknown type `$sym.name`', node.receiver_pos)
|
c.error('unknown type `$sym.name`', node.receiver_pos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// if sym.has_method(node.name) {
|
// make sure interface does not implement its own interface methods
|
||||||
// c.warn('duplicate method `$node.name`', node.pos)
|
if sym.kind == .interface_ && sym.has_method(node.name) {
|
||||||
// }
|
if sym.info is table.Interface {
|
||||||
|
info := sym.info as table.Interface
|
||||||
|
// if the method is in info.methods then it is an interface method
|
||||||
|
if info.has_method(node.name) {
|
||||||
|
c.error('interface `$sym.name` cannot implement its own interface method `$node.name`',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// needed for proper error reporting during vweb route checking
|
// needed for proper error reporting during vweb route checking
|
||||||
sym.methods[node.method_idx].source_fn = voidptr(node)
|
sym.methods[node.method_idx].source_fn = voidptr(node)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
vlib/v/checker/tests/interface_implementing_own_interface_method.vv:5:1: error: interface `Animal` cannot implement its own interface method `speak`
|
||||||
|
3 | }
|
||||||
|
4 |
|
||||||
|
5 | fn (a Animal) speak() {
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
6 | println('speaking')
|
||||||
|
7 | }
|
|
@ -0,0 +1,7 @@
|
||||||
|
interface Animal {
|
||||||
|
speak()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (a Animal) speak() {
|
||||||
|
println('speaking')
|
||||||
|
}
|
|
@ -221,11 +221,20 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type_sym := p.table.get_type_symbol(rec.typ)
|
type_sym := p.table.get_type_symbol(rec.typ)
|
||||||
// interfaces are handled in the checker, methods can not be defined on them this way
|
if is_method {
|
||||||
if is_method && (type_sym.has_method(name) && type_sym.kind != .interface_) {
|
mut is_duplicate := type_sym.has_method(name)
|
||||||
p.error_with_pos('duplicate method `$name`', pos)
|
// make sure this is a normal method and not an interface method
|
||||||
return ast.FnDecl{
|
if type_sym.kind == .interface_ && is_duplicate {
|
||||||
scope: 0
|
if type_sym.info is table.Interface {
|
||||||
|
// if the method is in info then its an interface method
|
||||||
|
is_duplicate = !type_sym.info.has_method(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if is_duplicate {
|
||||||
|
p.error_with_pos('duplicate method `$name`', pos)
|
||||||
|
return ast.FnDecl{
|
||||||
|
scope: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// cannot redefine buildin function
|
// cannot redefine buildin function
|
||||||
|
@ -276,7 +285,6 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut end_pos := p.prev_tok.position()
|
|
||||||
// Return type
|
// Return type
|
||||||
mut return_type := table.void_type
|
mut return_type := table.void_type
|
||||||
// don't confuse token on the next line: fn decl, [attribute]
|
// don't confuse token on the next line: fn decl, [attribute]
|
||||||
|
@ -287,6 +295,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
}
|
}
|
||||||
mut type_sym_method_idx := 0
|
mut type_sym_method_idx := 0
|
||||||
no_body := p.tok.kind != .lcbr
|
no_body := p.tok.kind != .lcbr
|
||||||
|
end_pos := p.prev_tok.position()
|
||||||
// Register
|
// Register
|
||||||
if is_method {
|
if is_method {
|
||||||
mut type_sym := p.table.get_type_symbol(rec.typ)
|
mut type_sym := p.table.get_type_symbol(rec.typ)
|
||||||
|
@ -348,7 +357,6 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
language: language
|
language: language
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
end_pos = p.prev_tok.position()
|
|
||||||
// Body
|
// Body
|
||||||
p.cur_fn_name = name
|
p.cur_fn_name = name
|
||||||
mut stmts := []ast.Stmt{}
|
mut stmts := []ast.Stmt{}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
vlib/v/parser/tests/interface_duplicate_interface_method.vv:4:2: error: duplicate method `fun`
|
||||||
|
2 | interface Abc {
|
||||||
|
3 | fun()
|
||||||
|
4 | fun()
|
||||||
|
| ~~~
|
||||||
|
5 | }
|
|
@ -0,0 +1,5 @@
|
||||||
|
// duplicate interface methods in decleration
|
||||||
|
interface Abc {
|
||||||
|
fun()
|
||||||
|
fun()
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
vlib/v/parser/tests/interface_duplicate_method.vv:3:2: error: duplicate method `fun`
|
vlib/v/parser/tests/interface_duplicate_method.vv:5:12: error: duplicate method `foo`
|
||||||
1 | interface Abc {
|
3 | // duplicate normal method definitions on interface
|
||||||
2 | fun()
|
4 | fn (a Abc) foo() {}
|
||||||
3 | fun()
|
5 | fn (a Abc) foo() {}
|
||||||
| ~~~
|
| ~~~
|
||||||
4 | }
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
interface Abc {
|
interface Abc {}
|
||||||
fun()
|
|
||||||
fun()
|
// duplicate normal method definitions on interface
|
||||||
}
|
fn (a Abc) foo() {}
|
||||||
|
fn (a Abc) foo() {}
|
|
@ -993,6 +993,22 @@ pub fn (i &Interface) find_field(name string) ?Field {
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (i &Interface) find_method(name string) ?Fn {
|
||||||
|
for method in i.methods {
|
||||||
|
if method.name == name {
|
||||||
|
return method
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (i &Interface) has_method(name string) bool {
|
||||||
|
if _ := i.find_method(name) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (s Struct) find_field(name string) ?Field {
|
pub fn (s Struct) find_field(name string) ?Field {
|
||||||
for field in s.fields {
|
for field in s.fields {
|
||||||
if field.name == name {
|
if field.name == name {
|
||||||
|
|
Loading…
Reference in New Issue