mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: fix map assign array of interface values (#10532)
This commit is contained in:
parent
e259f7ac58
commit
da4b6b934d
@ -6872,30 +6872,43 @@ pub fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
|
|||||||
return node.typ
|
return node.typ
|
||||||
}
|
}
|
||||||
if node.keys.len > 0 && node.vals.len > 0 {
|
if node.keys.len > 0 && node.vals.len > 0 {
|
||||||
// `{'age': 20}`
|
mut key0_type := ast.void_type
|
||||||
mut key0_type := c.table.mktyp(c.expr(node.keys[0]))
|
mut val0_type := ast.void_type
|
||||||
if node.keys[0].is_auto_deref_var() {
|
use_expected_type := c.expected_type != ast.void_type && !c.inside_const
|
||||||
key0_type = key0_type.deref()
|
&& c.table.get_type_symbol(c.expected_type).kind == .map
|
||||||
}
|
if use_expected_type {
|
||||||
mut val0_type := c.table.mktyp(c.expr(node.vals[0]))
|
sym := c.table.get_type_symbol(c.expected_type)
|
||||||
if node.vals[0].is_auto_deref_var() {
|
info := sym.map_info()
|
||||||
val0_type = val0_type.deref()
|
key0_type = c.unwrap_generic(info.key_type)
|
||||||
|
val0_type = c.unwrap_generic(info.value_type)
|
||||||
|
} else {
|
||||||
|
// `{'age': 20}`
|
||||||
|
key0_type = c.table.mktyp(c.expr(node.keys[0]))
|
||||||
|
if node.keys[0].is_auto_deref_var() {
|
||||||
|
key0_type = key0_type.deref()
|
||||||
|
}
|
||||||
|
val0_type = c.table.mktyp(c.expr(node.vals[0]))
|
||||||
|
if node.vals[0].is_auto_deref_var() {
|
||||||
|
val0_type = val0_type.deref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mut same_key_type := true
|
mut same_key_type := true
|
||||||
for i, key in node.keys {
|
for i, key in node.keys {
|
||||||
if i == 0 {
|
if i == 0 && !use_expected_type {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val := node.vals[i]
|
val := node.vals[i]
|
||||||
key_type := c.expr(key)
|
key_type := c.expr(key)
|
||||||
c.expected_type = val0_type
|
c.expected_type = val0_type
|
||||||
val_type := c.expr(val)
|
val_type := c.expr(val)
|
||||||
if !c.check_types(key_type, key0_type) {
|
if !c.check_types(key_type, key0_type) || (i == 0 && key_type.is_number()
|
||||||
|
&& key0_type.is_number() && key0_type != c.table.mktyp(key_type)) {
|
||||||
msg := c.expected_msg(key_type, key0_type)
|
msg := c.expected_msg(key_type, key0_type)
|
||||||
c.error('invalid map key: $msg', key.position())
|
c.error('invalid map key: $msg', key.position())
|
||||||
same_key_type = false
|
same_key_type = false
|
||||||
}
|
}
|
||||||
if !c.check_types(val_type, val0_type) {
|
if !c.check_types(val_type, val0_type) || (i == 0 && val_type.is_number()
|
||||||
|
&& val0_type.is_number() && val0_type != c.table.mktyp(val_type)) {
|
||||||
msg := c.expected_msg(val_type, val0_type)
|
msg := c.expected_msg(val_type, val0_type)
|
||||||
c.error('invalid map value: $msg', val.position())
|
c.error('invalid map value: $msg', val.position())
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
vlib/v/checker/tests/map_init_wrong_type.vv:3:8: error: cannot assign to `a`: expected `map[string]f32`, not `map[string]f64`
|
vlib/v/checker/tests/map_init_wrong_type.vv:3:15: error: invalid map value: expected `f32`, not `float literal`
|
||||||
1 | fn main() {
|
1 | fn main() {
|
||||||
2 | mut a := map[string]f32{}
|
2 | mut a := map[string]f32{}
|
||||||
3 | a = { 'x': 12.3 }
|
3 | a = { 'x': 12.3 }
|
||||||
| ~~~~~~~~~~~~~
|
| ~~~~
|
||||||
4 | _ = {2:0 3:0 "hi":0}
|
4 | _ = {2:0 3:0 "hi":0}
|
||||||
5 | _ = {2:0 3:`@` 4:0}
|
5 | _ = {2:0 3:`@` 4:0}
|
||||||
vlib/v/checker/tests/map_init_wrong_type.vv:4:17: error: invalid map key: expected `int`, not `string`
|
vlib/v/checker/tests/map_init_wrong_type.vv:4:17: error: invalid map key: expected `int`, not `string`
|
||||||
|
40
vlib/v/tests/map_assign_array_of_interface_test.v
Normal file
40
vlib/v/tests/map_assign_array_of_interface_test.v
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
interface Animal {
|
||||||
|
say(message string) ?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Cat {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Dog {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (cat Cat) say(message string) ? {
|
||||||
|
println('$message, meow')
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (dog Dog) say(message string) ? {
|
||||||
|
println('$message, wooff')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_map_assign_array_of_interface() {
|
||||||
|
mut owner_and_animals := map[string][]Animal{}
|
||||||
|
|
||||||
|
owner_and_animals = map{
|
||||||
|
'John Doe': [
|
||||||
|
Cat{
|
||||||
|
name: 'Bobby'
|
||||||
|
},
|
||||||
|
Dog{
|
||||||
|
name: 'Hulk'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
println(owner_and_animals)
|
||||||
|
assert owner_and_animals['John Doe'].len == 2
|
||||||
|
println(owner_and_animals['John Doe'][0])
|
||||||
|
assert '${owner_and_animals['John Doe'][0]}'.contains("name: 'Bobby'")
|
||||||
|
println(owner_and_animals['John Doe'][1])
|
||||||
|
assert '${owner_and_animals['John Doe'][1]}'.contains("name: 'Hulk'")
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user