From 076089d3c53ef5cd43734aea2897f2a7ad129895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kr=C3=BCger?= <45282134+UweKrueger@users.noreply.github.com> Date: Mon, 1 Jun 2020 21:15:59 +0200 Subject: [PATCH] checker: apply stricter type checks to function args and return types --- vlib/bitfield/bitfield.v | 2 +- vlib/bitfield/bitfield_test.v | 26 ++--- vlib/builtin/map.v | 12 +- vlib/builtin/sorted_map.v | 4 +- vlib/builtin/string.v | 6 +- vlib/builtin/utf8.v | 2 +- vlib/freetype/freetype.v | 2 +- vlib/gg/gg.v | 4 +- vlib/glm/glm.v | 2 +- vlib/hash/crc32/crc32.v | 2 +- vlib/hash/crc32/crc32_test.v | 2 +- vlib/math/bits/bits.v | 4 +- vlib/math/fractions/fraction.v | 2 +- vlib/net/websocket/ws.v | 4 +- vlib/readline/readline_linux.c.v | 4 +- vlib/time/format_test.v | 2 +- vlib/time/misc/misc.v | 2 +- vlib/time/time.v | 6 +- vlib/v/checker/check_types.v | 108 +++++++++--------- vlib/v/checker/checker.v | 6 +- .../checker/tests/function_wrong_arg_type.out | 7 ++ .../checker/tests/function_wrong_arg_type.vv | 9 ++ .../tests/function_wrong_return_type.out | 6 + .../tests/function_wrong_return_type.vv | 8 ++ vlib/v/gen/x64/gen.v | 10 +- vlib/v/tests/fn_high_test.v | 6 +- 26 files changed, 141 insertions(+), 107 deletions(-) create mode 100644 vlib/v/checker/tests/function_wrong_arg_type.out create mode 100644 vlib/v/checker/tests/function_wrong_arg_type.vv create mode 100644 vlib/v/checker/tests/function_wrong_return_type.out create mode 100644 vlib/v/checker/tests/function_wrong_return_type.vv diff --git a/vlib/bitfield/bitfield.v b/vlib/bitfield/bitfield.v index b05db4d733..e7ae271145 100644 --- a/vlib/bitfield/bitfield.v +++ b/vlib/bitfield/bitfield.v @@ -84,7 +84,7 @@ pub fn (instance BitField) get_bit(bitnr int) int { if bitnr >= instance.size { return 0 } - return (instance.field[bitslot(bitnr)] >> (bitnr % slot_size)) & u32(1) + return int((instance.field[bitslot(bitnr)] >> (bitnr % slot_size)) & u32(1)) } // set_bit sets bit number 'bit_nr' to 1 (count from 0). diff --git a/vlib/bitfield/bitfield_test.v b/vlib/bitfield/bitfield_test.v index 71c679418a..9ded88c4e3 100644 --- a/vlib/bitfield/bitfield_test.v +++ b/vlib/bitfield/bitfield_test.v @@ -19,7 +19,7 @@ fn test_bf_set_clear_toggle_get() { } fn test_bf_and_not_or_xor() { - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut input1 := bitfield.new(len) mut input2 := bitfield.new(len) @@ -46,7 +46,7 @@ fn test_bf_and_not_or_xor() { } fn test_clone_cmp() { - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut input := bitfield.new(len) for i in 0..len { @@ -60,7 +60,7 @@ fn test_clone_cmp() { } fn test_slice_join() { - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut input := bitfield.new(len) for i in 0..len { @@ -83,7 +83,7 @@ fn test_slice_join() { } fn test_pop_count() { - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut count0 := 0 mut input := bitfield.new(len) @@ -98,7 +98,7 @@ fn test_pop_count() { } fn test_hamming() { - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut count := 0 mut input1 := bitfield.new(len) @@ -138,7 +138,7 @@ fn test_bf_from_bytes() { } fn test_bf_from_str() { - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut input := '' for _ in 0..len { @@ -160,7 +160,7 @@ fn test_bf_from_str() { } fn test_bf_bf2str() { - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut input := bitfield.new(len) for i in 0..len { @@ -188,7 +188,7 @@ fn test_bf_bf2str() { } fn test_bf_set_all() { - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut input := bitfield.new(len) input.set_all() @@ -202,7 +202,7 @@ fn test_bf_set_all() { } fn test_bf_clear_all() { - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut input := bitfield.new(len) for i in 0..len { @@ -221,7 +221,7 @@ fn test_bf_clear_all() { } fn test_bf_reverse() { - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut input := bitfield.new(len) for i in 0..len { @@ -241,7 +241,7 @@ fn test_bf_reverse() { } fn test_bf_resize() { - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut input := bitfield.new(rand.next(len) + 1) for _ in 0..100 { @@ -259,7 +259,7 @@ fn test_bf_pos() { * all haystacks here contain exactly one instanse of needle, * so search should return non-negative-values **/ - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut result := 1 for i := 1; i < len; i++ { // needle size @@ -322,7 +322,7 @@ fn test_bf_rotate() { } fn test_bf_printing(){ - rand.seed(time.now().unix) + rand.seed(int(time.now().unix)) len := 80 mut input := bitfield.new(len) for i in 0..len { diff --git a/vlib/builtin/map.v b/vlib/builtin/map.v index 9d60e2fad3..2ca00ea647 100644 --- a/vlib/builtin/map.v +++ b/vlib/builtin/map.v @@ -111,7 +111,7 @@ fn new_dense_array(value_bytes int) DenseArray { cap: 8 size: 0 deletes: 0 - keys: &string(malloc(8 * sizeof(string))) + keys: &string(malloc(int(8 * sizeof(string)))) values: malloc(8 * value_bytes) } } @@ -198,7 +198,7 @@ fn new_map_1(value_bytes int) map { cached_hashbits: max_cached_hashbits shift: init_log_capicity key_values: new_dense_array(value_bytes) - metas: &u32(vcalloc(sizeof(u32) * (init_capicity + extra_metas_inc))) + metas: &u32(vcalloc(int(sizeof(u32) * (init_capicity + extra_metas_inc)))) extra_metas: extra_metas_inc size: 0 } @@ -323,7 +323,7 @@ fn (mut m map) rehash() { fn (mut m map) cached_rehash(old_cap u32) { old_metas := m.metas - m.metas = &u32(vcalloc(sizeof(u32) * (m.cap + 2 + m.extra_metas))) + m.metas = &u32(vcalloc(int(sizeof(u32) * (m.cap + 2 + m.extra_metas)))) old_extra_metas := m.extra_metas for i := u32(0); i <= old_cap + old_extra_metas; i += 2 { if old_metas[i] == 0 { @@ -430,8 +430,8 @@ pub fn (d DenseArray) clone() DenseArray { cap: d.cap size: d.size deletes: d.deletes - keys: &string(malloc(d.cap * sizeof(string))) - values: byteptr(malloc(d.cap * u32(d.value_bytes))) + keys: &string(malloc(int(d.cap * sizeof(string)))) + values: byteptr(malloc(int(d.cap * u32(d.value_bytes)))) } C.memcpy(res.keys, d.keys, d.cap * sizeof(string)) C.memcpy(res.values, d.values, d.cap * u32(d.value_bytes)) @@ -447,7 +447,7 @@ pub fn (m map) clone() map { cached_hashbits: m.cached_hashbits shift: m.shift key_values: m.key_values.clone() - metas: &u32(malloc(metas_size)) + metas: &u32(malloc(int(metas_size))) extra_metas: m.extra_metas size: m.size } diff --git a/vlib/builtin/sorted_map.v b/vlib/builtin/sorted_map.v index 93538a9af3..2e35c7ee57 100644 --- a/vlib/builtin/sorted_map.v +++ b/vlib/builtin/sorted_map.v @@ -121,13 +121,13 @@ fn (mut n mapnode) split_child(child_index int, y mut mapnode) { z.values[j] = y.values[j + degree] } if !isnil(y.children) { - z.children = &voidptr(malloc(children_bytes)) + z.children = &voidptr(malloc(int(children_bytes))) for jj := degree - 1; jj >= 0; jj-- { z.children[jj] = y.children[jj + degree] } } if isnil(n.children) { - n.children = &voidptr(malloc(children_bytes)) + n.children = &voidptr(malloc(int(children_bytes))) } n.children[n.size + 1] = n.children[n.size] for j := n.size; j > child_index; j-- { diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 32a8b8bff9..72f89f115d 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -982,7 +982,7 @@ pub fn (s string) ustring() ustring { // runes will have at least s.len elements, save reallocations // TODO use VLA for small strings? - runes: __new_array(0, s.len, sizeof(int)) + runes: __new_array(0, s.len, int(sizeof(int))) } for i := 0; i < s.len; i++ { char_len := utf8_char_len(s.str[i]) @@ -1000,7 +1000,7 @@ __global g_ustring_runes []int pub fn (s string) ustring_tmp() ustring { if g_ustring_runes.len == 0 { - g_ustring_runes = __new_array(0, 128, sizeof(int)) + g_ustring_runes = __new_array(0, 128, int(sizeof(int))) } mut res := ustring{ s: s @@ -1048,7 +1048,7 @@ fn (u ustring) ge(a ustring) bool { pub fn (u ustring) add(a ustring) ustring { mut res := ustring{ s: u.s + a.s - runes: __new_array(0, u.s.len + a.s.len, sizeof(int)) + runes: __new_array(0, u.s.len + a.s.len, int(sizeof(int))) } mut j := 0 for i := 0; i < u.s.len; i++ { diff --git a/vlib/builtin/utf8.v b/vlib/builtin/utf8.v index 8273620f68..e85eec4cee 100644 --- a/vlib/builtin/utf8.v +++ b/vlib/builtin/utf8.v @@ -227,7 +227,7 @@ fn utf8_str_visible_length(s string) int { // Reads an utf8 character from standard input pub fn utf8_getchar() int { c := C.getchar() - len := utf8_len(~c) + len := utf8_len(byte(~c)) if c < 0 { return 0 } diff --git a/vlib/freetype/freetype.v b/vlib/freetype/freetype.v index 42e53fbee2..6ce352e4ee 100644 --- a/vlib/freetype/freetype.v +++ b/vlib/freetype/freetype.v @@ -183,7 +183,7 @@ pub fn new_context(cfg gg.Cfg) &FreeType { C.glBlendFunc(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA) shader := gl.new_shader('text') shader.use() - projection := glm.ortho(0, width, 0, height) // 0 at BOT + projection := glm.ortho(0, f32(width), 0, f32(height)) // 0 at BOT shader.set_mat4('projection', projection) // FREETYPE ft := C.FT_Library{} diff --git a/vlib/gg/gg.v b/vlib/gg/gg.v index 7b5e9ff2e8..b741fe6e12 100644 --- a/vlib/gg/gg.v +++ b/vlib/gg/gg.v @@ -100,7 +100,7 @@ pub fn new_context(cfg Cfg) &GG { shader := gl.new_shader('simple') shader.use() if cfg.use_ortho { - projection := glm.ortho(0, cfg.width, cfg.height, 0) + projection := glm.ortho(0, f32(cfg.width), f32(cfg.height), 0) shader.set_mat4('projection', projection) } else { @@ -304,7 +304,7 @@ fn todo_remove_me(cfg Cfg, scale int) { //# glBlendFunc(C.GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); shader := gl.new_shader('text') shader.use() - projection := glm.ortho(0, width, 0, height)// 0 at BOT + projection := glm.ortho(0, f32(width), 0, f32(height))// 0 at BOT // projection_new := ortho(0, width, 0, height)// 0 at BOT // projection := gl.ortho(0, width,height,0) // 0 at TOP shader.set_mat4('projection', projection) diff --git a/vlib/glm/glm.v b/vlib/glm/glm.v index 9db44dbdf1..40b5c3878d 100644 --- a/vlib/glm/glm.v +++ b/vlib/glm/glm.v @@ -398,7 +398,7 @@ fn ortho_js(left, right, bottom, top f32) &f32 { bt := 1.0 / (bottom - top) nf := f32(1.0) / 1.0// (mynear -myfar) mut out := &f32(0) - unsafe { out = &f32( malloc (sizeof(f32) * 16)) } + unsafe { out = &f32( malloc (int(sizeof(f32) * 16))) } out[0] = -2.0 * lr out[1] = 0 out[2] = 0 diff --git a/vlib/hash/crc32/crc32.v b/vlib/hash/crc32/crc32.v index 5ab8ef2353..5babc6ef69 100644 --- a/vlib/hash/crc32/crc32.v +++ b/vlib/hash/crc32/crc32.v @@ -58,6 +58,6 @@ pub fn new(poly int) &Crc32 { // calculate crc32 using ieee pub fn sum(b []byte) u32 { - c := new(ieee) + c := new(int(ieee)) return c.sum32(b) } diff --git a/vlib/hash/crc32/crc32_test.v b/vlib/hash/crc32/crc32_test.v index 777dd10fb2..bea6764d0d 100644 --- a/vlib/hash/crc32/crc32_test.v +++ b/vlib/hash/crc32/crc32_test.v @@ -7,7 +7,7 @@ fn test_hash_crc32() { assert sum1.hex() == '483f8cf0' - c := crc32.new(crc32.ieee) + c := crc32.new(int(crc32.ieee)) b2 := 'testing crc32 again'.bytes() sum2 := c.checksum(b2) assert sum2 == u32(1420327025) diff --git a/vlib/math/bits/bits.v b/vlib/math/bits/bits.v index e8eaf40149..7c5c96e40f 100644 --- a/vlib/math/bits/bits.v +++ b/vlib/math/bits/bits.v @@ -208,7 +208,7 @@ pub fn reverse_32(x u32) u32 { mut y := ((x>>u32(1) & (m0 & max_u32)) | ((x & (m0 & max_u32))<<1)) y = ((y>>u32(2) & (m1 & max_u32)) | ((y & (m1 & max_u32))<>u32(4) & (m2 & max_u32)) | ((y & (m2 & max_u32))<>u32(8) & (m3 & max_u32)) | ((x & (m3 & max_u32))<>16) | (y<<16) + return u32((y>>16) | (y<<16)) } // reverse_bytes_64 returns the value of x with its bytes in reversed order. diff --git a/vlib/math/fractions/fraction.v b/vlib/math/fractions/fraction.v index e199b29147..48d6701723 100644 --- a/vlib/math/fractions/fraction.v +++ b/vlib/math/fractions/fraction.v @@ -240,7 +240,7 @@ fn cmp_f64s(a, b f64) int { // Two integers are safe to multiply when their bit lengths // sum up to less than 64 (conservative estimate). fn safe_to_multiply(a, b i64) bool { - return (bits.len_64(abs(a)) + bits.len_64(abs(b))) < 64 + return (bits.len_64(u64(abs(a))) + bits.len_64(u64(abs(b)))) < 64 } fn cmp(f1, f2 Fraction) int { diff --git a/vlib/net/websocket/ws.v b/vlib/net/websocket/ws.v index 3a4fd05e9d..ee81ef93ea 100644 --- a/vlib/net/websocket/ws.v +++ b/vlib/net/websocket/ws.v @@ -418,7 +418,7 @@ pub fn (mut ws Client) read() int { } else if frame.opcode in [.text_frame, .binary_frame] { data_node: l.d('read: recieved text_frame or binary_frame') - mut payload := malloc(sizeof(byte) * u32(payload_len) + 1) + mut payload := malloc(int(sizeof(byte) * u32(payload_len) + 1)) if payload == 0 { l.f('out of memory') } @@ -438,7 +438,7 @@ pub fn (mut ws Client) read() int { size += f.len } } - mut pl := malloc(sizeof(byte) * u32(size)) + mut pl := malloc(int(sizeof(byte) * u32(size))) if pl == 0 { l.f('out of memory') } diff --git a/vlib/readline/readline_linux.c.v b/vlib/readline/readline_linux.c.v index a472c4a800..09b64ebc5c 100644 --- a/vlib/readline/readline_linux.c.v +++ b/vlib/readline/readline_linux.c.v @@ -203,8 +203,8 @@ match c { `B` { return .history_next } `A` { return .history_previous } `1` { return r.analyse_extended_control() } - `2` { return r.analyse_extended_control_no_eat(sequence) } - `3` { return r.analyse_extended_control_no_eat(sequence) } + `2` { return r.analyse_extended_control_no_eat(byte(sequence)) } + `3` { return r.analyse_extended_control_no_eat(byte(sequence)) } else {} } } diff --git a/vlib/time/format_test.v b/vlib/time/format_test.v index b3924b04e7..2978a3f4ee 100644 --- a/vlib/time/format_test.v +++ b/vlib/time/format_test.v @@ -15,7 +15,7 @@ const ( fn test_now_format() { t := time.now() u := t.unix - assert t.format() == time.unix(u).format() + assert t.format() == time.unix(int(u)).format() } fn test_format() { diff --git a/vlib/time/misc/misc.v b/vlib/time/misc/misc.v index aa4b7efb56..a004ecc8f8 100644 --- a/vlib/time/misc/misc.v +++ b/vlib/time/misc/misc.v @@ -8,5 +8,5 @@ const ( ) // random returns a random time struct in *the past*. pub fn random() time.Time { - return time.unix(rand.next(start_time_unix)) + return time.unix(rand.next(int(start_time_unix))) } diff --git a/vlib/time/time.v b/vlib/time/time.v index 8449b230a6..7dae0906bf 100644 --- a/vlib/time/time.v +++ b/vlib/time/time.v @@ -118,7 +118,7 @@ pub fn new_time(t Time) Time { // unix_time returns Unix time. pub fn (t Time) unix_time() int { if t.unix != 0 { - return t.unix + return int(t.unix) } tt := C.tm{ tm_sec: t.second @@ -134,12 +134,12 @@ pub fn (t Time) unix_time() int { // add_seconds returns a new time struct with an added number of seconds. pub fn (t Time) add_seconds(seconds int) Time { // TODO Add(d time.Duration) - return unix(t.unix + u64(seconds)) + return unix(int(t.unix + u64(seconds))) } // add_days returns a new time struct with an added number of days. pub fn (t Time) add_days(days int) Time { - return unix(t.unix + u64(i64(days) * 3600 * 24)) + return unix(int(t.unix + u64(i64(days) * 3600 * 24))) } // since returns a number of seconds elapsed since a given time. diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 543702a82a..3aec2fbbe8 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -6,7 +6,7 @@ module checker import v.table import v.token -pub fn (c &Checker) check_types(got, expected table.Type) bool { +pub fn (c &Checker) check_basic(got, expected table.Type) bool { t := c.table got_idx := t.unalias_num_type(got).idx() exp_idx := t.unalias_num_type(expected).idx() @@ -114,10 +114,10 @@ pub fn (c &Checker) check_types(got, expected table.Type) bool { exp_fn := exp_info.func // we are using check() to compare return type & args as they might include // functions themselves. TODO: optimize, only use check() when needed - if got_fn.args.len == exp_fn.args.len && c.check_types(got_fn.return_type, exp_fn.return_type) { + if got_fn.args.len == exp_fn.args.len && c.check_basic(got_fn.return_type, exp_fn.return_type) { for i, got_arg in got_fn.args { exp_arg := exp_fn.args[i] - if !c.check_types(got_arg.typ, exp_arg.typ) { + if !c.check_basic(got_arg.typ, exp_arg.typ) { return false } } @@ -157,55 +157,57 @@ pub fn (c &Checker) promote(left_type, right_type table.Type) table.Type { return left_type // strings, self defined operators } if right_type.is_number() && left_type.is_number() { - // sort the operands to save time - mut type_hi := left_type - mut type_lo := right_type - if type_hi.idx() < type_lo.idx() { - tmp := type_hi - type_hi = type_lo - type_lo = tmp - } - idx_hi := type_hi.idx() - idx_lo := type_lo.idx() - // the following comparisons rely on the order of the indices in atypes.v - if idx_hi == table.any_int_type_idx { - return type_lo - } else if idx_hi == table.any_flt_type_idx { - if idx_lo in table.float_type_idxs { - return type_lo - } else { - return table.void_type - } - } else if type_hi.is_float() { - if idx_hi == table.f32_type_idx { - if idx_lo in [table.int_type_idx, table.i64_type_idx, table.u32_type_idx, table.u64_type_idx] { - return table.void_type - } else { - return type_hi - } - } else { // f64, any_flt - if idx_lo in [table.i64_type_idx, table.u64_type_idx] { - return table.void_type - } else { - return type_hi - } - } - } else if idx_lo >= table.byte_type_idx { // both operands are unsigned - return type_hi - } else if idx_lo >= table.i8_type_idx && idx_hi <= table.i64_type_idx { // both signed - return type_hi - } else if idx_hi - idx_lo < (table.byte_type_idx - table.i8_type_idx) { - return type_lo // conversion unsigned -> signed if signed type is larger - } else { - return table.void_type // conversion signed -> unsigned not allowed - } + return c.promote_num(left_type, right_type) } else { return left_type // default to left if not automatic promotion possible } } -// TODO: promote(), assign_check(), symmetric_check() and check() overlap - should be rearranged -pub fn (c &Checker) assign_check(got, expected table.Type) bool { +fn (c &Checker) promote_num(left_type, right_type table.Type) table.Type { + // sort the operands to save time + mut type_hi := left_type + mut type_lo := right_type + if type_hi.idx() < type_lo.idx() { + type_hi, type_lo = type_lo, type_hi + } + idx_hi := type_hi.idx() + idx_lo := type_lo.idx() + // the following comparisons rely on the order of the indices in atypes.v + if idx_hi == table.any_int_type_idx { + return type_lo + } else if idx_hi == table.any_flt_type_idx { + if idx_lo in table.float_type_idxs { + return type_lo + } else { + return table.void_type + } + } else if type_hi.is_float() { + if idx_hi == table.f32_type_idx { + if idx_lo in [table.int_type_idx, table.i64_type_idx, table.u32_type_idx, table.u64_type_idx] { + return table.void_type + } else { + return type_hi + } + } else { // f64, any_flt + if idx_lo in [table.i64_type_idx, table.u64_type_idx] { + return table.void_type + } else { + return type_hi + } + } + } else if idx_lo >= table.byte_type_idx { // both operands are unsigned + return type_hi + } else if idx_lo >= table.i8_type_idx && idx_hi <= table.i64_type_idx { // both signed + return type_hi + } else if idx_hi - idx_lo < (table.byte_type_idx - table.i8_type_idx) { + return type_lo // conversion unsigned -> signed if signed type is larger + } else { + return table.void_type // conversion signed -> unsigned not allowed + } +} + +// TODO: promote(), check_types(), symmetric_check() and check() overlap - should be rearranged +pub fn (c &Checker) check_types(got, expected table.Type) bool { exp_idx := expected.idx() got_idx := got.idx() if exp_idx == got_idx { @@ -228,12 +230,14 @@ pub fn (c &Checker) assign_check(got, expected table.Type) bool { return true } } - if !c.check_types(got, expected) { // TODO: this should go away... + if !c.check_basic(got, expected) { // TODO: this should go away... return false } - if c.promote(expected, got) != expected { - println('could not promote ${c.table.get_type_symbol(got).name} to ${c.table.get_type_symbol(expected).name}') - return false + if got.is_number() && expected.is_number() { + if c.promote_num(expected, got) != expected { + // println('could not promote ${c.table.get_type_symbol(got).name} to ${c.table.get_type_symbol(expected).name}') + return false + } } return true } @@ -252,5 +256,5 @@ pub fn (c &Checker) symmetric_check(left, right table.Type) bool { return true } } - return c.check_types(left, right) + return c.check_basic(left, right) } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 5c964a3e28..4a9cf8e48f 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -369,7 +369,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type { expr_type := c.expr(field.expr) expr_type_sym := c.table.get_type_symbol(expr_type) field_type_sym := c.table.get_type_symbol(info_field.typ) - if !c.assign_check(expr_type, info_field.typ) { + if !c.check_types(expr_type, info_field.typ) { c.error('cannot assign `$expr_type_sym.name` as `$field_type_sym.name` for field `$info_field.name`', field.pos) } @@ -698,7 +698,7 @@ fn (mut c Checker) assign_expr(mut assign_expr ast.AssignExpr) { else {} } // Dual sides check (compatibility check) - if !c.assign_check(right_type, left_type) { + if !c.check_types(right_type, left_type) { left_type_sym := c.table.get_type_symbol(left_type) right_type_sym := c.table.get_type_symbol(right_type) c.error('cannot assign `$right_type_sym.name` to variable `${assign_expr.left.str()}` of type `$left_type_sym.name`', @@ -1434,7 +1434,7 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type { c.expected_type = elem_type continue } - if !c.check_types(elem_type, typ) { + if !c.check_types(typ, elem_type) { elem_type_sym := c.table.get_type_symbol(elem_type) c.error('expected array element with type `$elem_type_sym.name`', array_init.pos) } diff --git a/vlib/v/checker/tests/function_wrong_arg_type.out b/vlib/v/checker/tests/function_wrong_arg_type.out new file mode 100644 index 0000000000..b2efcac8b8 --- /dev/null +++ b/vlib/v/checker/tests/function_wrong_arg_type.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/function_wrong_arg_type.v:7:7: error: cannot use type `f64` as type `int` in argument 1 to `f` + 5 | fn main() { + 6 | a := 12.3 + 7 | q := f(a) + | ~~~~ + 8 | println('$q') + 9 | } diff --git a/vlib/v/checker/tests/function_wrong_arg_type.vv b/vlib/v/checker/tests/function_wrong_arg_type.vv new file mode 100644 index 0000000000..6cd3fbb454 --- /dev/null +++ b/vlib/v/checker/tests/function_wrong_arg_type.vv @@ -0,0 +1,9 @@ +fn f(x int) int { + return x+x +} + +fn main() { + a := 12.3 + q := f(a) + println('$q') +} diff --git a/vlib/v/checker/tests/function_wrong_return_type.out b/vlib/v/checker/tests/function_wrong_return_type.out new file mode 100644 index 0000000000..25f13687d7 --- /dev/null +++ b/vlib/v/checker/tests/function_wrong_return_type.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/function_wrong_return_type.v:2:9: error: cannot use `any_float` as type `int` in return argument + 1 | fn h() int { + 2 | return 3.14 + | ~~~~ + 3 | } + 4 | diff --git a/vlib/v/checker/tests/function_wrong_return_type.vv b/vlib/v/checker/tests/function_wrong_return_type.vv new file mode 100644 index 0000000000..0c47628e7e --- /dev/null +++ b/vlib/v/checker/tests/function_wrong_return_type.vv @@ -0,0 +1,8 @@ +fn h() int { + return 3.14 +} + +fn main() { + d := h() + println('$d') +} diff --git a/vlib/v/gen/x64/gen.v b/vlib/v/gen/x64/gen.v index a73a0745e5..4232000cf8 100644 --- a/vlib/v/gen/x64/gen.v +++ b/vlib/v/gen/x64/gen.v @@ -225,7 +225,7 @@ fn (mut g Gen) jne() int { pos := g.pos() g.write32(placeholder) g.println('jne') - return pos + return int(pos) } fn (mut g Gen) jge() int { @@ -233,7 +233,7 @@ fn (mut g Gen) jge() int { pos := g.pos() g.write32(placeholder) g.println('jne') - return pos + return int(pos) } fn (mut g Gen) jmp(addr int) { @@ -669,7 +669,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { // The value is the relative address, difference between current position and the location // after `jne 00 00 00 00` // println('after if g.pos=$g.pos() jneaddr=$jne_addr') - g.write32_at(jne_addr, g.pos() - jne_addr - 4) // 4 is for "00 00 00 00" + g.write32_at(jne_addr, int(g.pos() - jne_addr - 4)) // 4 is for "00 00 00 00" } fn (mut g Gen) for_stmt(node ast.ForStmt) { @@ -690,9 +690,9 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) { g.stmts(node.stmts) // Go back to `cmp ...` // Diff between `jmp 00 00 00 00 X` and `cmp` - g.jmp(0xffffffff - (g.pos() + 5 - start) + 1) + g.jmp(int(0xffffffff - (g.pos() + 5 - start) + 1)) // Update the jump addr to current pos - g.write32_at(jump_addr, g.pos() - jump_addr - 4) // 4 is for "00 00 00 00" + g.write32_at(jump_addr, int(g.pos() - jump_addr - 4)) // 4 is for "00 00 00 00" g.println('jpm after for') } diff --git a/vlib/v/tests/fn_high_test.v b/vlib/v/tests/fn_high_test.v index 7ce8802866..8f70aa4982 100644 --- a/vlib/v/tests/fn_high_test.v +++ b/vlib/v/tests/fn_high_test.v @@ -23,7 +23,7 @@ fn high_fn_multi_return(a int, b fn (c []int, d []string) ([]int, []string)) { fn high_fn_return_single_anon() (fn(int)f32) { _ := 1 correct := fn(n int)f32 { - return n * n + return f32(n * n) } return correct } @@ -36,7 +36,7 @@ fn high_fn_return_multi_anons() (fn(int)f32, fn(int)string) { return '$n' } correct_first := fn(n int)f32 { - return n * n + return f32(n * n) } // parsing trap _ := fn(n int)[]int { @@ -110,7 +110,7 @@ fn simple_fn1() int { } fn simple_fn2(n f32) (int, string) { - return 1 + n, "fish" + return int(1 + n), "fish" } fn test_assigning_fns() {