mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: check in
left type
This commit is contained in:
parent
fa4739794f
commit
a924defb94
@ -310,14 +310,22 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
||||
}
|
||||
}
|
||||
if infix_expr.op in [.key_in, .not_in] {
|
||||
if !(right.kind in [.array, .map, .string]) {
|
||||
c.error('`in` can only be used with an array/map/string', infix_expr.pos)
|
||||
}
|
||||
if right.kind == .array {
|
||||
right_sym := c.table.get_type_symbol(right.array_info().elem_type)
|
||||
if left.kind != .alias && left.kind != right_sym.kind {
|
||||
if left.kind != right_sym.kind {
|
||||
c.error('the data type on the left of `in` does not match the array item type', infix_expr.pos)
|
||||
}
|
||||
} else if right.kind == .map {
|
||||
key_sym := c.table.get_type_symbol(right.map_info().key_type)
|
||||
if left.kind != key_sym.kind {
|
||||
c.error('the data type on the left of `in` does not match the map key type', infix_expr.pos)
|
||||
}
|
||||
} else if right.kind == .string {
|
||||
if left.kind != .string {
|
||||
c.error('the data type on the left of `in` must be a string', infix_expr.pos)
|
||||
}
|
||||
} else {
|
||||
c.error('`in` can only be used with an array/map/string', infix_expr.pos)
|
||||
}
|
||||
return table.bool_type
|
||||
}
|
||||
@ -1156,15 +1164,16 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
||||
ast.ForInStmt {
|
||||
c.in_for_count++
|
||||
typ := c.expr(it.cond)
|
||||
typ_idx := table.type_idx(typ)
|
||||
if it.is_range {
|
||||
high_type := c.expr(it.high)
|
||||
if typ in table.integer_type_idxs && high_type !in table.integer_type_idxs {
|
||||
high_type_idx := table.type_idx(c.expr(it.high))
|
||||
if typ_idx in table.integer_type_idxs && high_type_idx !in table.integer_type_idxs {
|
||||
c.error('range types do not match', it.cond.position())
|
||||
} else if typ in table.float_type_idxs || high_type in table.float_type_idxs {
|
||||
} else if typ_idx in table.float_type_idxs || high_type_idx in table.float_type_idxs {
|
||||
c.error('range type can not be float', it.cond.position())
|
||||
} else if typ == table.bool_type_idx || high_type == table.bool_type_idx {
|
||||
} else if typ_idx == table.bool_type_idx || high_type_idx == table.bool_type_idx {
|
||||
c.error('range type can not be bool', it.cond.position())
|
||||
} else if typ == table.string_type_idx || high_type == table.string_type_idx {
|
||||
} else if typ_idx == table.string_type_idx || high_type_idx == table.string_type_idx {
|
||||
c.error('range type can not be string', it.cond.position())
|
||||
}
|
||||
c.expr(it.high)
|
||||
|
@ -1,6 +0,0 @@
|
||||
vlib/v/checker/tests/inout/in_array_mismatch_type.v:2:7: error: the data type on the left of `in` does not match the array item type
|
||||
1| fn main() {
|
||||
2| if 1 in ['1', '2'] {
|
||||
~~
|
||||
3| println('ok')
|
||||
4| }
|
@ -1,5 +0,0 @@
|
||||
fn main() {
|
||||
if 1 in ['1', '2'] {
|
||||
println('ok')
|
||||
}
|
||||
}
|
56
vlib/v/checker/tests/inout/in_mismatch_type.out
Normal file
56
vlib/v/checker/tests/inout/in_mismatch_type.out
Normal file
@ -0,0 +1,56 @@
|
||||
vlib/v/checker/tests/inout/in_mismatch_type.v:13:7: error: the data type on the left of `in` does not match the array item type
|
||||
11| }
|
||||
12| s := 'abcd'
|
||||
13| if 1 in a_s {
|
||||
~~
|
||||
14| println('ok')
|
||||
15| }
|
||||
vlib/v/checker/tests/inout/in_mismatch_type.v:16:7: error: the data type on the left of `in` does not match the map key type
|
||||
14| println('ok')
|
||||
15| }
|
||||
16| if 2 in m {
|
||||
~~
|
||||
17| println('yeah')
|
||||
18| }
|
||||
vlib/v/checker/tests/inout/in_mismatch_type.v:19:7: error: the data type on the left of `in` must be a string
|
||||
17| println('yeah')
|
||||
18| }
|
||||
19| if 3 in s {
|
||||
~~
|
||||
20| println('dope')
|
||||
21| }
|
||||
vlib/v/checker/tests/inout/in_mismatch_type.v:22:9: error: the data type on the left of `in` must be a string
|
||||
20| println('dope')
|
||||
21| }
|
||||
22| if `a` in s {
|
||||
~~
|
||||
23| println("oh no :'(")
|
||||
24| }
|
||||
vlib/v/checker/tests/inout/in_mismatch_type.v:25:7: error: `in` can only be used with an array/map/string
|
||||
23| println("oh no :'(")
|
||||
24| }
|
||||
25| if 1 in 12 {
|
||||
~~
|
||||
26| println('right')
|
||||
27| }
|
||||
vlib/v/checker/tests/inout/in_mismatch_type.v:28:12: error: the data type on the left of `in` does not match the map key type
|
||||
26| println('right')
|
||||
27| }
|
||||
28| if Int(2) in m {
|
||||
~~
|
||||
29| println('yeah')
|
||||
30| }
|
||||
vlib/v/checker/tests/inout/in_mismatch_type.v:31:15: error: the data type on the left of `in` does not match the array item type
|
||||
29| println('yeah')
|
||||
30| }
|
||||
31| if Str2('3') in a_i {
|
||||
~~
|
||||
32| println('sure')
|
||||
33| }
|
||||
vlib/v/checker/tests/inout/in_mismatch_type.v:34:15: error: the data type on the left of `in` does not match the array item type
|
||||
32| println('sure')
|
||||
33| }
|
||||
34| if Str3('2') in a_i {
|
||||
~~
|
||||
35| println('all right')
|
||||
36| }
|
37
vlib/v/checker/tests/inout/in_mismatch_type.vv
Normal file
37
vlib/v/checker/tests/inout/in_mismatch_type.vv
Normal file
@ -0,0 +1,37 @@
|
||||
type Int = int
|
||||
|
||||
type Str2 = string
|
||||
type Str3 = Str2
|
||||
|
||||
fn main() {
|
||||
a_i := [1, 2, 3]
|
||||
a_s := ['1', '2', '3']
|
||||
m := {
|
||||
'test': 1
|
||||
}
|
||||
s := 'abcd'
|
||||
if 1 in a_s {
|
||||
println('ok')
|
||||
}
|
||||
if 2 in m {
|
||||
println('yeah')
|
||||
}
|
||||
if 3 in s {
|
||||
println('dope')
|
||||
}
|
||||
if `a` in s {
|
||||
println("oh no :'(")
|
||||
}
|
||||
if 1 in 12 {
|
||||
println('right')
|
||||
}
|
||||
if Int(2) in m {
|
||||
println('yeah')
|
||||
}
|
||||
if Str2('3') in a_i {
|
||||
println('sure')
|
||||
}
|
||||
if Str3('2') in a_i {
|
||||
println('all right')
|
||||
}
|
||||
}
|
@ -1397,9 +1397,7 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||
g.expr_with_cast(node.right, node.right_type, info.elem_type)
|
||||
g.write(' })')
|
||||
}
|
||||
} else if (node.left_type == node.right_type) && node.left_type in [table.f32_type_idx,
|
||||
table.f64_type_idx
|
||||
] && node.op in [.eq, .ne] {
|
||||
} else if (node.left_type == node.right_type) && table.is_float(node.left_type) && node.op in [.eq, .ne] {
|
||||
// floats should be compared with epsilon
|
||||
if node.left_type == table.f64_type_idx {
|
||||
if node.op == .eq {
|
||||
|
@ -130,6 +130,17 @@ pub fn new_type_ptr(idx, nr_muls int) Type {
|
||||
return (nr_muls << 16) | u16(idx)
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn is_float(typ Type) bool {
|
||||
return type_idx(typ) in float_type_idxs
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn is_int(typ Type) bool {
|
||||
return type_idx(typ) in integer_type_idxs
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn is_number(typ Type) bool {
|
||||
return type_idx(typ) in number_type_idxs
|
||||
}
|
||||
|
@ -104,6 +104,24 @@ fn test_in_expression_with_string() {
|
||||
assert a == false
|
||||
}
|
||||
|
||||
fn test_in_expression_in_map() {
|
||||
m := {
|
||||
'one': 1
|
||||
'two': 2
|
||||
'three': 3
|
||||
}
|
||||
assert 'one' in m
|
||||
assert 'four' !in m
|
||||
}
|
||||
|
||||
fn test_in_expression_in_string() {
|
||||
s := 'abcd'
|
||||
assert 'a' in s
|
||||
assert 'ab' in s
|
||||
assert 'abcd' in s
|
||||
assert 'dbca' !in s
|
||||
}
|
||||
|
||||
fn test_optimized_in_expression() {
|
||||
mut a := false
|
||||
a = true && 2 in [1, 2]
|
||||
|
Loading…
Reference in New Issue
Block a user