diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index f8c1f192ab..eb6f151cf7 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -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 diff --git a/vlib/v/checker/tests/interface_implementing_interface.out b/vlib/v/checker/tests/interface_implementing_interface.out new file mode 100644 index 0000000000..b2476ce4d3 --- /dev/null +++ b/vlib/v/checker/tests/interface_implementing_interface.out @@ -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) \ No newline at end of file diff --git a/vlib/v/checker/tests/interface_implementing_interface.vv b/vlib/v/checker/tests/interface_implementing_interface.vv new file mode 100644 index 0000000000..a71e9eabd1 --- /dev/null +++ b/vlib/v/checker/tests/interface_implementing_interface.vv @@ -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) diff --git a/vlib/v/checker/tests/struct_type_cast_err.out b/vlib/v/checker/tests/struct_type_cast_err.out index 39b4ea3613..4648a27f43 100644 --- a/vlib/v/checker/tests/struct_type_cast_err.out +++ b/vlib/v/checker/tests/struct_type_cast_err.out @@ -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 | } \ No newline at end of file