diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 7bc7c79a15..0404c1c771 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -206,6 +206,7 @@ pub: is_variadic bool is_anon bool receiver Field + receiver_pos token.Position is_method bool rec_mut bool // is receiver mutable is_c bool diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index f5519f837a..bcb91efe4e 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1385,12 +1385,15 @@ fn (mut c Checker) stmt(node ast.Stmt) { c.check_expr_opt_call(it.expr, etype, false) } ast.FnDecl { - // if it.is_method { - // sym := c.table.get_type_symbol(it.receiver.typ) - // if sym.has_method(it.name) { - // c.warn('duplicate method `$it.name`', it.pos) - // } - // } + if it.is_method { + sym := c.table.get_type_symbol(it.receiver.typ) + if sym.kind == .interface_ { + c.error('interaces cannot be used as method receiver', it.receiver_pos) + } + // if sym.has_method(it.name) { + // c.warn('duplicate method `$it.name`', it.pos) + // } + } if !it.is_c { // Make sure all types are valid for arg in it.args { @@ -1748,7 +1751,8 @@ pub fn (mut c Checker) ident(ident mut ast.Ident) table.Type { if sym.info is table.FnType { // anon/local fn assigned to new variable uses this info := sym.info as table.FnType - fn_type := table.new_type(c.table.find_or_register_fn_type(info.func, true, true)) + fn_type := table.new_type(c.table.find_or_register_fn_type(info.func, + true, true)) ident.kind = .function ident.info = ast.IdentFn{ typ: fn_type diff --git a/vlib/v/checker/tests/no_interface_receiver.out b/vlib/v/checker/tests/no_interface_receiver.out new file mode 100644 index 0000000000..738aafe9e5 --- /dev/null +++ b/vlib/v/checker/tests/no_interface_receiver.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/no_interface_receiver.v:5:5: error: interaces cannot be used as method receiver + 3 | } + 4 | + 5 | fn (a Animal) str() {} + | ~~~~~~~~ + diff --git a/vlib/v/checker/tests/no_interface_receiver.vv b/vlib/v/checker/tests/no_interface_receiver.vv new file mode 100644 index 0000000000..e0001aae5f --- /dev/null +++ b/vlib/v/checker/tests/no_interface_receiver.vv @@ -0,0 +1,5 @@ +interface Animal { + speak() +} + +fn (a Animal) str() {} diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 06ccc8616e..d22d5cf7a7 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -109,6 +109,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { // Receiver? mut rec_name := '' mut is_method := false + mut receiver_pos := token.Position{} mut rec_type := table.void_type mut rec_mut := false mut args := []table.Arg{} @@ -119,11 +120,13 @@ fn (mut p Parser) fn_decl() ast.FnDecl { if rec_mut { p.next() // `mut` } + rec_start_pos := p.tok.position() rec_name = p.check_name() if !rec_mut { rec_mut = p.tok.kind == .key_mut } is_amp := p.tok.kind == .amp + receiver_pos = rec_start_pos.extend(p.tok.position()) // if rec_mut { // p.check(.key_mut) // } @@ -256,6 +259,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { name: rec_name typ: rec_type } + receiver_pos: receiver_pos is_method: is_method rec_mut: rec_mut is_c: is_c