parser: check types in `a in b` expressions

pull/2978/head
Alexander Medvednikov 2019-12-04 22:05:36 +03:00
parent f0f62f6217
commit fb237b9e53
2 changed files with 13 additions and 2 deletions

View File

@ -2171,7 +2171,7 @@ fn (p mut Parser) indot_expr() string {
if p.tok == .key_in { if p.tok == .key_in {
p.fspace() p.fspace()
p.check(.key_in) p.check(.key_in)
p.expected_type = typ // this allows `foo in [.val1, .val2, .val3]` p.expected_type = typ // this allows short enum syntax `foo in [.val1, .val2, .val3]`
if p.tok == .lsbr { if p.tok == .lsbr {
// a in [1,2,3] optimization => `a == 1 || a == 2 || a == 3` // a in [1,2,3] optimization => `a == 1 || a == 2 || a == 3`
// avoids an allocation // avoids an allocation
@ -2182,9 +2182,16 @@ fn (p mut Parser) indot_expr() string {
p.gen('), ') p.gen('), ')
arr_typ := p.expression() arr_typ := p.expression()
is_map := arr_typ.starts_with('map_') is_map := arr_typ.starts_with('map_')
if !arr_typ.starts_with('array_') && !is_map { is_arr:= arr_typ.starts_with('array_')
if !is_arr && !is_map {
p.error('`in` requires an array/map') p.error('`in` requires an array/map')
} }
if is_arr && arr_typ[6..] != typ {
p.error('bad element type: `$typ` in `$arr_typ`')
}
if is_map && typ != 'string' {
p.error('bad element type: expecting `string`')
}
T := p.table.find_type(arr_typ) T := p.table.find_type(arr_typ)
if !is_map && !T.has_method('contains') { if !is_map && !T.has_method('contains') {
p.error('$arr_typ has no method `contains`') p.error('$arr_typ has no method `contains`')

View File

@ -0,0 +1,4 @@
a := [1,2,3]
println('hi' in a)
===output===
.vrepl.v:2:18: bad element type: `string` in `[]int`