checker: error if smaller signed == unsigned (#14078)
parent
147e6e669f
commit
d8a5df9044
|
@ -931,7 +931,7 @@ fn test_u64_keys() {
|
|||
m[i]++
|
||||
assert m[i] == i + 1
|
||||
}
|
||||
assert m.len == end
|
||||
assert u64(m.len) == end
|
||||
keys := m.keys()
|
||||
for i in u64(0) .. end {
|
||||
assert keys[i] == i
|
||||
|
|
|
@ -919,7 +919,7 @@ fn test_u64_keys() {
|
|||
m[i]++
|
||||
assert m[i] == i + 1
|
||||
}
|
||||
assert m.len == end
|
||||
assert u64(m.len) == end
|
||||
keys := m.keys()
|
||||
for i in u64(0) .. end {
|
||||
assert keys[i] == i
|
||||
|
|
|
@ -223,7 +223,7 @@ pub fn (mut ws Client) parse_frame_header() ?Frame {
|
|||
buffer[bytes_read] = rbuff[0]
|
||||
bytes_read++
|
||||
// parses the first two header bytes to get basic frame information
|
||||
if bytes_read == u64(websocket.header_len_offset) {
|
||||
if bytes_read == websocket.header_len_offset {
|
||||
frame.fin = (buffer[0] & 0x80) == 0x80
|
||||
frame.rsv1 = (buffer[0] & 0x40) == 0x40
|
||||
frame.rsv2 = (buffer[0] & 0x20) == 0x20
|
||||
|
@ -249,7 +249,7 @@ pub fn (mut ws Client) parse_frame_header() ?Frame {
|
|||
break
|
||||
}
|
||||
}
|
||||
if frame.payload_len == 126 && bytes_read == u64(websocket.extended_payload16_end_byte) {
|
||||
if frame.payload_len == 126 && bytes_read == websocket.extended_payload16_end_byte {
|
||||
frame.header_len += 2
|
||||
frame.payload_len = 0
|
||||
frame.payload_len |= int(u32(buffer[2]) << 8)
|
||||
|
@ -259,7 +259,7 @@ pub fn (mut ws Client) parse_frame_header() ?Frame {
|
|||
break
|
||||
}
|
||||
}
|
||||
if frame.payload_len == 127 && bytes_read == u64(websocket.extended_payload64_end_byte) {
|
||||
if frame.payload_len == 127 && bytes_read == websocket.extended_payload64_end_byte {
|
||||
frame.header_len += 8
|
||||
// these shift operators needs 64 bit on clang with -prod flag
|
||||
mut payload_len := u64(0)
|
||||
|
|
|
@ -41,7 +41,7 @@ fn test_open_file() {
|
|||
mut file := os.open_file(filename, 'w+', 0o666) or { panic(err) }
|
||||
file.write_string(hello) or { panic(err) }
|
||||
file.close()
|
||||
assert hello.len == os.file_size(filename)
|
||||
assert u64(hello.len) == os.file_size(filename)
|
||||
read_hello := os.read_file(filename) or { panic('error reading file $filename') }
|
||||
assert hello == read_hello
|
||||
os.rm(filename) or { panic(err) }
|
||||
|
@ -58,7 +58,7 @@ fn test_open_file_binary() {
|
|||
bytes := hello.bytes()
|
||||
unsafe { file.write_ptr(bytes.data, bytes.len) }
|
||||
file.close()
|
||||
assert hello.len == os.file_size(filename)
|
||||
assert u64(hello.len) == os.file_size(filename)
|
||||
read_hello := os.read_bytes(filename) or { panic('error reading file $filename') }
|
||||
assert bytes == read_hello
|
||||
os.rm(filename) or { panic(err) }
|
||||
|
@ -100,7 +100,7 @@ fn test_create_file() ? {
|
|||
filename := './test1.txt'
|
||||
hello := 'hello world!'
|
||||
create_and_write_to_file(filename, hello) ?
|
||||
assert hello.len == os.file_size(filename)
|
||||
assert u64(hello.len) == os.file_size(filename)
|
||||
os.rm(filename) or { panic(err) }
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ fn test_write_and_read_string_to_file() {
|
|||
filename := './test1.txt'
|
||||
hello := 'hello world!'
|
||||
os.write_file(filename, hello) or { panic(err) }
|
||||
assert hello.len == os.file_size(filename)
|
||||
assert u64(hello.len) == os.file_size(filename)
|
||||
read_hello := os.read_file(filename) or { panic('error reading file $filename') }
|
||||
assert hello == read_hello
|
||||
os.rm(filename) or { panic(err) }
|
||||
|
@ -157,7 +157,7 @@ fn test_write_and_read_bytes() {
|
|||
// compare the length of the array with the file size (have to match).
|
||||
unsafe { file_write.write_ptr(payload.data, 5) }
|
||||
file_write.close()
|
||||
assert payload.len == os.file_size(file_name)
|
||||
assert u64(payload.len) == os.file_size(file_name)
|
||||
mut file_read := os.open(os.real_path(file_name)) or {
|
||||
eprintln('failed to open file $file_name')
|
||||
return
|
||||
|
@ -792,7 +792,7 @@ fn test_truncate() ? {
|
|||
mut f := os.create(filename) ?
|
||||
f.write_string(hello) ?
|
||||
f.close()
|
||||
assert hello.len == os.file_size(filename)
|
||||
assert u64(hello.len) == os.file_size(filename)
|
||||
newlen := u64(40000)
|
||||
os.truncate(filename, newlen) or { panic(err) }
|
||||
assert newlen == os.file_size(filename)
|
||||
|
|
|
@ -18,7 +18,7 @@ fn test_count_10_times_1_cycle_should_result_10_cycles_with_sync() {
|
|||
go count_one_cycle(mut counter, mut wg)
|
||||
}
|
||||
wg.wait()
|
||||
assert counter.counter == desired_iterations
|
||||
assert counter.counter == u64(desired_iterations)
|
||||
eprintln(' with synchronization the counter is: ${counter.counter:10} , expectedly == ${desired_iterations:10}')
|
||||
}
|
||||
|
||||
|
|
|
@ -689,3 +689,38 @@ pub fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr
|
|||
c.need_recheck_generic_fns = true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c &Checker) sizeof_integer(a ast.Type) int {
|
||||
t := if a in ast.unsigned_integer_type_idxs { a.flip_signedness() } else { a }
|
||||
r := match t {
|
||||
ast.char_type_idx, ast.i8_type_idx {
|
||||
1
|
||||
}
|
||||
ast.i16_type_idx {
|
||||
2
|
||||
}
|
||||
ast.int_type_idx {
|
||||
4
|
||||
}
|
||||
ast.rune_type_idx {
|
||||
4
|
||||
}
|
||||
ast.i64_type_idx {
|
||||
8
|
||||
}
|
||||
ast.isize_type_idx {
|
||||
if c.pref.m64 { 8 } else { 4 }
|
||||
}
|
||||
ast.int_literal_type {
|
||||
s := c.table.type_to_str(a)
|
||||
panic('`$s` has unknown size')
|
||||
0
|
||||
}
|
||||
else {
|
||||
s := c.table.type_to_str(a)
|
||||
panic('`$s` is not an integer')
|
||||
0
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
|
|
@ -640,6 +640,18 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
rt := c.table.sym(right_type).name
|
||||
c.error('negative value cannot be compared with `$rt`', node.left.pos)
|
||||
}
|
||||
} else if is_left_type_signed != is_right_type_signed
|
||||
&& left_type != ast.int_literal_type_idx
|
||||
&& right_type != ast.int_literal_type_idx {
|
||||
ls := c.sizeof_integer(left_type)
|
||||
rs := c.sizeof_integer(right_type)
|
||||
// prevent e.g. `u32 == i16` but not `u16 == i32` as max_u16 fits in i32
|
||||
// TODO u32 == i32, change < to <=
|
||||
if (is_left_type_signed && ls < rs) || (is_right_type_signed && rs < ls) {
|
||||
lt := c.table.sym(left_type).name
|
||||
rt := c.table.sym(right_type).name
|
||||
c.error('`$lt` cannot be compared with `$rt`', node.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,45 @@ vlib/v/checker/tests/compare_unsigned_signed.vv:10:16: error: `u8` cannot be com
|
|||
10 | _ = u8(-1) == -1 // false!
|
||||
| ~~
|
||||
11 | _ = -1 == u16(-1) // false!
|
||||
12 | }
|
||||
12 |
|
||||
vlib/v/checker/tests/compare_unsigned_signed.vv:11:6: error: negative value cannot be compared with `u16`
|
||||
9 | // unsigned == literal
|
||||
10 | _ = u8(-1) == -1 // false!
|
||||
11 | _ = -1 == u16(-1) // false!
|
||||
| ~~
|
||||
12 | }
|
||||
12 |
|
||||
13 | // smaller unsigned == signed, OK
|
||||
vlib/v/checker/tests/compare_unsigned_signed.vv:18:12: error: `i8` cannot be compared with `u16`
|
||||
16 |
|
||||
17 | // smaller signed == unsigned, NG
|
||||
18 | _ = i8(0) == u16(0)
|
||||
| ~~
|
||||
19 | _ = i16(0) != u32(0)
|
||||
20 | _ = int(0) == u64(0)
|
||||
vlib/v/checker/tests/compare_unsigned_signed.vv:19:13: error: `i16` cannot be compared with `u32`
|
||||
17 | // smaller signed == unsigned, NG
|
||||
18 | _ = i8(0) == u16(0)
|
||||
19 | _ = i16(0) != u32(0)
|
||||
| ~~
|
||||
20 | _ = int(0) == u64(0)
|
||||
21 | _ = i32(0) == u64(0) // FIXME
|
||||
vlib/v/checker/tests/compare_unsigned_signed.vv:20:13: error: `int` cannot be compared with `u64`
|
||||
18 | _ = i8(0) == u16(0)
|
||||
19 | _ = i16(0) != u32(0)
|
||||
20 | _ = int(0) == u64(0)
|
||||
| ~~
|
||||
21 | _ = i32(0) == u64(0) // FIXME
|
||||
22 | // swap order
|
||||
vlib/v/checker/tests/compare_unsigned_signed.vv:23:13: error: `u16` cannot be compared with `i8`
|
||||
21 | _ = i32(0) == u64(0) // FIXME
|
||||
22 | // swap order
|
||||
23 | _ = u16(0) == i8(0)
|
||||
| ~~
|
||||
24 | _ = u64(0) == i16(0)
|
||||
25 | }
|
||||
vlib/v/checker/tests/compare_unsigned_signed.vv:24:13: error: `u64` cannot be compared with `i16`
|
||||
22 | // swap order
|
||||
23 | _ = u16(0) == i8(0)
|
||||
24 | _ = u64(0) == i16(0)
|
||||
| ~~
|
||||
25 | }
|
||||
|
|
|
@ -9,4 +9,17 @@ fn main() {
|
|||
// unsigned == literal
|
||||
_ = u8(-1) == -1 // false!
|
||||
_ = -1 == u16(-1) // false!
|
||||
|
||||
// smaller unsigned == signed, OK
|
||||
_ = u16(-1) == int(-1)
|
||||
_ = int(-1) != u8(-1)
|
||||
|
||||
// smaller signed == unsigned, NG
|
||||
_ = i8(0) == u16(0)
|
||||
_ = i16(0) != u32(0)
|
||||
_ = int(0) == u64(0)
|
||||
_ = i32(0) == u64(0) // FIXME
|
||||
// swap order
|
||||
_ = u16(0) == i8(0)
|
||||
_ = u64(0) == i16(0)
|
||||
}
|
||||
|
|
|
@ -42,9 +42,9 @@ fn test_cmp_u32_and_signed() {
|
|||
|
||||
fn test_cmp_signed_and_u64() {
|
||||
// ==
|
||||
assert int(1) == u64(1)
|
||||
// assert int(1) == u64(1)
|
||||
// !=
|
||||
assert int(1) != u64(2)
|
||||
// assert int(1) != u64(2)
|
||||
// >
|
||||
assert !(int(1) > u64(1))
|
||||
assert int(1) > u64(0)
|
||||
|
@ -63,9 +63,9 @@ fn test_cmp_signed_and_u64() {
|
|||
|
||||
fn test_cmp_u64_and_signed() {
|
||||
// ==
|
||||
assert u64(1) == int(1)
|
||||
// assert u64(1) == int(1)
|
||||
// !=
|
||||
assert u64(2) != int(1)
|
||||
// assert u64(2) != int(1)
|
||||
// >
|
||||
assert !(u64(1) > int(1))
|
||||
assert u64(1) > int(0)
|
||||
|
|
|
@ -58,13 +58,13 @@ fn test_shift_operators() {
|
|||
assert e == a
|
||||
mut e3 := u64(1)
|
||||
e3 <<= u32(i)
|
||||
assert e3 == b
|
||||
assert e3 == u64(b)
|
||||
e3 >>= u32(i)
|
||||
assert e == a
|
||||
e3 <<= u64(i)
|
||||
assert e3 == b
|
||||
assert e3 == u64(b)
|
||||
e3 >>= u64(i)
|
||||
assert e3 == a
|
||||
assert e3 == u64(a)
|
||||
// Test shifts with custom int types
|
||||
x := MyInt(2)
|
||||
assert x << 2 == 8
|
||||
|
|
Loading…
Reference in New Issue