cgen: fix `x.interface_field = value_implementing_interface` (closes #7620)
parent
8872b0a23b
commit
df61cf246b
|
@ -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`
|
||||||
|
|
|
@ -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 | }
|
||||||
|
|
|
@ -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 | }
|
||||||
|
|
|
@ -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{})
|
||||||
| ~~~~~
|
| ~~~~~
|
||||||
|
|
|
@ -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'
|
||||||
|
}
|
Loading…
Reference in New Issue