checker: verify interface is not used as receiver

pull/4770/head
Enzo Baldisserri 2020-05-07 10:14:51 +02:00 committed by GitHub
parent 7d32476841
commit 0f8ed84333
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 7 deletions

View File

@ -206,6 +206,7 @@ pub:
is_variadic bool is_variadic bool
is_anon bool is_anon bool
receiver Field receiver Field
receiver_pos token.Position
is_method bool is_method bool
rec_mut bool // is receiver mutable rec_mut bool // is receiver mutable
is_c bool is_c bool

View File

@ -1385,12 +1385,15 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.check_expr_opt_call(it.expr, etype, false) c.check_expr_opt_call(it.expr, etype, false)
} }
ast.FnDecl { ast.FnDecl {
// if it.is_method { if it.is_method {
// sym := c.table.get_type_symbol(it.receiver.typ) 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) { // if sym.has_method(it.name) {
// c.warn('duplicate method `$it.name`', it.pos) // c.warn('duplicate method `$it.name`', it.pos)
// } // }
// } }
if !it.is_c { if !it.is_c {
// Make sure all types are valid // Make sure all types are valid
for arg in it.args { 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 { if sym.info is table.FnType {
// anon/local fn assigned to new variable uses this // anon/local fn assigned to new variable uses this
info := sym.info as table.FnType 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.kind = .function
ident.info = ast.IdentFn{ ident.info = ast.IdentFn{
typ: fn_type typ: fn_type

View File

@ -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() {}
| ~~~~~~~~

View File

@ -0,0 +1,5 @@
interface Animal {
speak()
}
fn (a Animal) str() {}

View File

@ -109,6 +109,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
// Receiver? // Receiver?
mut rec_name := '' mut rec_name := ''
mut is_method := false mut is_method := false
mut receiver_pos := token.Position{}
mut rec_type := table.void_type mut rec_type := table.void_type
mut rec_mut := false mut rec_mut := false
mut args := []table.Arg{} mut args := []table.Arg{}
@ -119,11 +120,13 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
if rec_mut { if rec_mut {
p.next() // `mut` p.next() // `mut`
} }
rec_start_pos := p.tok.position()
rec_name = p.check_name() rec_name = p.check_name()
if !rec_mut { if !rec_mut {
rec_mut = p.tok.kind == .key_mut rec_mut = p.tok.kind == .key_mut
} }
is_amp := p.tok.kind == .amp is_amp := p.tok.kind == .amp
receiver_pos = rec_start_pos.extend(p.tok.position())
// if rec_mut { // if rec_mut {
// p.check(.key_mut) // p.check(.key_mut)
// } // }
@ -256,6 +259,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
name: rec_name name: rec_name
typ: rec_type typ: rec_type
} }
receiver_pos: receiver_pos
is_method: is_method is_method: is_method
rec_mut: rec_mut rec_mut: rec_mut
is_c: is_c is_c: is_c