checker: check duplicated field and method (only for fields that are anon-fns for now) (#10927)

pull/10944/head
Daniel Däschle 2021-07-24 15:06:09 +02:00 committed by GitHub
parent a621149fc2
commit 3be8ef3b5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 3 deletions

View File

@ -521,6 +521,13 @@ pub fn (mut c Checker) interface_decl(mut decl ast.InterfaceDecl) {
for param in method.params { for param in method.params {
c.ensure_type_exists(param.typ, param.pos) or { return } c.ensure_type_exists(param.typ, param.pos) or { return }
} }
for field in decl.fields {
field_sym := c.table.get_type_symbol(field.typ)
if field.name == method.name && field_sym.kind == .function {
c.error('type `$decl_sym.name` has both field and method named `$method.name`',
method.pos)
}
}
for j in 0 .. i { for j in 0 .. i {
if method.name == decl.methods[j].name { if method.name == decl.methods[j].name {
c.error('duplicate method name `$method.name`', method.pos) c.error('duplicate method name `$method.name`', method.pos)
@ -7888,15 +7895,23 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
} }
// make sure interface does not implement its own interface methods // make sure interface does not implement its own interface methods
if sym.kind == .interface_ && sym.has_method(node.name) { if sym.kind == .interface_ && sym.has_method(node.name) {
if sym.info is ast.Interface { if mut sym.info is ast.Interface {
info := sym.info as ast.Interface
// if the method is in info.methods then it is an interface method // if the method is in info.methods then it is an interface method
if info.has_method(node.name) { if sym.info.has_method(node.name) {
c.error('interface `$sym.name` cannot implement its own interface method `$node.name`', c.error('interface `$sym.name` cannot implement its own interface method `$node.name`',
node.pos) node.pos)
} }
} }
} }
if mut sym.info is ast.Struct {
if field := c.table.find_field(sym, node.name) {
field_sym := c.table.get_type_symbol(field.typ)
if field_sym.kind == .function {
c.error('type `$sym.name` has both field and method named `$node.name`',
node.pos)
}
}
}
// needed for proper error reporting during vweb route checking // needed for proper error reporting during vweb route checking
if node.method_idx < sym.methods.len { if node.method_idx < sym.methods.len {
sym.methods[node.method_idx].source_fn = voidptr(node) sym.methods[node.method_idx].source_fn = voidptr(node)

View File

@ -0,0 +1,13 @@
vlib/v/checker/tests/duplicate_field_method_err.vv:5:1: error: type `St` has both field and method named `attr`
3 | }
4 |
5 | fn (s St) attr() {}
| ~~~~~~~~~~~~~~~~
6 |
7 | interface Foo {
vlib/v/checker/tests/duplicate_field_method_err.vv:9:2: error: type `Foo` has both field and method named `bar`
7 | interface Foo {
8 | bar fn ()
9 | bar()
| ~~~~~
10 | }

View File

@ -0,0 +1,10 @@
struct St{
attr fn()
}
fn (s St) attr() {}
interface Foo {
bar fn ()
bar()
}