checker: fix map assign array of interface values (#10532)
parent
e259f7ac58
commit
da4b6b934d
|
@ -6872,30 +6872,43 @@ pub fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
|
|||
return node.typ
|
||||
}
|
||||
if node.keys.len > 0 && node.vals.len > 0 {
|
||||
// `{'age': 20}`
|
||||
mut key0_type := c.table.mktyp(c.expr(node.keys[0]))
|
||||
if node.keys[0].is_auto_deref_var() {
|
||||
key0_type = key0_type.deref()
|
||||
}
|
||||
mut val0_type := c.table.mktyp(c.expr(node.vals[0]))
|
||||
if node.vals[0].is_auto_deref_var() {
|
||||
val0_type = val0_type.deref()
|
||||
mut key0_type := ast.void_type
|
||||
mut val0_type := ast.void_type
|
||||
use_expected_type := c.expected_type != ast.void_type && !c.inside_const
|
||||
&& c.table.get_type_symbol(c.expected_type).kind == .map
|
||||
if use_expected_type {
|
||||
sym := c.table.get_type_symbol(c.expected_type)
|
||||
info := sym.map_info()
|
||||
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
|
||||
for i, key in node.keys {
|
||||
if i == 0 {
|
||||
if i == 0 && !use_expected_type {
|
||||
continue
|
||||
}
|
||||
val := node.vals[i]
|
||||
key_type := c.expr(key)
|
||||
c.expected_type = val0_type
|
||||
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)
|
||||
c.error('invalid map key: $msg', key.position())
|
||||
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)
|
||||
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() {
|
||||
2 | mut a := map[string]f32{}
|
||||
3 | a = { 'x': 12.3 }
|
||||
| ~~~~~~~~~~~~~
|
||||
| ~~~~
|
||||
4 | _ = {2:0 3:0 "hi":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`
|
||||
|
|
|
@ -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