checker: error if smaller signed == unsigned (#14078)
parent
5b58f4efbf
commit
13902a827b
|
@ -931,7 +931,7 @@ fn test_u64_keys() {
|
||||||
m[i]++
|
m[i]++
|
||||||
assert m[i] == i + 1
|
assert m[i] == i + 1
|
||||||
}
|
}
|
||||||
assert m.len == end
|
assert u64(m.len) == end
|
||||||
keys := m.keys()
|
keys := m.keys()
|
||||||
for i in u64(0) .. end {
|
for i in u64(0) .. end {
|
||||||
assert keys[i] == i
|
assert keys[i] == i
|
||||||
|
|
|
@ -919,7 +919,7 @@ fn test_u64_keys() {
|
||||||
m[i]++
|
m[i]++
|
||||||
assert m[i] == i + 1
|
assert m[i] == i + 1
|
||||||
}
|
}
|
||||||
assert m.len == end
|
assert u64(m.len) == end
|
||||||
keys := m.keys()
|
keys := m.keys()
|
||||||
for i in u64(0) .. end {
|
for i in u64(0) .. end {
|
||||||
assert keys[i] == i
|
assert keys[i] == i
|
||||||
|
|
|
@ -223,7 +223,7 @@ pub fn (mut ws Client) parse_frame_header() ?Frame {
|
||||||
buffer[bytes_read] = rbuff[0]
|
buffer[bytes_read] = rbuff[0]
|
||||||
bytes_read++
|
bytes_read++
|
||||||
// parses the first two header bytes to get basic frame information
|
// 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.fin = (buffer[0] & 0x80) == 0x80
|
||||||
frame.rsv1 = (buffer[0] & 0x40) == 0x40
|
frame.rsv1 = (buffer[0] & 0x40) == 0x40
|
||||||
frame.rsv2 = (buffer[0] & 0x20) == 0x20
|
frame.rsv2 = (buffer[0] & 0x20) == 0x20
|
||||||
|
@ -249,7 +249,7 @@ pub fn (mut ws Client) parse_frame_header() ?Frame {
|
||||||
break
|
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.header_len += 2
|
||||||
frame.payload_len = 0
|
frame.payload_len = 0
|
||||||
frame.payload_len |= int(u32(buffer[2]) << 8)
|
frame.payload_len |= int(u32(buffer[2]) << 8)
|
||||||
|
@ -259,7 +259,7 @@ pub fn (mut ws Client) parse_frame_header() ?Frame {
|
||||||
break
|
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
|
frame.header_len += 8
|
||||||
// these shift operators needs 64 bit on clang with -prod flag
|
// these shift operators needs 64 bit on clang with -prod flag
|
||||||
mut payload_len := u64(0)
|
mut payload_len := u64(0)
|
||||||
|
|
|
@ -41,7 +41,7 @@ fn test_open_file() {
|
||||||
mut file := os.open_file(filename, 'w+', 0o666) or { panic(err) }
|
mut file := os.open_file(filename, 'w+', 0o666) or { panic(err) }
|
||||||
file.write_string(hello) or { panic(err) }
|
file.write_string(hello) or { panic(err) }
|
||||||
file.close()
|
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') }
|
read_hello := os.read_file(filename) or { panic('error reading file $filename') }
|
||||||
assert hello == read_hello
|
assert hello == read_hello
|
||||||
os.rm(filename) or { panic(err) }
|
os.rm(filename) or { panic(err) }
|
||||||
|
@ -58,7 +58,7 @@ fn test_open_file_binary() {
|
||||||
bytes := hello.bytes()
|
bytes := hello.bytes()
|
||||||
unsafe { file.write_ptr(bytes.data, bytes.len) }
|
unsafe { file.write_ptr(bytes.data, bytes.len) }
|
||||||
file.close()
|
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') }
|
read_hello := os.read_bytes(filename) or { panic('error reading file $filename') }
|
||||||
assert bytes == read_hello
|
assert bytes == read_hello
|
||||||
os.rm(filename) or { panic(err) }
|
os.rm(filename) or { panic(err) }
|
||||||
|
@ -100,7 +100,7 @@ fn test_create_file() ? {
|
||||||
filename := './test1.txt'
|
filename := './test1.txt'
|
||||||
hello := 'hello world!'
|
hello := 'hello world!'
|
||||||
create_and_write_to_file(filename, hello) ?
|
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) }
|
os.rm(filename) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ fn test_write_and_read_string_to_file() {
|
||||||
filename := './test1.txt'
|
filename := './test1.txt'
|
||||||
hello := 'hello world!'
|
hello := 'hello world!'
|
||||||
os.write_file(filename, hello) or { panic(err) }
|
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') }
|
read_hello := os.read_file(filename) or { panic('error reading file $filename') }
|
||||||
assert hello == read_hello
|
assert hello == read_hello
|
||||||
os.rm(filename) or { panic(err) }
|
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).
|
// compare the length of the array with the file size (have to match).
|
||||||
unsafe { file_write.write_ptr(payload.data, 5) }
|
unsafe { file_write.write_ptr(payload.data, 5) }
|
||||||
file_write.close()
|
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 {
|
mut file_read := os.open(os.real_path(file_name)) or {
|
||||||
eprintln('failed to open file $file_name')
|
eprintln('failed to open file $file_name')
|
||||||
return
|
return
|
||||||
|
@ -792,7 +792,7 @@ fn test_truncate() ? {
|
||||||
mut f := os.create(filename) ?
|
mut f := os.create(filename) ?
|
||||||
f.write_string(hello) ?
|
f.write_string(hello) ?
|
||||||
f.close()
|
f.close()
|
||||||
assert hello.len == os.file_size(filename)
|
assert u64(hello.len) == os.file_size(filename)
|
||||||
newlen := u64(40000)
|
newlen := u64(40000)
|
||||||
os.truncate(filename, newlen) or { panic(err) }
|
os.truncate(filename, newlen) or { panic(err) }
|
||||||
assert newlen == os.file_size(filename)
|
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)
|
go count_one_cycle(mut counter, mut wg)
|
||||||
}
|
}
|
||||||
wg.wait()
|
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}')
|
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
|
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
|
rt := c.table.sym(right_type).name
|
||||||
c.error('negative value cannot be compared with `$rt`', node.left.pos)
|
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!
|
10 | _ = u8(-1) == -1 // false!
|
||||||
| ~~
|
| ~~
|
||||||
11 | _ = -1 == u16(-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`
|
vlib/v/checker/tests/compare_unsigned_signed.vv:11:6: error: negative value cannot be compared with `u16`
|
||||||
9 | // unsigned == literal
|
9 | // unsigned == literal
|
||||||
10 | _ = u8(-1) == -1 // false!
|
10 | _ = u8(-1) == -1 // false!
|
||||||
11 | _ = -1 == u16(-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
|
// unsigned == literal
|
||||||
_ = u8(-1) == -1 // false!
|
_ = u8(-1) == -1 // false!
|
||||||
_ = -1 == u16(-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() {
|
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(1))
|
||||||
assert int(1) > u64(0)
|
assert int(1) > u64(0)
|
||||||
|
@ -63,9 +63,9 @@ fn test_cmp_signed_and_u64() {
|
||||||
|
|
||||||
fn test_cmp_u64_and_signed() {
|
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(1))
|
||||||
assert u64(1) > int(0)
|
assert u64(1) > int(0)
|
||||||
|
|
|
@ -58,13 +58,13 @@ fn test_shift_operators() {
|
||||||
assert e == a
|
assert e == a
|
||||||
mut e3 := u64(1)
|
mut e3 := u64(1)
|
||||||
e3 <<= u32(i)
|
e3 <<= u32(i)
|
||||||
assert e3 == b
|
assert e3 == u64(b)
|
||||||
e3 >>= u32(i)
|
e3 >>= u32(i)
|
||||||
assert e == a
|
assert e == a
|
||||||
e3 <<= u64(i)
|
e3 <<= u64(i)
|
||||||
assert e3 == b
|
assert e3 == u64(b)
|
||||||
e3 >>= u64(i)
|
e3 >>= u64(i)
|
||||||
assert e3 == a
|
assert e3 == u64(a)
|
||||||
// Test shifts with custom int types
|
// Test shifts with custom int types
|
||||||
x := MyInt(2)
|
x := MyInt(2)
|
||||||
assert x << 2 == 8
|
assert x << 2 == 8
|
||||||
|
|
Loading…
Reference in New Issue