cgen: fix `x.interface_field = value_implementing_interface` (closes #7620)

pull/7622/head
Delyan Angelov 2020-12-27 19:12:39 +02:00
parent 8872b0a23b
commit df61cf246b
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
5 changed files with 41 additions and 9 deletions

View File

@ -1720,7 +1720,8 @@ fn (mut c Checker) type_implements(typ table.Type, inter_typ table.Type, pos tok
} }
continue 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 mut inter_sym.info is table.Interface {
if typ !in inter_sym.info.types && typ_sym.kind != .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()) 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 // 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` // Check `x := &y` and `mut x := <-ch`

View File

@ -1,14 +1,14 @@
vlib/v/checker/tests/is_type_invalid.vv:14:12: error: `IoS` has no variant `byte` vlib/v/checker/tests/is_type_invalid.vv:14:12: error: `IoS` has no variant `byte`
12 | 12 |
13 | fn main() { 13 | fn main() {
14 | if IoS(1) is byte { 14 | if IoS(1) is byte {
| ~~ | ~~
15 | println('not cool') 15 | println('not cool')
16 | } 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 | } 16 | }
17 | a := Animal(Dog{}) 17 | a := Animal(Dog{})
18 | if a is Cat { 18 | if a is Cat {
| ~~~~~~~~~~~ | ~~~~~~~~~~~
19 | println('not cool either') 19 | println('not cool either')
20 | } 20 | }

View File

@ -6,16 +6,16 @@ vlib/v/checker/tests/match_invalid_type.vv:5:3: error: `IoS` has no variant `byt
6 | println('not cool') 6 | println('not cool')
7 | } 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) 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() { 3 | fn sum() {
4 | match IoS(1) { 4 | match IoS(1) {
| ~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~
5 | byte { 5 | byte {
6 | println('not cool') 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{}) 22 | a := Animal(Dog{})
23 | match a { 23 | match a {
24 | Cat { 24 | Cat {
| ~~~ | ~~~
25 | println('not cool either') 25 | println('not cool either')
26 | } 26 | }

View File

@ -1,5 +1,5 @@
vlib/v/checker/tests/unimplemented_interface_a.vv:10:6: error: `Cat` doesn't implement method `name` vlib/v/checker/tests/unimplemented_interface_a.vv:10:6: error: `Cat` doesn't implement method `name` of interface `Animal`
8 | 8 |
9 | fn main() { 9 | fn main() {
10 | foo(Cat{}) 10 | foo(Cat{})
| ~~~~~ | ~~~~~

View File

@ -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'
}