diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 86b3974305..67b204070a 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1720,7 +1720,8 @@ fn (mut c Checker) type_implements(typ table.Type, inter_typ table.Type, pos tok } continue } - c.error("`$styp` doesn't implement method `$imethod.name`", pos) + c.error("`$styp` doesn't implement method `$imethod.name` of interface `$inter_sym.name`", + pos) } if mut inter_sym.info is table.Interface { if typ !in inter_sym.info.types && typ_sym.kind != .interface_ { @@ -2370,6 +2371,9 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { c.error('cannot assign to `$left`: $err', right.position()) } } + if left_sym.kind == .interface_ { + c.type_implements(right_type, left_type, right.position()) + } } // this needs to run after the assign stmt left exprs have been run through checker so that ident.obj is set // Check `x := &y` and `mut x := <-ch` diff --git a/vlib/v/checker/tests/is_type_invalid.out b/vlib/v/checker/tests/is_type_invalid.out index 7943bfc461..f26cb47d3f 100644 --- a/vlib/v/checker/tests/is_type_invalid.out +++ b/vlib/v/checker/tests/is_type_invalid.out @@ -1,14 +1,14 @@ vlib/v/checker/tests/is_type_invalid.vv:14:12: error: `IoS` has no variant `byte` - 12 | + 12 | 13 | fn main() { 14 | if IoS(1) is byte { | ~~ 15 | println('not cool') 16 | } -vlib/v/checker/tests/is_type_invalid.vv:18:2: error: `Cat` doesn't implement method `speak` +vlib/v/checker/tests/is_type_invalid.vv:18:2: error: `Cat` doesn't implement method `speak` of interface `Animal` 16 | } 17 | a := Animal(Dog{}) 18 | if a is Cat { | ~~~~~~~~~~~ 19 | println('not cool either') - 20 | } \ No newline at end of file + 20 | } diff --git a/vlib/v/checker/tests/match_invalid_type.out b/vlib/v/checker/tests/match_invalid_type.out index aeb38aafaa..4c6b98b836 100644 --- a/vlib/v/checker/tests/match_invalid_type.out +++ b/vlib/v/checker/tests/match_invalid_type.out @@ -6,16 +6,16 @@ vlib/v/checker/tests/match_invalid_type.vv:5:3: error: `IoS` has no variant `byt 6 | println('not cool') 7 | } vlib/v/checker/tests/match_invalid_type.vv:4:2: error: match must be exhaustive (add match branches for: `int`, `string` or `else {}` at the end) - 2 | + 2 | 3 | fn sum() { 4 | match IoS(1) { | ~~~~~~~~~~~~~~ 5 | byte { 6 | println('not cool') -vlib/v/checker/tests/match_invalid_type.vv:24:3: error: `Cat` doesn't implement method `speak` +vlib/v/checker/tests/match_invalid_type.vv:24:3: error: `Cat` doesn't implement method `speak` of interface `Animal` 22 | a := Animal(Dog{}) 23 | match a { 24 | Cat { | ~~~ 25 | println('not cool either') - 26 | } \ No newline at end of file + 26 | } diff --git a/vlib/v/checker/tests/unimplemented_interface_a.out b/vlib/v/checker/tests/unimplemented_interface_a.out index c4bb12f89c..225ccd0837 100644 --- a/vlib/v/checker/tests/unimplemented_interface_a.out +++ b/vlib/v/checker/tests/unimplemented_interface_a.out @@ -1,5 +1,5 @@ -vlib/v/checker/tests/unimplemented_interface_a.vv:10:6: error: `Cat` doesn't implement method `name` - 8 | +vlib/v/checker/tests/unimplemented_interface_a.vv:10:6: error: `Cat` doesn't implement method `name` of interface `Animal` + 8 | 9 | fn main() { 10 | foo(Cat{}) | ~~~~~ diff --git a/vlib/v/tests/interface_edge_cases/assign_to_interface_field_test.v b/vlib/v/tests/interface_edge_cases/assign_to_interface_field_test.v new file mode 100644 index 0000000000..cb69e550c8 --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/assign_to_interface_field_test.v @@ -0,0 +1,28 @@ +interface Planet { + name() string +} + +struct Moon {} + +fn (moon Moon) name() string { + return 'moon' +} + +struct Mars {} + +fn (moon Mars) name() string { + return 'mars' +} + +struct AnyPlanet { +mut: + planet Planet +} + +fn test_a_struct_implementing_an_interface_can_be_assigned_without_explicit_casts() { + mut anyplanet := AnyPlanet{} + anyplanet.planet = Moon{} + assert anyplanet.planet.name() == 'moon' + anyplanet.planet = Mars{} + assert anyplanet.planet.name() == 'mars' +}