From 3be8ef3b5af586d93eb788c71e25a383f82c4570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A4schle?= Date: Sat, 24 Jul 2021 15:06:09 +0200 Subject: [PATCH] checker: check duplicated field and method (only for fields that are anon-fns for now) (#10927) --- vlib/v/checker/checker.v | 21 ++++++++++++++++--- .../tests/duplicate_field_method_err.out | 13 ++++++++++++ .../tests/duplicate_field_method_err.vv | 10 +++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 vlib/v/checker/tests/duplicate_field_method_err.out create mode 100644 vlib/v/checker/tests/duplicate_field_method_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index dc81518ce9..e0b0dc2347 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -521,6 +521,13 @@ pub fn (mut c Checker) interface_decl(mut decl ast.InterfaceDecl) { for param in method.params { 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 { if method.name == decl.methods[j].name { 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 if sym.kind == .interface_ && sym.has_method(node.name) { - if sym.info is ast.Interface { - info := sym.info as ast.Interface + if mut sym.info is ast.Interface { // 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`', 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 if node.method_idx < sym.methods.len { sym.methods[node.method_idx].source_fn = voidptr(node) diff --git a/vlib/v/checker/tests/duplicate_field_method_err.out b/vlib/v/checker/tests/duplicate_field_method_err.out new file mode 100644 index 0000000000..b4befdd8ef --- /dev/null +++ b/vlib/v/checker/tests/duplicate_field_method_err.out @@ -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 | } diff --git a/vlib/v/checker/tests/duplicate_field_method_err.vv b/vlib/v/checker/tests/duplicate_field_method_err.vv new file mode 100644 index 0000000000..2c34f78175 --- /dev/null +++ b/vlib/v/checker/tests/duplicate_field_method_err.vv @@ -0,0 +1,10 @@ +struct St{ + attr fn() +} + +fn (s St) attr() {} + +interface Foo { + bar fn () + bar() +}