parser: duplicate method declaration on interface (#5825)

pull/5836/head
Enzo 2020-07-15 10:23:21 +02:00 committed by GitHub
parent 8df6e59678
commit 2ee8f93d60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 45 additions and 3 deletions

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/no_interface_receiver_duplicate_a.v:5:5: error: interfaces cannot be used as method receiver
3 | }
4 |
5 | fn (a Abc) fun() {
| ~~~~~
6 | }

View File

@ -0,0 +1,6 @@
interface Abc {
fun()
}
fn (a Abc) fun() {
}

View File

@ -0,0 +1,5 @@
vlib/v/checker/tests/no_interface_receiver_duplicate_b.v:1:5: error: interfaces cannot be used as method receiver
1 | fn (a Abc) fun() {
| ~~~~~
2 | }
3 |

View File

@ -0,0 +1,6 @@
fn (a Abc) fun() {
}
interface Abc {
fun()
}

View File

@ -196,7 +196,9 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
if language == .v && !p.pref.translated && util.contains_capital(name) {
p.error('function names cannot contain uppercase letters, use snake_case instead')
}
if is_method && p.table.get_type_symbol(rec_type).has_method(name) {
type_sym := p.table.get_type_symbol(rec_type)
// interfaces are handled in the checker, methods can not be defined on them this way
if is_method && (type_sym.has_method(name) && type_sym.kind != .interface_) {
p.error('duplicate method `$name`')
}
}
@ -476,7 +478,8 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool, bool) {
p.check_fn_mutable_arguments(typ, pos)
}
} else if is_shared || is_atomic {
p.error_with_pos('generic object cannot be `atomic` or `shared`', pos)
p.error_with_pos('generic object cannot be `atomic` or `shared`',
pos)
}
typ = typ.set_nr_muls(1)
if is_shared {
@ -527,7 +530,8 @@ fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position)
fn (mut p Parser) check_fn_shared_arguments(typ table.Type, pos token.Position) {
sym := p.table.get_type_symbol(typ)
if sym.kind !in [.array, .struct_, .map, .placeholder] && !typ.is_ptr() {
p.error_with_pos('shared arguments are only allowed for arrays, maps, and structs\n', pos)
p.error_with_pos('shared arguments are only allowed for arrays, maps, and structs\n',
pos)
}
}

View File

@ -359,12 +359,17 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
}
typ := table.new_type(reg_idx)
ts := p.table.get_type_symbol(typ)
// if methods were declared before, it's an error, ignore them
ts.methods.clear()
// Parse methods
mut methods := []ast.FnDecl{}
for p.tok.kind != .rcbr && p.tok.kind != .eof {
method_start_pos := p.tok.position()
line_nr := p.tok.line_nr
name := p.check_name()
if ts.has_method(name) {
p.error_with_pos('duplicate method `$name`', method_start_pos)
}
if util.contains_capital(name) {
p.error('interface methods cannot contain uppercase letters, use snake_case instead')
}

View File

@ -0,0 +1,6 @@
vlib/v/parser/tests/interface_duplicate_method.v:3:2: error: duplicate method `fun`
1 | interface Abc {
2 | fun()
3 | fun()
| ~~~
4 | }

View File

@ -0,0 +1,4 @@
interface Abc {
fun()
fun()
}