checker: make implementing an interface with another interface an error (#8398)

pull/8401/head
spaceface 2021-01-29 00:41:59 +01:00 committed by GitHub
parent adb646a1d2
commit 4aee997689
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 10 deletions

View File

@ -1870,6 +1870,11 @@ fn (mut c Checker) type_implements(typ table.Type, inter_typ table.Type, pos tok
typ_sym := c.table.get_type_symbol(typ)
mut inter_sym := c.table.get_type_symbol(inter_typ)
styp := c.table.type_to_str(typ)
same_base_type := typ.idx() == inter_typ.idx()
if typ_sym.kind == .interface_ && inter_sym.kind == .interface_ && !same_base_type {
c.error('cannot implement interface `$inter_sym.name` with a different interface `$styp`',
pos)
}
imethods := if inter_sym.kind == .interface_ {
(inter_sym.info as table.Interface).methods
} else {
@ -3566,6 +3571,8 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) table.Type {
type_name := c.table.type_to_str(node.expr_type)
c.error('cannot cast `$type_name` to struct', node.pos)
}
} else if to_type_sym.kind == .interface_ {
c.type_implements(node.expr_type, node.typ, node.pos)
} else if node.typ == table.bool_type {
c.error('cannot cast to bool - use e.g. `some_int != 0` instead', node.pos)
} else if node.expr_type == table.none_type {
@ -3575,8 +3582,6 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) table.Type {
if (node.typ.is_ptr() || to_type_sym.kind !in [.sum_type, .interface_]) && !c.is_builtin_mod {
type_name := c.table.type_to_str(node.typ)
c.error('cannot cast struct to `$type_name`', node.pos)
} else if to_type_sym.kind == .interface_ {
c.type_implements(node.expr_type, node.typ, node.pos)
}
} else if node.expr_type.has_flag(.optional) || node.expr_type.has_flag(.variadic) {
// variadic case can happen when arrays are converted into variadic

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/interface_implementing_interface.vv:15:10: error: cannot implement interface `Thing` with a different interface `Animal`
13 | dog := Dog{}
14 | animal := Animal(dog)
15 | thing := Thing(animal)
| ~~~~~~~~~~~~~
16 | println(thing)

View File

@ -0,0 +1,16 @@
interface Thing {
kind string
}
interface Animal {
kind string
}
struct Dog {
kind string = 'labrador'
}
dog := Dog{}
animal := Animal(dog)
thing := Thing(animal)
println(thing)

View File

@ -60,11 +60,4 @@ vlib/v/checker/tests/struct_type_cast_err.vv:13:10: error: cannot cast struct to
13 | _ := int(foo)
| ~~~~~~~~
14 | _ = &I1(foo)
15 | }
vlib/v/checker/tests/struct_type_cast_err.vv:14:10: error: cannot cast struct to `&I1`
12 | _ := i64(foo)
13 | _ := int(foo)
14 | _ = &I1(foo)
| ~~~~~~~
15 | }
16 |
15 | }