diff --git a/cmd/tools/modules/testing/common.v b/cmd/tools/modules/testing/common.v index 1398663f71..ef4ebf2956 100644 --- a/cmd/tools/modules/testing/common.v +++ b/cmd/tools/modules/testing/common.v @@ -50,7 +50,7 @@ pub fn new_test_session(_vargs string) TestSession { skip_files: skip_files vargs: vargs show_ok_tests: !_vargs.contains('-silent') - message_handler: 0 + message_handler: &TestMessageHandler(0) } } diff --git a/doc/docs.md b/doc/docs.md index 7980f8cb6d..6e03f1fdc5 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -269,6 +269,8 @@ rune // represents a Unicode code point f32 f64 +any_int, any_float // internal intermediate types of number literals + byteptr // these two are mostly used for C interop voidptr @@ -277,6 +279,27 @@ any // similar to C's void* and Go's interface{} Please note that unlike C and Go, `int` is always a 32 bit integer. +There is an exceptions to the rule that all operators +in V must have values of the same type on both sides. A small primitive type +on one side can be automatically promoted if it fits +completely into the data range of the type on the other side, i.e. when +the promotion does not result in any data loss. +These are the allowed possibilities: + +``` + i8 → i16 → int → i64 + ↘ ↘ + f32 → f64 + ↗ ↗ + byte → u16 → u32 → u64 ⬎ + ↘ ↘ ↘ ptr + i8 → i16 → int → i64 ⬏ +``` +An `int` value for example can be automatically promoted to `f64` +or `i64` but not to `f32` or `u32`. (`f32` would mean precission +loss for large values and `u32` would mean loss of the sign for +negative values). + ## Strings ```v diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v index 7c300eb68c..2b036f9786 100644 --- a/vlib/builtin/array.v +++ b/vlib/builtin/array.v @@ -360,9 +360,9 @@ pub fn (b []byte) hex() string { mut dst_i := 0 for i in b { n0 := i >> 4 - hex[dst_i++] = if n0 < 10 { n0 + `0` } else { n0 + 87 } + hex[dst_i++] = if n0 < 10 { n0 + `0` } else { n0 + byte(87) } n1 := i & 0xF - hex[dst_i++] = if n1 < 10 { n1 + `0` } else { n1 + 87 } + hex[dst_i++] = if n1 < 10 { n1 + `0` } else { n1 + byte(87) } } hex[dst_i] = `\0` return tos(hex,dst_i) diff --git a/vlib/builtin/array_test.v b/vlib/builtin/array_test.v index cd7a883a04..7702a93935 100644 --- a/vlib/builtin/array_test.v +++ b/vlib/builtin/array_test.v @@ -468,6 +468,10 @@ fn test_in() { assert !(0 in a) assert 0 !in a assert 4 !in a + b := [1, 4, 0] + c := [3, 6, 2, 0] + assert 0 in b + assert 0 in c } fn sum(prev int, curr int) int { @@ -557,7 +561,7 @@ fn test_map() { assert strs.map(it.to_upper()) == ['V', 'IS', 'AWESOME'] assert strs.map(it == 'awesome') == [false, false, true] assert strs.map(it.len in nums) == [true, true, false] - assert strs.map(7) == [7, 7, 7] + assert strs.map(int(7)) == [7, 7, 7] // external func assert nums.map(map_test_helper_1(it)) == [1, 4, 9, 16, 25, 36] @@ -568,9 +572,9 @@ fn test_map() { assert []int{len:0}.map(it * 2) == [] // nested maps (where it is of same type) - assert nums.map( strs.map(7) == [7, 7, 7] ) == [true, true, true, true, true, true] + assert nums.map( strs.map(int(7)) == [7, 7, 7] ) == [true, true, true, true, true, true] assert nums.map( '$it' + strs.map('a')[0] ) == ['1a', '2a', '3a', '4a', '5a', '6a'] - assert nums.map( it + strs.map(7)[0] ) == [8, 9, 10, 11, 12, 13] + assert nums.map( it + strs.map(int(7))[0] ) == [8, 9, 10, 11, 12, 13] assert nums.map( it + strs.map(it.len)[0] ) == [2, 3, 4, 5, 6, 7] assert strs.map( it.len + strs.map(it.len)[0] ) == [2, 3, 8] diff --git a/vlib/builtin/float.v b/vlib/builtin/float.v index b4d84ce58e..dbb2a961d1 100644 --- a/vlib/builtin/float.v +++ b/vlib/builtin/float.v @@ -13,6 +13,17 @@ pub fn (d f64) str() string { return ftoa.ftoa_64(d) } +[inline] +pub fn (d any_float) str() string { + x := f64(d) + abs_x := f64_abs(x) + if abs_x >= 0.01 && abs_x < 1.0e16 { + return ftoa.f64_to_str_l(x) + } else { + return ftoa.ftoa_64(x) + } +} + // return a string of the input f64 in scientific notation with digit_num deciamals displayed, max 17 digits [inline] pub fn (x f64) strsci(digit_num int) string { @@ -84,7 +95,7 @@ pub fn (a f64) eq(b f64) bool { [inline] pub fn (a f32) eq(b f32) bool { - return f32_abs(a - b) <= C.FLT_EPSILON + return f32_abs(a - b) <= f32(C.FLT_EPSILON) } pub fn (a f64) eqbit(b f64) bool { diff --git a/vlib/builtin/int.v b/vlib/builtin/int.v index 433e94a96a..357e226351 100644 --- a/vlib/builtin/int.v +++ b/vlib/builtin/int.v @@ -144,6 +144,11 @@ pub fn (nn u32) str() string { //return tos(buf + index, (max-index)) } +[inline] +pub fn (n any_int) str() string { + return i64(n).str() +} + pub fn (nn i64) str() string { mut n := nn mut d := i64(0) @@ -188,7 +193,7 @@ pub fn (nn i64) str() string { pub fn (nn u64) str() string { mut n := nn - mut d := 0 + mut d := u64(0) if n == 0 { return '0' } @@ -274,7 +279,7 @@ pub fn (nn u16) hex() string { mut index := max buf[index--] = `\0` for n > 0 { - d := n & 0xF + d := byte(n & 0xF) n = n >> 4 buf[index--] = if d < 10 { d + `0` } else { d + 87 } } @@ -301,7 +306,7 @@ pub fn (nn u32) hex() string { mut index := max buf[index--] = `\0` for n > 0 { - d := n & 0xF + d := byte(n & 0xF) n = n >> 4 buf[index--] = if d < 10 { d + `0` } else { d + 87 } } @@ -328,7 +333,7 @@ pub fn (nn u64) hex() string { mut index := max buf[index--] = `\0` for n > 0 { - d := n & 0xF + d := byte(n & 0xF) n = n >> 4 buf[index--] = if d < 10 { d + `0` } else { d + 87 } } @@ -345,6 +350,10 @@ pub fn (nn i64) hex() string { return u64(nn).hex() } +pub fn (nn any_int) hex() string { + return u64(nn).hex() +} + pub fn (nn voidptr) str() string { return u64(nn).hex() } diff --git a/vlib/builtin/int_test.v b/vlib/builtin/int_test.v index ff4bc9a2ba..ac9454b640 100644 --- a/vlib/builtin/int_test.v +++ b/vlib/builtin/int_test.v @@ -214,7 +214,7 @@ fn test_int_to_hex() { assert u32(c0).hex() == 'c' assert 2147483647.hex() == '7fffffff' assert u32(2147483647).hex() == '7fffffff' - assert (-1).hex() == 'ffffffff' + assert (-1).hex() == 'ffffffffffffffff' assert u32(4294967295).hex() == 'ffffffff' // 64 bit assert u64(0).hex() == '0' diff --git a/vlib/builtin/map.v b/vlib/builtin/map.v index 9b37a43877..9d60e2fad3 100644 --- a/vlib/builtin/map.v +++ b/vlib/builtin/map.v @@ -123,22 +123,22 @@ fn (mut d DenseArray) push(key string, value voidptr) u32 { if d.cap == d.size { d.cap += d.cap >> 3 d.keys = &string(C.realloc(d.keys, sizeof(string) * d.cap)) - d.values = C.realloc(d.values, d.value_bytes * d.cap) + d.values = C.realloc(d.values, u32(d.value_bytes) * d.cap) } push_index := d.size d.keys[push_index] = key - C.memcpy(d.values + push_index * d.value_bytes, value, d.value_bytes) + C.memcpy(d.values + push_index * u32(d.value_bytes), value, d.value_bytes) d.size++ return push_index } fn (d DenseArray) get(i int) voidptr { $if !no_bounds_checking? { - if i < 0 || i >= d.size { + if i < 0 || i >= int(d.size) { panic('DenseArray.get: index out of range (i == $i, d.len == $d.size)') } } - return byteptr(d.keys) + i * sizeof(string) + return byteptr(d.keys) + i * int(sizeof(string)) } // Move all zeros to the end of the array @@ -153,8 +153,8 @@ fn (mut d DenseArray) zeros_to_end() { d.keys[count] = d.keys[i] d.keys[i] = tmp_key // swap values (TODO: optimize) - C.memcpy(tmp_value, d.values + count * d.value_bytes, d.value_bytes) - C.memcpy(d.values + count * d.value_bytes, d.values + i * d.value_bytes, d.value_bytes) + C.memcpy(tmp_value, d.values + count * u32(d.value_bytes), d.value_bytes) + C.memcpy(d.values + count * u32(d.value_bytes), d.values + i * d.value_bytes, d.value_bytes) C.memcpy(d.values + i * d.value_bytes, tmp_value, d.value_bytes) count++ } @@ -164,7 +164,7 @@ fn (mut d DenseArray) zeros_to_end() { d.size = count d.cap = if count < 8 { u32(8) } else { count } d.keys = &string(C.realloc(d.keys, sizeof(string) * d.cap)) - d.values = C.realloc(d.values, d.value_bytes * d.cap) + d.values = C.realloc(d.values, u32(d.value_bytes) * d.cap) } pub struct map { @@ -280,7 +280,7 @@ fn (mut m map) set(k string, value voidptr) { for meta == m.metas[index] { kv_index := m.metas[index + 1] if fast_string_eq(key, m.key_values.keys[kv_index]) { - C.memcpy(m.key_values.values + kv_index * m.value_bytes , value, m.value_bytes) + C.memcpy(m.key_values.values + kv_index * u32(m.value_bytes), value, m.value_bytes) return } index += 2 @@ -349,7 +349,7 @@ fn (m map) get3(key string, zero voidptr) voidptr { if meta == m.metas[index] { kv_index := m.metas[index + 1] if fast_string_eq(key, m.key_values.keys[kv_index]) { - return voidptr(m.key_values.values + kv_index * m.value_bytes) + return voidptr(m.key_values.values + kv_index * u32(m.value_bytes)) } } index += 2 @@ -431,10 +431,10 @@ pub fn (d DenseArray) clone() DenseArray { size: d.size deletes: d.deletes keys: &string(malloc(d.cap * sizeof(string))) - values: byteptr(malloc(d.cap * d.value_bytes)) + values: byteptr(malloc(d.cap * u32(d.value_bytes))) } C.memcpy(res.keys, d.keys, d.cap * sizeof(string)) - C.memcpy(res.values, d.values, d.cap * d.value_bytes) + C.memcpy(res.values, d.values, d.cap * u32(d.value_bytes)) return res } diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 5e95ef3c50..65af029ca6 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -750,7 +750,7 @@ pub fn (s string) ends_with(p string) bool { pub fn (s string) to_lower() string { mut b := malloc(s.len + 1) for i in 0..s.len { - b[i] = C.tolower(s.str[i]) + b[i] = byte(C.tolower(s.str[i])) } return tos(b, s.len) } @@ -767,7 +767,7 @@ pub fn (s string) is_lower() bool { pub fn (s string) to_upper() string { mut b := malloc(s.len + 1) for i in 0..s.len { - b[i] = C.toupper(s.str[i]) + b[i] = byte(C.toupper(s.str[i])) } return tos(b, s.len) } diff --git a/vlib/builtin/utf8.v b/vlib/builtin/utf8.v index 28905f1073..8273620f68 100644 --- a/vlib/builtin/utf8.v +++ b/vlib/builtin/utf8.v @@ -13,33 +13,33 @@ pub fn utf32_to_str(code u32) string { icode := int(code) // Prevents doing casts everywhere mut buffer := malloc(5) if icode <= 127/* 0x7F */ { - buffer[0] = icode + buffer[0] = byte(icode) return tos(buffer, 1) } if icode <= 2047/* 0x7FF */ { - buffer[0] = 192/*0xC0*/ | (icode>>6)/* 110xxxxx */ + buffer[0] = 192/*0xC0*/ | byte(icode>>6)/* 110xxxxx */ - buffer[1] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ + buffer[1] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */ return tos(buffer, 2) } if icode <= 65535/* 0xFFFF */ { - buffer[0] = 224/*0xE0*/ | (icode>>12)/* 1110xxxx */ + buffer[0] = 224/*0xE0*/ | byte(icode>>12)/* 1110xxxx */ - buffer[1] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ + buffer[1] = 128/*0x80*/ | (byte(icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ - buffer[2] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ + buffer[2] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */ return tos(buffer, 3) } if icode <= 1114111/* 0x10FFFF */ { - buffer[0] = 240/*0xF0*/ | (icode>>18)/* 11110xxx */ + buffer[0] = 240/*0xF0*/ | byte(icode>>18)/* 11110xxx */ - buffer[1] = 128/*0x80*/ | ((icode>>12) & 63/*0x3F*/)/* 10xxxxxx */ + buffer[1] = 128/*0x80*/ | (byte(icode>>12) & 63/*0x3F*/)/* 10xxxxxx */ - buffer[2] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ + buffer[2] = 128/*0x80*/ | (byte(icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ - buffer[3] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ + buffer[3] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */ return tos(buffer, 4) } @@ -51,33 +51,33 @@ pub fn utf32_to_str_no_malloc(code u32, buf voidptr) string { icode := int(code) // Prevents doing casts everywhere mut buffer := byteptr(buf) if icode <= 127/* 0x7F */ { - buffer[0] = icode + buffer[0] = byte(icode) return tos(buffer, 1) } if icode <= 2047/* 0x7FF */ { - buffer[0] = 192/*0xC0*/ | (icode>>6)/* 110xxxxx */ + buffer[0] = 192/*0xC0*/ | byte(icode>>6)/* 110xxxxx */ - buffer[1] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ + buffer[1] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */ return tos(buffer, 2) } if icode <= 65535/* 0xFFFF */ { - buffer[0] = 224/*0xE0*/ | (icode>>12)/* 1110xxxx */ + buffer[0] = 224/*0xE0*/ | byte(icode>>12)/* 1110xxxx */ - buffer[1] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ + buffer[1] = 128/*0x80*/ | (byte(icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ - buffer[2] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ + buffer[2] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */ return tos(buffer, 3) } if icode <= 1114111/* 0x10FFFF */ { - buffer[0] = 240/*0xF0*/ | (icode>>18)/* 11110xxx */ + buffer[0] = 240/*0xF0*/ | byte(icode>>18)/* 11110xxx */ - buffer[1] = 128/*0x80*/ | ((icode>>12) & 63/*0x3F*/)/* 10xxxxxx */ + buffer[1] = 128/*0x80*/ | (byte(icode>>12) & 63/*0x3F*/)/* 10xxxxxx */ - buffer[2] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ + buffer[2] = 128/*0x80*/ | (byte(icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ - buffer[3] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ + buffer[3] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */ return tos(buffer, 4) } diff --git a/vlib/clipboard/clipboard_windows.c.v b/vlib/clipboard/clipboard_windows.c.v index 072f5e649d..9eecbee97e 100644 --- a/vlib/clipboard/clipboard_windows.c.v +++ b/vlib/clipboard/clipboard_windows.c.v @@ -127,7 +127,7 @@ fn (mut cb Clipboard) free() { fn to_wide(text string) &C.HGLOBAL { len_required := C.MultiByteToWideChar(C.CP_UTF8, C.MB_ERR_INVALID_CHARS, text.str, text.len + 1, C.NULL, 0) - buf := C.GlobalAlloc(C.GMEM_MOVEABLE, sizeof(u16) * len_required) + buf := C.GlobalAlloc(C.GMEM_MOVEABLE, i64(sizeof(u16)) * len_required) if buf != C.HGLOBAL(C.NULL) { mut locked := &u16(C.GlobalLock(buf)) C.MultiByteToWideChar(C.CP_UTF8, C.MB_ERR_INVALID_CHARS, text.str, text.len + 1, locked, len_required) diff --git a/vlib/freetype/freetype.v b/vlib/freetype/freetype.v index f3113a7cd3..42e53fbee2 100644 --- a/vlib/freetype/freetype.v +++ b/vlib/freetype/freetype.v @@ -152,8 +152,8 @@ fn ft_load_char(face &C.FT_FaceRec, code i64) Character { horizontal_bearing_px: gg.vec2((*face).glyph.metrics.horiBearingX >> 6, (*face).glyph.metrics.horiBearingY >> 6) vertical_bearing_px: gg.vec2((*face).glyph.metrics.vertBearingX >> 6, (*face).glyph.metrics.vertBearingY >> 6) // not used for now - horizontal_advance_px: (*face).glyph.metrics.horiAdvance >> 6 - vertical_advance_px: (*face).glyph.metrics.vertAdvance >> 6 + horizontal_advance_px: u32((*face).glyph.metrics.horiAdvance) >> 6 + vertical_advance_px: u32((*face).glyph.metrics.vertAdvance) >> 6 } } @@ -203,7 +203,7 @@ pub fn new_context(cfg gg.Cfg) &FreeType { } if !os.exists(font_path) { eprintln('freetype: font "$font_path" does not exist') - return 0 + return voidptr(0) } face := &C.FT_FaceRec{ glyph: 0 @@ -289,11 +289,11 @@ fn (mut ctx FreeType) private_draw_text(_x, _y int, utext ustring, cfg gx.TextCf if cfg.align == gx.align_right { // width := utext.len * 7 width := wx - x -= width + 10 + x -= f32(width + 10) } - x *= ctx.scale - y *= ctx.scale - y += yoffset + x *= f32(ctx.scale) + y *= f32(ctx.scale) + y += f32(yoffset) y = f32(ctx.height) - y // invert y direction color := cfg.color // Activate corresponding render state diff --git a/vlib/gg/utils.v b/vlib/gg/utils.v index a84faf0854..7075d8dfd7 100644 --- a/vlib/gg/utils.v +++ b/vlib/gg/utils.v @@ -8,7 +8,7 @@ fn arc_vertices(x, y, r, start_angle, end_angle f32, segments int) []f32 { mut vertices := []f32{} start_rads := start_angle * 0.0174533 // deg -> rad approx end_rads := end_angle * 0.0174533 - increment := (end_rads - start_rads) / segments + increment := (end_rads - start_rads) / f32(segments) vertices << [x + f32(math.cos(start_rads)) * r, y + f32(math.sin(start_rads)) * r] ! mut i := 1 for i < segments { diff --git a/vlib/gl/gl.v b/vlib/gl/gl.v index c9ba9fe3d8..e2ca96f988 100644 --- a/vlib/gl/gl.v +++ b/vlib/gl/gl.v @@ -183,12 +183,12 @@ pub fn buffer_data(typ, size int, arr voidptr, draw_typ int) { } pub fn buffer_data_int(typ int, vertices []int, draw_typ int) { - size := sizeof(int) * vertices.len + size := sizeof(int) * u32(vertices.len) C.glBufferData(typ, size, vertices.data, draw_typ) } pub fn buffer_data_f32(typ int, vertices []f32, draw_typ int) { - size := sizeof(f32) * vertices.len + size := sizeof(f32) * u32(vertices.len) C.glBufferData(typ, size, vertices.data, draw_typ) } @@ -263,11 +263,11 @@ pub fn gen_buffer() u32 { } pub fn vertex_attrib_pointer(index, size int, typ int, normalized bool, _stride int, _ptr int) { - mut stride := _stride + mut stride := u32(_stride) mut ptr := _ptr if typ == C.GL_FLOAT { stride *= sizeof(f32) - ptr *= sizeof(f32) + ptr *= int(sizeof(f32)) } C.glVertexAttribPointer(index, size, typ, normalized, stride, ptr) } @@ -311,4 +311,4 @@ pub fn set_bool(loc int, val bool) { } else { set_f32(loc, 0) } -} \ No newline at end of file +} diff --git a/vlib/net/websocket/ws.v b/vlib/net/websocket/ws.v index ee3118fc32..1de9384d08 100644 --- a/vlib/net/websocket/ws.v +++ b/vlib/net/websocket/ws.v @@ -191,8 +191,8 @@ pub fn (mut ws Client) close(code int, message string) { code_ := C.htons(code) message_len := message.len + 2 mut close_frame := [`0`].repeat(message_len) - close_frame[0] = code_ & 0xFF - close_frame[1] = (code_ >> 8) + close_frame[0] = byte(code_ & 0xFF) + close_frame[1] = byte(code_ >> 8) code32 = (close_frame[0] << 8) + close_frame[1] for i in 0 .. message.len { close_frame[i + 2] = message[i] @@ -248,9 +248,9 @@ pub fn (mut ws Client) write(payload byteptr, payload_len int, code OPCode) int fbdata := byteptr( frame_buf.data ) masking_key := create_masking_key() mut header := [`0`].repeat(header_len) - header[0] = (int(code) | 0x80) + header[0] = byte(code) | 0x80 if payload_len <= 125 { - header[1] = (payload_len | 0x80) + header[1] = byte(payload_len | 0x80) header[2] = masking_key[0] header[3] = masking_key[1] header[4] = masking_key[2] @@ -417,7 +417,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) * int(payload_len) + 1) + mut payload := malloc(sizeof(byte) * u32(payload_len) + 1) if payload == 0 { l.f('out of memory') } @@ -437,7 +437,7 @@ pub fn (mut ws Client) read() int { size += f.len } } - mut pl := malloc(sizeof(byte) * int(size)) + mut pl := malloc(sizeof(byte) * u32(size)) if pl == 0 { l.f('out of memory') } @@ -581,8 +581,8 @@ fn (mut ws Client) send_control_frame(code OPCode, frame_typ string, payload []b frame_len := header_len + payload.len mut control_frame := [`0`].repeat(frame_len) masking_key := create_masking_key() - control_frame[0] = (int(code) | 0x80) - control_frame[1] = (payload.len | 0x80) + control_frame[0] = byte(code | 0x80) + control_frame[1] = byte(payload.len | 0x80) control_frame[2] = masking_key[0] control_frame[3] = masking_key[1] control_frame[4] = masking_key[2] diff --git a/vlib/os/environment.v b/vlib/os/environment.v index 16863a732e..130c733398 100644 --- a/vlib/os/environment.v +++ b/vlib/os/environment.v @@ -19,7 +19,7 @@ pub fn getenv(key string) string { return string_from_wide(s) } $else { s := C.getenv(key.str) - if s == 0 { + if s == voidptr(0) { return '' } // NB: C.getenv *requires* that the result be copied. diff --git a/vlib/os/inode.v b/vlib/os/inode.v index 4c25eb13b7..a08b2e6a9d 100644 --- a/vlib/os/inode.v +++ b/vlib/os/inode.v @@ -35,19 +35,19 @@ pub fn inode(path string) FileMode { C.stat(path.str, &attr) mut typ := FileType.regular - if attr.st_mode & C.S_IFMT == C.S_IFDIR { + if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFDIR) { typ = .directory } $if !windows { - if attr.st_mode & C.S_IFMT == C.S_IFCHR { + if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFCHR) { typ = .character_device - } else if attr.st_mode & C.S_IFMT == C.S_IFBLK { + } else if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFBLK) { typ = .block_device - } else if attr.st_mode & C.S_IFMT == C.S_IFIFO { + } else if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFIFO) { typ = .fifo - } else if attr.st_mode & C.S_IFMT == C.S_IFLNK { + } else if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFLNK) { typ = .symbolic_link - } else if attr.st_mode & C.S_IFMT == C.S_IFSOCK { + } else if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFSOCK) { typ = .socket } } @@ -56,38 +56,38 @@ pub fn inode(path string) FileMode { return FileMode{ typ: typ owner: FilePermission{ - read: bool(attr.st_mode & C.S_IREAD) - write: bool(attr.st_mode & C.S_IWRITE) - execute: bool(attr.st_mode & C.S_IEXEC) + read: bool(attr.st_mode & u32(C.S_IREAD)) + write: bool(attr.st_mode & u32(C.S_IWRITE)) + execute: bool(attr.st_mode & u32(C.S_IEXEC)) } group: FilePermission{ - read: bool(attr.st_mode & C.S_IREAD) - write: bool(attr.st_mode & C.S_IWRITE) - execute: bool(attr.st_mode & C.S_IEXEC) + read: bool(attr.st_mode & u32(C.S_IREAD)) + write: bool(attr.st_mode & u32(C.S_IWRITE)) + execute: bool(attr.st_mode & u32(C.S_IEXEC)) } others: FilePermission{ - read: bool(attr.st_mode & C.S_IREAD) - write: bool(attr.st_mode & C.S_IWRITE) - execute: bool(attr.st_mode & C.S_IEXEC) + read: bool(attr.st_mode & u32(C.S_IREAD)) + write: bool(attr.st_mode & u32(C.S_IWRITE)) + execute: bool(attr.st_mode & u32(C.S_IEXEC)) } } } $else { return FileMode{ typ: typ owner: FilePermission{ - read: bool(attr.st_mode & C.S_IRUSR) - write: bool(attr.st_mode & C.S_IWUSR) - execute: bool(attr.st_mode & C.S_IXUSR) + read: bool(attr.st_mode & u32(C.S_IRUSR)) + write: bool(attr.st_mode & u32(C.S_IWUSR)) + execute: bool(attr.st_mode & u32(C.S_IXUSR)) } group: FilePermission{ - read: bool(attr.st_mode & C.S_IRGRP) - write: bool(attr.st_mode & C.S_IWGRP) - execute: bool(attr.st_mode & C.S_IXGRP) + read: bool(attr.st_mode & u32(C.S_IRGRP)) + write: bool(attr.st_mode & u32(C.S_IWGRP)) + execute: bool(attr.st_mode & u32(C.S_IXGRP)) } others: FilePermission{ - read: bool(attr.st_mode & C.S_IROTH) - write: bool(attr.st_mode & C.S_IWOTH) - execute: bool(attr.st_mode & C.S_IXOTH) + read: bool(attr.st_mode & u32(C.S_IROTH)) + write: bool(attr.st_mode & u32(C.S_IWOTH)) + execute: bool(attr.st_mode & u32(C.S_IXOTH)) } } } diff --git a/vlib/os/os.v b/vlib/os/os.v index d9eedb766d..f46fc8a589 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -1090,12 +1090,12 @@ pub fn real_path(fpath string) string { mut fullpath := vcalloc(max_path_len) mut ret := charptr(0) $if windows { - ret = C._fullpath(fullpath, fpath.str, max_path_len) + ret = charptr(C._fullpath(fullpath, fpath.str, max_path_len)) if ret == 0 { return fpath } } $else { - ret = C.realpath(fpath.str, fullpath) + ret = charptr(C.realpath(fpath.str, fullpath)) if ret == 0 { return fpath } @@ -1324,7 +1324,7 @@ pub fn open(path string) ?File { } */ cfile := vfopen(path, 'rb') - if cfile == 0 { + if cfile == voidptr(0) { return error('failed to open file "$path"') } fd := fileno(cfile) @@ -1361,7 +1361,7 @@ pub fn create(path string) ?File { } */ cfile := vfopen(path, 'wb') - if cfile == 0 { + if cfile == voidptr(0) { return error('failed to create file "$path"') } fd := fileno(cfile) diff --git a/vlib/os/os_windows.c.v b/vlib/os/os_windows.c.v index 228b61ed85..c290df8ffc 100644 --- a/vlib/os/os_windows.c.v +++ b/vlib/os/os_windows.c.v @@ -146,7 +146,7 @@ pub fn mkdir(path string) ?bool { // get_file_handle retrieves the operating-system file handle that is associated with the specified file descriptor. pub fn get_file_handle(path string) HANDLE { cfile := vfopen(path, 'rb') - if cfile == 0 { + if cfile == voidptr(0) { return HANDLE(invalid_handle_value) } handle := HANDLE(C._get_osfhandle(fileno(cfile))) // CreateFile? - hah, no -_- diff --git a/vlib/strconv/ftoa/f32_str.v b/vlib/strconv/ftoa/f32_str.v index 7a09bf525f..64dda843e5 100644 --- a/vlib/strconv/ftoa/f32_str.v +++ b/vlib/strconv/ftoa/f32_str.v @@ -59,7 +59,7 @@ const( const( mantbits32 = u32(23) expbits32 = u32(8) - bias32 = u32(127) // f32 exponent bias + bias32 = 127 // f32 exponent bias maxexp32 = 255 ) @@ -189,10 +189,10 @@ pub fn f32_to_decimal(mant u32, exp u32) Dec32 { if exp == 0 { // We subtract 2 so that the bounds computation has // 2 additional bits. - e2 = 1 - bias32 - mantbits32 - 2 + e2 = 1 - bias32 - int(mantbits32) - 2 m2 = mant } else { - e2 = int(exp) - bias32 - mantbits32 - 2 + e2 = int(exp) - bias32 - int(mantbits32) - 2 m2 = (u32(1) << mantbits32) | mant } even := (m2 & 1) == 0 diff --git a/vlib/strconv/ftoa/f64_str.v b/vlib/strconv/ftoa/f64_str.v index 68e63044c4..530bb579df 100644 --- a/vlib/strconv/ftoa/f64_str.v +++ b/vlib/strconv/ftoa/f64_str.v @@ -73,7 +73,7 @@ const( const( mantbits64 = u32(52) expbits64 = u32(11) - bias64 = u32(1023) // f64 exponent bias + bias64 = 1023 // f64 exponent bias maxexp64 = 2047 ) @@ -220,10 +220,10 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 { if exp == 0 { // We subtract 2 so that the bounds computation has // 2 additional bits. - e2 = 1 - bias64 - mantbits64 - 2 + e2 = 1 - bias64 - int(mantbits64) - 2 m2 = mant } else { - e2 = int(exp) - bias64 - mantbits64 - 2 + e2 = int(exp) - bias64 - int(mantbits64) - 2 m2 = (u64(1)<= 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 + } + } 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 { + exp_idx := expected.idx() + got_idx := got.idx() + if exp_idx == got_idx { + return true + } + if exp_idx == table.voidptr_type_idx || exp_idx == table.byteptr_type_idx { + if got.is_ptr() || got.is_pointer() { + return true + } + } + // allow direct int-literal assignment for pointers for now + // maybe in the future optionals should be used for that + if expected.is_ptr() || expected.is_pointer() { + if got == table.any_int_type { + return true + } + } + if got_idx == table.voidptr_type_idx || got_idx == table.byteptr_type_idx { + if expected.is_ptr() || expected.is_pointer() { + return true + } + } + if !c.check_types(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 + } + return true +} + +pub fn (c &Checker) symmetric_check(left, right table.Type) bool { + // allow direct int-literal assignment for pointers for now + // maybe in the future optionals should be used for that + if right.is_ptr() || right.is_pointer() { + if left == table.any_int_type { + return true + } + } + // allow direct int-literal assignment for pointers for now + if left.is_ptr() || left.is_pointer() { + if right == table.any_int_type { + return true + } + } + return c.check_types(left, right) +} diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index ba3f23e7a3..22d5bb2dfa 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -362,11 +362,11 @@ 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.check_types(expr_type, info_field.typ) { + if !c.assign_check(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) } - if info_field.typ.is_ptr() && !expr_type.is_ptr() && !expr_type.is_number() { + if info_field.typ.is_ptr() && !expr_type.is_ptr() && !expr_type.is_pointer() && !expr_type.is_number() { c.error('ref', field.pos) } struct_init.fields[i].typ = expr_type @@ -408,6 +408,10 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { infix_expr.right_type = right_type right := c.table.get_type_symbol(right_type) left := c.table.get_type_symbol(left_type) + left_default := c.table.get_type_symbol(c.table.mktyp(left_type)) + left_pos := infix_expr.left.position() + right_pos := infix_expr.right.position() + mut return_type := left_type // Single side check // Place these branches according to ops' usage frequency to accelerate. // TODO: First branch includes ops where single side check is not needed, or needed but hasn't been implemented. @@ -417,22 +421,22 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { .key_in, .not_in { match right.kind { .array { - right_sym := c.table.get_type_symbol(right.array_info().elem_type) - if left.kind != right_sym.kind { - c.error('the data type on the left of `$infix_expr.op.str()` does not match the array item type', + right_sym := c.table.get_type_symbol(c.table.mktyp(right.array_info().elem_type)) + if left_default.kind != right_sym.kind { + c.error('the data type on the left of `$infix_expr.op.str()` (`$left.name`) does not match the array item type (`$right_sym.name`)', infix_expr.pos) } } .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 `$infix_expr.op.str()` does not match the map key type', + key_sym := c.table.get_type_symbol(c.table.mktyp(right.map_info().key_type)) + if left_default.kind != key_sym.kind { + c.error('the data type on the left of `$infix_expr.op.str()` (`$left.name`) does not match the map key type `$key_sym.name`', infix_expr.pos) } } .string { if left.kind != .string { - c.error('the data type on the left of `$infix_expr.op.str()` must be a string', + c.error('the data type on the left of `$infix_expr.op.str()` must be a string (is `$left.name`)', infix_expr.pos) } } @@ -443,15 +447,43 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { } return table.bool_type } - .plus, .minus, .mul, .div { - if infix_expr.op == .div && (infix_expr.right is ast.IntegerLiteral && infix_expr.right.str() == - '0' || infix_expr.right is ast.FloatLiteral && infix_expr.right.str().f64() == 0.0) { - c.error('division by zero', infix_expr.right.position()) - } - if left.kind in [.array, .array_fixed, .map, .struct_] && !left.has_method(infix_expr.op.str()) { - c.error('mismatched types `$left.name` and `$right.name`', infix_expr.left.position()) - } else if right.kind in [.array, .array_fixed, .map, .struct_] && !right.has_method(infix_expr.op.str()) { - c.error('mismatched types `$left.name` and `$right.name`', infix_expr.right.position()) + .plus, .minus, .mul, .div, .mod, .xor, .amp, .pipe { // binary operators that expect matching types + if left.kind in [.array, .array_fixed, .map, .struct_] { + if left.has_method(infix_expr.op.str()) { + return_type = left_type + } else { + c.error('mismatched types `$left.name` and `$right.name`', left_pos) + } + } else if right.kind in [.array, .array_fixed, .map, .struct_] { + if right.has_method(infix_expr.op.str()) { + return_type = right_type + } else { + c.error('mismatched types `$left.name` and `$right.name`', right_pos) + } + } else { + promoted_type := c.promote(c.table.unalias_num_type(left_type), c.table.unalias_num_type(right_type)) + if promoted_type.idx() == table.void_type_idx { + c.error('mismatched types `$left.name` and `$right.name`', infix_expr.pos) + } else if promoted_type.is_float() { + if infix_expr.op in [.mod, .xor, .amp, .pipe] { + side := if left_type == promoted_type { 'left' } else { 'right' } + pos := if left_type == promoted_type { left_pos } else { right_pos } + name := if left_type == promoted_type { left.name } else { right.name } + if infix_expr.op == .mod { + c.error('float modulo not allowed, use math.fmod() instead', pos) + } else { + c.error('$side type of `${infix_expr.op.str()}` cannot be non-integer type $name', pos) + } + } + } + if infix_expr.op in [.div, .mod] { + if infix_expr.right is ast.IntegerLiteral && infix_expr.right.str() == '0' || + infix_expr.right is ast.FloatLiteral && infix_expr.right.str().f64() == 0.0 { + oper := if infix_expr.op == .div { 'division' } else { 'modulo' } + c.error('$oper by zero', right_pos) + } + } + return_type = promoted_type } } .left_shift { @@ -463,11 +495,10 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { if left_value_sym.kind == .interface_ { if right.kind != .array { // []Animal << Cat - c.type_implements(right_type, left_value_type, infix_expr.right.position()) + c.type_implements(right_type, left_value_type, right_pos) } else { // []Animal << Cat - c.type_implements(c.table.value_type(right_type), left_value_type, - infix_expr.right.position()) + c.type_implements(c.table.value_type(right_type), left_value_type, right_pos) } return table.void_type } @@ -481,13 +512,13 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { return table.void_type } s := left.name.replace('array_', '[]') - c.error('cannot append `$right.name` to `$s`', infix_expr.right.position()) + c.error('cannot append `$right.name` to `$s`', right_pos) return table.void_type } else if !left.is_int() { - c.error('cannot shift type $right.name into non-integer type $left.name', infix_expr.left.position()) + c.error('cannot shift type $right.name into non-integer type $left.name', left_pos) return table.void_type } else if !right.is_int() { - c.error('cannot shift non-integer type $right.name into type $left.name', infix_expr.right.position()) + c.error('cannot shift non-integer type $right.name into type $left.name', right_pos) return table.void_type } } @@ -499,33 +530,6 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { } return table.bool_type } - .amp, .pipe, .xor { - if !left.is_int() { - c.error('left type of `${infix_expr.op.str()}` cannot be non-integer type $left.name', - infix_expr.left.position()) - } else if !right.is_int() { - c.error('right type of `${infix_expr.op.str()}` cannot be non-integer type $right.name', - infix_expr.right.position()) - } - } - .mod { - if left.is_int() && !right.is_int() { - c.error('mismatched types `$left.name` and `$right.name`', infix_expr.right.position()) - } else if !left.is_int() && right.is_int() { - c.error('mismatched types `$left.name` and `$right.name`', infix_expr.left.position()) - } else if left.kind == .f32 && right.kind == .f32 || left.kind == .f64 && right.kind == - .f64 { - c.error('float modulo not allowed, use math.fmod() instead', infix_expr.left.position()) - } else if left.kind in [.f32, .f64, .string, .array, .array_fixed, .map, .struct_] && - !left.has_method(infix_expr.op.str()) { - c.error('mismatched types `$left.name` and `$right.name`', infix_expr.left.position()) - } else if right.kind in [.f32, .f64, .string, .array, .array_fixed, .map, .struct_] && - !right.has_method(infix_expr.op.str()) { - c.error('mismatched types `$left.name` and `$right.name`', infix_expr.right.position()) - } else if infix_expr.right is ast.IntegerLiteral && infix_expr.right.str() == '0' { - c.error('modulo by zero', infix_expr.right.position()) - } - } else {} } // TODO: Absorb this block into the above single side check block to accelerate. @@ -539,7 +543,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { infix_expr.pos) } // Dual sides check (compatibility check) - if !c.check_types(right_type, left_type) { + if !c.symmetric_check(right_type, left_type) { // for type-unresolved consts if left_type == table.void_type || right_type == table.void_type { return table.void_type @@ -550,7 +554,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { return if infix_expr.op.is_relational() { table.bool_type } else { - left_type + return_type } } @@ -678,7 +682,7 @@ fn (mut c Checker) assign_expr(mut assign_expr ast.AssignExpr) { else {} } // Dual sides check (compatibility check) - if !c.check_types(right_type, left_type) { + if !c.assign_check(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`', @@ -1268,12 +1272,15 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { } else if i < assign_stmt.right.len { // only once for multi return c.check_expr_opt_call(assign_stmt.right[i], assign_stmt.right_types[i]) } - val_type := assign_stmt.right_types[i] + mut val_type := assign_stmt.right_types[i] // check variable name for beginning with capital letter 'Abc' is_decl := assign_stmt.op == .decl_assign if is_decl && ident.name != '_' { c.check_valid_snake_case(ident.name, 'variable name', ident.pos) } + if assign_stmt.op == .decl_assign { + val_type = c.table.mktyp(val_type) + } mut ident_var_info := ident.var_info() if assign_stmt.op == .assign { c.fail_if_immutable(ident) @@ -1301,12 +1308,12 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type { if array_init.typ != table.void_type { if array_init.exprs.len == 0 { if array_init.has_cap { - if c.expr(array_init.cap_expr) != table.int_type { + if c.expr(array_init.cap_expr) !in [table.int_type, table.any_int_type] { c.error('array cap needs to be an int', array_init.pos) } } if array_init.has_len { - if c.expr(array_init.len_expr) != table.int_type { + if c.expr(array_init.len_expr) !in [table.int_type, table.any_int_type] { c.error('array len needs to be an int', array_init.pos) } } @@ -1316,12 +1323,12 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type { // a = [] if array_init.exprs.len == 0 { if array_init.has_cap { - if c.expr(array_init.cap_expr) != table.int_type { + if c.expr(array_init.cap_expr) !in [table.int_type, table.any_int_type] { c.error('array cap needs to be an int', array_init.pos) } } if array_init.has_len { - if c.expr(array_init.len_expr) != table.int_type { + if c.expr(array_init.len_expr) !in [table.int_type, table.any_int_type] { c.error('array len needs to be an int', array_init.pos) } } @@ -1372,8 +1379,8 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type { } // The first element's type if i == 0 { - elem_type = typ - c.expected_type = typ + elem_type = c.table.mktyp(typ) + c.expected_type = elem_type continue } if !c.check_types(elem_type, typ) { @@ -1492,7 +1499,7 @@ fn (mut c Checker) stmt(node ast.Stmt) { c.const_decl = field.name c.const_deps << field.name typ := c.expr(field.expr) - it.fields[i].typ = typ + it.fields[i].typ = c.table.mktyp(typ) for cd in c.const_deps { for j, f in it.fields { if j != i && cd in field_names && cd == f.name && j !in done_fields { @@ -1748,7 +1755,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { return c.enum_val(mut it) } ast.FloatLiteral { - return table.f64_type + return table.any_flt_type } ast.Ident { // c.checked_ident = it.name @@ -1770,7 +1777,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { return c.infix_expr(mut it) } ast.IntegerLiteral { - return table.int_type + return table.any_int_type } ast.MapInit { return c.map_init(mut it) @@ -1805,7 +1812,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { return c.selector_expr(mut it) } ast.SizeOf { - return table.int_type + return table.u32_type } ast.StringLiteral { if it.language == .c { @@ -2140,10 +2147,33 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type { // first branch of if expression node.is_expr = true node.typ = last_expr.typ - } else { - c.error('mismatched types `${c.table.type_to_str(node.typ)}` and `${c.table.type_to_str(last_expr.typ)}`', - node.pos) + continue + } else if node.typ in [table.any_flt_type, table.any_int_type] { + if node.typ == table.any_int_type { + if last_expr.typ.is_int() || last_expr.typ.is_float() { + node.typ = last_expr.typ + continue + } + } else { // node.typ == any_float + if last_expr.typ.is_float() { + node.typ = last_expr.typ + continue + } + } } + if last_expr.typ in [table.any_flt_type, table.any_int_type] { + if last_expr.typ == table.any_int_type { + if node.typ.is_int() || node.typ.is_float() { + continue + } + } else { // expr_type == any_float + if node.typ.is_float() { + continue + } + } + } + c.error('mismatched types `${c.table.type_to_str(node.typ)}` and `${c.table.type_to_str(last_expr.typ)}`', + node.pos) } } else { c.error('`if` expression requires an expression as the last statement of every branch', @@ -2151,6 +2181,12 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type { } } } + // if only untyped literals were given default to int/f64 + if node.typ == table.any_int_type { + node.typ = table.int_type + } else if node.typ == table.any_flt_type { + node.typ = table.f64_type + } if expr_required { if !node.has_else { c.error('`if` expression needs `else` clause', node.pos) diff --git a/vlib/v/checker/tests/add_op_wrong_left_type_err_a.out b/vlib/v/checker/tests/add_op_wrong_left_type_err_a.out index 706bbb1941..cee46d4a7e 100644 --- a/vlib/v/checker/tests/add_op_wrong_left_type_err_a.out +++ b/vlib/v/checker/tests/add_op_wrong_left_type_err_a.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/add_op_wrong_left_type_err_a.v:3:5: error: mismatched types `A` and `int` +vlib/v/checker/tests/add_op_wrong_left_type_err_a.v:3:5: error: mismatched types `A` and `any_int` 1 | struct A{} 2 | fn main() { 3 | A{} + 10 diff --git a/vlib/v/checker/tests/add_op_wrong_left_type_err_b.out b/vlib/v/checker/tests/add_op_wrong_left_type_err_b.out index 54e8fbd155..864151db2c 100644 --- a/vlib/v/checker/tests/add_op_wrong_left_type_err_b.out +++ b/vlib/v/checker/tests/add_op_wrong_left_type_err_b.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/add_op_wrong_left_type_err_b.v:2:5: error: mismatched types `array_int` and `int` +vlib/v/checker/tests/add_op_wrong_left_type_err_b.v:2:5: error: mismatched types `array_int` and `any_int` 1 | fn main() { 2 | [1,2,3] + 10 | ~~~~~~~ diff --git a/vlib/v/checker/tests/add_op_wrong_left_type_err_c.out b/vlib/v/checker/tests/add_op_wrong_left_type_err_c.out index 72f0107bdc..7f260d0c2e 100644 --- a/vlib/v/checker/tests/add_op_wrong_left_type_err_c.out +++ b/vlib/v/checker/tests/add_op_wrong_left_type_err_c.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/add_op_wrong_left_type_err_c.v:3:5: error: mismatched types `map_string_int` and `int` +vlib/v/checker/tests/add_op_wrong_left_type_err_c.v:3:5: error: mismatched types `map_string_int` and `any_int` 1 | fn main() { 2 | a := map[string]int 3 | a + 10 diff --git a/vlib/v/checker/tests/add_op_wrong_right_type_err_a.out b/vlib/v/checker/tests/add_op_wrong_right_type_err_a.out index 56ad595917..d77e2624ff 100644 --- a/vlib/v/checker/tests/add_op_wrong_right_type_err_a.out +++ b/vlib/v/checker/tests/add_op_wrong_right_type_err_a.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/add_op_wrong_right_type_err_a.v:3:10: error: mismatched types `int` and `A` +vlib/v/checker/tests/add_op_wrong_right_type_err_a.v:3:10: error: mismatched types `any_int` and `A` 1 | struct A{} 2 | fn main() { 3 | 10 + A{} diff --git a/vlib/v/checker/tests/add_op_wrong_right_type_err_b.out b/vlib/v/checker/tests/add_op_wrong_right_type_err_b.out index a886cf04e7..8d61f81c2a 100644 --- a/vlib/v/checker/tests/add_op_wrong_right_type_err_b.out +++ b/vlib/v/checker/tests/add_op_wrong_right_type_err_b.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/add_op_wrong_right_type_err_b.v:2:10: error: mismatched types `int` and `array_int` +vlib/v/checker/tests/add_op_wrong_right_type_err_b.v:2:10: error: mismatched types `any_int` and `array_int` 1 | fn main() { 2 | 10 + [1,2,3] | ~~~~~~~ diff --git a/vlib/v/checker/tests/add_op_wrong_right_type_err_c.out b/vlib/v/checker/tests/add_op_wrong_right_type_err_c.out index 4a4a3aedbb..085c32fb86 100644 --- a/vlib/v/checker/tests/add_op_wrong_right_type_err_c.out +++ b/vlib/v/checker/tests/add_op_wrong_right_type_err_c.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/add_op_wrong_right_type_err_c.v:3:10: error: mismatched types `int` and `map_string_int` +vlib/v/checker/tests/add_op_wrong_right_type_err_c.v:3:10: error: mismatched types `any_int` and `map_string_int` 1 | fn main() { 2 | a := map[string]int 3 | 10 + a diff --git a/vlib/v/checker/tests/bit_op_wrong_left_type_err.out b/vlib/v/checker/tests/bit_op_wrong_left_type_err.out index bb4ba57bc0..0077eeff03 100644 --- a/vlib/v/checker/tests/bit_op_wrong_left_type_err.out +++ b/vlib/v/checker/tests/bit_op_wrong_left_type_err.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/bit_op_wrong_left_type_err.v:2:2: error: left type of `&` cannot be non-integer type f64 +vlib/v/checker/tests/bit_op_wrong_left_type_err.v:2:2: error: left type of `&` cannot be non-integer type any_float 1 | fn main() { 2 | 0.5 & 1 | ~~~ diff --git a/vlib/v/checker/tests/bit_op_wrong_right_type_err.out b/vlib/v/checker/tests/bit_op_wrong_right_type_err.out index 28d7cdb3b8..3e36bb91a1 100644 --- a/vlib/v/checker/tests/bit_op_wrong_right_type_err.out +++ b/vlib/v/checker/tests/bit_op_wrong_right_type_err.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/bit_op_wrong_right_type_err.v:2:6: error: right type of `|` cannot be non-integer type f64 +vlib/v/checker/tests/bit_op_wrong_right_type_err.v:2:6: error: right type of `|` cannot be non-integer type any_float 1 | fn main() { 2 | 1 | 0.5 | ~~~ diff --git a/vlib/v/checker/tests/cast_string_err.out b/vlib/v/checker/tests/cast_string_err.out index a5b128b429..794ca79b29 100644 --- a/vlib/v/checker/tests/cast_string_err.out +++ b/vlib/v/checker/tests/cast_string_err.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/cast_string_err.v:2:14: error: cannot cast type `int` to string, use `x.str()` instead +vlib/v/checker/tests/cast_string_err.v:2:14: error: cannot cast type `any_int` to string, use `x.str()` instead 1 | fn main() { 2 | a := string(1) | ^ diff --git a/vlib/v/checker/tests/div_op_wrong_left_type_err_a.out b/vlib/v/checker/tests/div_op_wrong_left_type_err_a.out index 76c663ceeb..410eb4a874 100644 --- a/vlib/v/checker/tests/div_op_wrong_left_type_err_a.out +++ b/vlib/v/checker/tests/div_op_wrong_left_type_err_a.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/div_op_wrong_left_type_err_a.v:3:5: error: mismatched types `A` and `int` +vlib/v/checker/tests/div_op_wrong_left_type_err_a.v:3:5: error: mismatched types `A` and `any_int` 1 | struct A{} 2 | fn main() { 3 | A{} / 10 diff --git a/vlib/v/checker/tests/div_op_wrong_left_type_err_b.out b/vlib/v/checker/tests/div_op_wrong_left_type_err_b.out index 1dd125f53b..3706ba2548 100644 --- a/vlib/v/checker/tests/div_op_wrong_left_type_err_b.out +++ b/vlib/v/checker/tests/div_op_wrong_left_type_err_b.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/div_op_wrong_left_type_err_b.v:2:5: error: mismatched types `array_int` and `int` +vlib/v/checker/tests/div_op_wrong_left_type_err_b.v:2:5: error: mismatched types `array_int` and `any_int` 1 | fn main() { 2 | [1,2,3] / 10 | ~~~~~~~ diff --git a/vlib/v/checker/tests/div_op_wrong_left_type_err_c.out b/vlib/v/checker/tests/div_op_wrong_left_type_err_c.out index 7c0144e001..336adaf5df 100644 --- a/vlib/v/checker/tests/div_op_wrong_left_type_err_c.out +++ b/vlib/v/checker/tests/div_op_wrong_left_type_err_c.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/div_op_wrong_left_type_err_c.v:3:5: error: mismatched types `map_string_int` and `int` +vlib/v/checker/tests/div_op_wrong_left_type_err_c.v:3:5: error: mismatched types `map_string_int` and `any_int` 1 | fn main() { 2 | a := map[string]int 3 | a / 10 diff --git a/vlib/v/checker/tests/div_op_wrong_right_type_err_a.out b/vlib/v/checker/tests/div_op_wrong_right_type_err_a.out index c46df5ace1..747f8deda7 100644 --- a/vlib/v/checker/tests/div_op_wrong_right_type_err_a.out +++ b/vlib/v/checker/tests/div_op_wrong_right_type_err_a.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/div_op_wrong_right_type_err_a.v:3:10: error: mismatched types `int` and `A` +vlib/v/checker/tests/div_op_wrong_right_type_err_a.v:3:10: error: mismatched types `any_int` and `A` 1 | struct A{} 2 | fn main() { 3 | 10 / A{} diff --git a/vlib/v/checker/tests/div_op_wrong_right_type_err_b.out b/vlib/v/checker/tests/div_op_wrong_right_type_err_b.out index 7497157e16..4dca5f2ce2 100644 --- a/vlib/v/checker/tests/div_op_wrong_right_type_err_b.out +++ b/vlib/v/checker/tests/div_op_wrong_right_type_err_b.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/div_op_wrong_right_type_err_b.v:2:10: error: mismatched types `int` and `array_int` +vlib/v/checker/tests/div_op_wrong_right_type_err_b.v:2:10: error: mismatched types `any_int` and `array_int` 1 | fn main() { 2 | 10 / [1,2,3] | ~~~~~~~ diff --git a/vlib/v/checker/tests/div_op_wrong_right_type_err_c.out b/vlib/v/checker/tests/div_op_wrong_right_type_err_c.out index c024c95a5c..834c6f72ef 100644 --- a/vlib/v/checker/tests/div_op_wrong_right_type_err_c.out +++ b/vlib/v/checker/tests/div_op_wrong_right_type_err_c.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/div_op_wrong_right_type_err_c.v:3:10: error: mismatched types `int` and `map_string_int` +vlib/v/checker/tests/div_op_wrong_right_type_err_c.v:3:10: error: mismatched types `any_int` and `map_string_int` 1 | fn main() { 2 | a := map[string]int 3 | 10 / a diff --git a/vlib/v/checker/tests/for-in-index-type.out b/vlib/v/checker/tests/for-in-index-type.out index b4ce5eb609..40c8bacaf8 100644 --- a/vlib/v/checker/tests/for-in-index-type.out +++ b/vlib/v/checker/tests/for-in-index-type.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/for-in-index-type.v:2:11: error: for in: cannot index `int` +vlib/v/checker/tests/for-in-index-type.v:2:11: error: for in: cannot index `any_int` 1 | fn main() { 2 | for a in 52 { | ~~ diff --git a/vlib/v/checker/tests/if_expr_mismatch.out b/vlib/v/checker/tests/if_expr_mismatch.out index 04ce5c54b9..0ab04350cd 100644 --- a/vlib/v/checker/tests/if_expr_mismatch.out +++ b/vlib/v/checker/tests/if_expr_mismatch.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/if_expr_mismatch.v:2:7: error: mismatched types `string` and `int` +vlib/v/checker/tests/if_expr_mismatch.v:2:7: error: mismatched types `string` and `any_int` 1 | fn main() { 2 | s := if true { '12' } else { 12 } | ~~ diff --git a/vlib/v/checker/tests/in_mismatch_type.out b/vlib/v/checker/tests/in_mismatch_type.out index 5cdb2492d2..7bc6c3778c 100644 --- a/vlib/v/checker/tests/in_mismatch_type.out +++ b/vlib/v/checker/tests/in_mismatch_type.out @@ -1,76 +1,76 @@ -vlib/v/checker/tests/in_mismatch_type.v:10:7: error: the data type on the left of `in` does not match the array item type +vlib/v/checker/tests/in_mismatch_type.v:10:7: error: the data type on the left of `in` (`any_int`) does not match the array item type (`string`) 8 | } 9 | s := 'abcd' 10 | if 1 in a_s { | ~~ 11 | println('ok') 12 | } -vlib/v/checker/tests/in_mismatch_type.v:13:7: error: the data type on the left of `in` does not match the map key type +vlib/v/checker/tests/in_mismatch_type.v:13:7: error: the data type on the left of `in` (`any_int`) does not match the map key type `string` 11 | println('ok') 12 | } 13 | if 2 in m { | ~~ 14 | println('yeah') 15 | } -vlib/v/checker/tests/in_mismatch_type.v:16:7: error: the data type on the left of `in` must be a string +vlib/v/checker/tests/in_mismatch_type.v:16:7: error: the data type on the left of `in` must be a string (is `any_int`) 14 | println('yeah') 15 | } 16 | if 3 in s { | ~~ 17 | println('dope') 18 | } -vlib/v/checker/tests/in_mismatch_type.v:19:9: error: the data type on the left of `in` must be a string +vlib/v/checker/tests/in_mismatch_type.v:19:9: error: the data type on the left of `in` must be a string (is `byte`) 17 | println('dope') 18 | } 19 | if `a` in s { | ~~ 20 | println("oh no :'(") 21 | } -vlib/v/checker/tests/in_mismatch_type.v:22:7: error: `in` can only be used with an array/map/string +vlib/v/checker/tests/in_mismatch_type.v:22:7: error: `in` can only be used with an array/map/string 20 | println("oh no :'(") 21 | } 22 | if 1 in 12 { | ~~ 23 | println('right') 24 | } -vlib/v/checker/tests/in_mismatch_type.v:25:12: error: the data type on the left of `in` does not match the map key type +vlib/v/checker/tests/in_mismatch_type.v:25:12: error: the data type on the left of `in` (`Int`) does not match the map key type `string` 23 | println('right') 24 | } 25 | if Int(2) in m { | ~~ 26 | println('yeah') 27 | } -vlib/v/checker/tests/in_mismatch_type.v:28:9: error: the data type on the left of `in` does not match the array item type +vlib/v/checker/tests/in_mismatch_type.v:28:9: error: the data type on the left of `in` (`string`) does not match the array item type (`int`) 26 | println('yeah') 27 | } 28 | if '3' in a_i { | ~~ 29 | println('sure') 30 | } -vlib/v/checker/tests/in_mismatch_type.v:31:9: error: the data type on the left of `in` does not match the array item type +vlib/v/checker/tests/in_mismatch_type.v:31:9: error: the data type on the left of `in` (`string`) does not match the array item type (`int`) 29 | println('sure') 30 | } 31 | if '2' in a_i { | ~~ 32 | println('all right') 33 | } -vlib/v/checker/tests/in_mismatch_type.v:34:7: error: the data type on the left of `!in` does not match the array item type +vlib/v/checker/tests/in_mismatch_type.v:34:7: error: the data type on the left of `!in` (`any_int`) does not match the array item type (`string`) 32 | println('all right') 33 | } 34 | if 1 !in a_s { | ~~~ 35 | println('ok') 36 | } -vlib/v/checker/tests/in_mismatch_type.v:37:9: error: the data type on the left of `!in` does not match the array item type +vlib/v/checker/tests/in_mismatch_type.v:37:9: error: the data type on the left of `!in` (`string`) does not match the array item type (`int`) 35 | println('ok') 36 | } 37 | if '1' !in a_i { | ~~~ 38 | println('good') 39 | } -vlib/v/checker/tests/in_mismatch_type.v:41:7: error: the data type on the left of `!in` does not match the map key type +vlib/v/checker/tests/in_mismatch_type.v:41:7: error: the data type on the left of `!in` (`any_int`) does not match the map key type `string` 39 | } - 40 | + 40 | 41 | if 5 !in m { | ~~~ 42 | println('yay') diff --git a/vlib/v/checker/tests/is_type_not_exist.out b/vlib/v/checker/tests/is_type_not_exist.out index 79385d0048..d732a34149 100644 --- a/vlib/v/checker/tests/is_type_not_exist.out +++ b/vlib/v/checker/tests/is_type_not_exist.out @@ -1,5 +1,12 @@ -vlib/v/checker/tests/is_type_not_exist.v:8:10: error: is: type `SomethingThatDontExist` does not exist +vlib/v/checker/tests/is_type_not_exist.v:4:2: error: cannot use type `any_int` as type `Integer` in argument 1 to `fn_with_sum_type_param` + 2 | + 3 | fn main() { + 4 | fn_with_sum_type_param(1) + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + 5 | } 6 | +vlib/v/checker/tests/is_type_not_exist.v:8:10: error: is: type `SomethingThatDontExist` does not exist + 6 | 7 | fn fn_with_sum_type_param(i Integer) { 8 | if i is SomethingThatDontExist { | ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/vlib/v/checker/tests/minus_op_wrong_left_type_err_a.out b/vlib/v/checker/tests/minus_op_wrong_left_type_err_a.out index 6c20a705f8..2e7c7efbce 100644 --- a/vlib/v/checker/tests/minus_op_wrong_left_type_err_a.out +++ b/vlib/v/checker/tests/minus_op_wrong_left_type_err_a.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/minus_op_wrong_left_type_err_a.v:3:5: error: mismatched types `A` and `int` +vlib/v/checker/tests/minus_op_wrong_left_type_err_a.v:3:5: error: mismatched types `A` and `any_int` 1 | struct A{} 2 | fn main() { 3 | A{} - 10 diff --git a/vlib/v/checker/tests/minus_op_wrong_left_type_err_b.out b/vlib/v/checker/tests/minus_op_wrong_left_type_err_b.out index 19b2b68a40..65e835c096 100644 --- a/vlib/v/checker/tests/minus_op_wrong_left_type_err_b.out +++ b/vlib/v/checker/tests/minus_op_wrong_left_type_err_b.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/minus_op_wrong_left_type_err_b.v:2:5: error: mismatched types `array_int` and `int` +vlib/v/checker/tests/minus_op_wrong_left_type_err_b.v:2:5: error: mismatched types `array_int` and `any_int` 1 | fn main() { 2 | [1,2,3] - 10 | ~~~~~~~ diff --git a/vlib/v/checker/tests/minus_op_wrong_left_type_err_c.out b/vlib/v/checker/tests/minus_op_wrong_left_type_err_c.out index 75e17e9358..714a7ee5b3 100644 --- a/vlib/v/checker/tests/minus_op_wrong_left_type_err_c.out +++ b/vlib/v/checker/tests/minus_op_wrong_left_type_err_c.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/minus_op_wrong_left_type_err_c.v:3:5: error: mismatched types `map_string_int` and `int` +vlib/v/checker/tests/minus_op_wrong_left_type_err_c.v:3:5: error: mismatched types `map_string_int` and `any_int` 1 | fn main() { 2 | a := map[string]int 3 | a - 10 diff --git a/vlib/v/checker/tests/minus_op_wrong_right_type_err_a.out b/vlib/v/checker/tests/minus_op_wrong_right_type_err_a.out index 63bd1c7062..add2249e0c 100644 --- a/vlib/v/checker/tests/minus_op_wrong_right_type_err_a.out +++ b/vlib/v/checker/tests/minus_op_wrong_right_type_err_a.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/minus_op_wrong_right_type_err_a.v:3:10: error: mismatched types `int` and `A` +vlib/v/checker/tests/minus_op_wrong_right_type_err_a.v:3:10: error: mismatched types `any_int` and `A` 1 | struct A{} 2 | fn main() { 3 | 10 - A{} diff --git a/vlib/v/checker/tests/minus_op_wrong_right_type_err_b.out b/vlib/v/checker/tests/minus_op_wrong_right_type_err_b.out index e717b7af60..76a786551f 100644 --- a/vlib/v/checker/tests/minus_op_wrong_right_type_err_b.out +++ b/vlib/v/checker/tests/minus_op_wrong_right_type_err_b.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/minus_op_wrong_right_type_err_b.v:2:10: error: mismatched types `int` and `array_int` +vlib/v/checker/tests/minus_op_wrong_right_type_err_b.v:2:10: error: mismatched types `any_int` and `array_int` 1 | fn main() { 2 | 10 - [1,2,3] | ~~~~~~~ diff --git a/vlib/v/checker/tests/minus_op_wrong_right_type_err_c.out b/vlib/v/checker/tests/minus_op_wrong_right_type_err_c.out index f37e415bcb..25c6184628 100644 --- a/vlib/v/checker/tests/minus_op_wrong_right_type_err_c.out +++ b/vlib/v/checker/tests/minus_op_wrong_right_type_err_c.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/minus_op_wrong_right_type_err_c.v:3:10: error: mismatched types `int` and `map_string_int` +vlib/v/checker/tests/minus_op_wrong_right_type_err_c.v:3:10: error: mismatched types `any_int` and `map_string_int` 1 | fn main() { 2 | a := map[string]int 3 | 10 - a diff --git a/vlib/v/checker/tests/mod_op_wrong_left_type_err_a.out b/vlib/v/checker/tests/mod_op_wrong_left_type_err_a.out index 48f72a0cda..86fb067512 100644 --- a/vlib/v/checker/tests/mod_op_wrong_left_type_err_a.out +++ b/vlib/v/checker/tests/mod_op_wrong_left_type_err_a.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mod_op_wrong_left_type_err_a.v:2:2: error: mismatched types `f64` and `int` +vlib/v/checker/tests/mod_op_wrong_left_type_err_a.v:2:2: error: float modulo not allowed, use math.fmod() instead 1 | fn main() { 2 | 0.5 % 1 | ~~~ diff --git a/vlib/v/checker/tests/mod_op_wrong_left_type_err_b.out b/vlib/v/checker/tests/mod_op_wrong_left_type_err_b.out index 806b145642..ac813150fc 100644 --- a/vlib/v/checker/tests/mod_op_wrong_left_type_err_b.out +++ b/vlib/v/checker/tests/mod_op_wrong_left_type_err_b.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mod_op_wrong_left_type_err_b.v:2:2: error: mismatched types `array_int` and `int` +vlib/v/checker/tests/mod_op_wrong_left_type_err_b.v:2:2: error: mismatched types `array_int` and `any_int` 1 | fn main() { 2 | [1,2,3] % 1 | ~~~~~~~ diff --git a/vlib/v/checker/tests/mod_op_wrong_left_type_err_c.out b/vlib/v/checker/tests/mod_op_wrong_left_type_err_c.out index bcea24d762..99b5337694 100644 --- a/vlib/v/checker/tests/mod_op_wrong_left_type_err_c.out +++ b/vlib/v/checker/tests/mod_op_wrong_left_type_err_c.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mod_op_wrong_left_type_err_c.v:4:2: error: mismatched types `A` and `int` +vlib/v/checker/tests/mod_op_wrong_left_type_err_c.v:4:2: error: mismatched types `A` and `any_int` 2 | fn main() { 3 | a := A{} 4 | a % 1 diff --git a/vlib/v/checker/tests/mod_op_wrong_left_type_err_d.out b/vlib/v/checker/tests/mod_op_wrong_left_type_err_d.out index b55825c29b..bbf5235c3e 100644 --- a/vlib/v/checker/tests/mod_op_wrong_left_type_err_d.out +++ b/vlib/v/checker/tests/mod_op_wrong_left_type_err_d.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mod_op_wrong_left_type_err_d.v:3:2: error: mismatched types `map_string_int` and `int` +vlib/v/checker/tests/mod_op_wrong_left_type_err_d.v:3:2: error: mismatched types `map_string_int` and `any_int` 1 | fn main() { 2 | a := map[string]int 3 | a % 1 diff --git a/vlib/v/checker/tests/mod_op_wrong_right_type_err_a.out b/vlib/v/checker/tests/mod_op_wrong_right_type_err_a.out index a3097a8ddf..989c42d4d0 100644 --- a/vlib/v/checker/tests/mod_op_wrong_right_type_err_a.out +++ b/vlib/v/checker/tests/mod_op_wrong_right_type_err_a.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mod_op_wrong_right_type_err_a.v:2:6: error: mismatched types `int` and `f64` +vlib/v/checker/tests/mod_op_wrong_right_type_err_a.v:2:6: error: float modulo not allowed, use math.fmod() instead 1 | fn main() { 2 | 1 % 0.5 | ~~~ diff --git a/vlib/v/checker/tests/mod_op_wrong_right_type_err_b.out b/vlib/v/checker/tests/mod_op_wrong_right_type_err_b.out index 9cdb1c0f9f..d43282c508 100644 --- a/vlib/v/checker/tests/mod_op_wrong_right_type_err_b.out +++ b/vlib/v/checker/tests/mod_op_wrong_right_type_err_b.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mod_op_wrong_right_type_err_b.v:2:6: error: mismatched types `int` and `array_int` +vlib/v/checker/tests/mod_op_wrong_right_type_err_b.v:2:6: error: mismatched types `any_int` and `array_int` 1 | fn main() { 2 | 1 % [1,2,3] | ~~~~~~~ diff --git a/vlib/v/checker/tests/mod_op_wrong_right_type_err_c.out b/vlib/v/checker/tests/mod_op_wrong_right_type_err_c.out index 80b805799f..12dadd60be 100644 --- a/vlib/v/checker/tests/mod_op_wrong_right_type_err_c.out +++ b/vlib/v/checker/tests/mod_op_wrong_right_type_err_c.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mod_op_wrong_right_type_err_c.v:4:6: error: mismatched types `int` and `A` +vlib/v/checker/tests/mod_op_wrong_right_type_err_c.v:4:6: error: mismatched types `any_int` and `A` 2 | fn main() { 3 | a := A{} 4 | 1 % a diff --git a/vlib/v/checker/tests/mod_op_wrong_right_type_err_d.out b/vlib/v/checker/tests/mod_op_wrong_right_type_err_d.out index b903190b45..2dd072bd1f 100644 --- a/vlib/v/checker/tests/mod_op_wrong_right_type_err_d.out +++ b/vlib/v/checker/tests/mod_op_wrong_right_type_err_d.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mod_op_wrong_right_type_err_d.v:3:6: error: mismatched types `int` and `map_string_int` +vlib/v/checker/tests/mod_op_wrong_right_type_err_d.v:3:6: error: mismatched types `any_int` and `map_string_int` 1 | fn main() { 2 | a := map[string]int 3 | 1 % a diff --git a/vlib/v/checker/tests/mul_op_wrong_left_type_err_a.out b/vlib/v/checker/tests/mul_op_wrong_left_type_err_a.out index be1c509109..6ae6aba93a 100644 --- a/vlib/v/checker/tests/mul_op_wrong_left_type_err_a.out +++ b/vlib/v/checker/tests/mul_op_wrong_left_type_err_a.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mul_op_wrong_left_type_err_a.v:3:5: error: mismatched types `A` and `int` +vlib/v/checker/tests/mul_op_wrong_left_type_err_a.v:3:5: error: mismatched types `A` and `any_int` 1 | struct A{} 2 | fn main() { 3 | A{} * 10 diff --git a/vlib/v/checker/tests/mul_op_wrong_left_type_err_b.out b/vlib/v/checker/tests/mul_op_wrong_left_type_err_b.out index 222812e0c2..342042bc30 100644 --- a/vlib/v/checker/tests/mul_op_wrong_left_type_err_b.out +++ b/vlib/v/checker/tests/mul_op_wrong_left_type_err_b.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mul_op_wrong_left_type_err_b.v:2:5: error: mismatched types `array_int` and `int` +vlib/v/checker/tests/mul_op_wrong_left_type_err_b.v:2:5: error: mismatched types `array_int` and `any_int` 1 | fn main() { 2 | [1,2,3] * 10 | ~~~~~~~ diff --git a/vlib/v/checker/tests/mul_op_wrong_left_type_err_c.out b/vlib/v/checker/tests/mul_op_wrong_left_type_err_c.out index 6c7397718d..3d1f7c5431 100644 --- a/vlib/v/checker/tests/mul_op_wrong_left_type_err_c.out +++ b/vlib/v/checker/tests/mul_op_wrong_left_type_err_c.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mul_op_wrong_left_type_err_c.v:3:5: error: mismatched types `map_string_int` and `int` +vlib/v/checker/tests/mul_op_wrong_left_type_err_c.v:3:5: error: mismatched types `map_string_int` and `any_int` 1 | fn main() { 2 | a := map[string]int 3 | a * 10 diff --git a/vlib/v/checker/tests/mul_op_wrong_left_type_err_d.out b/vlib/v/checker/tests/mul_op_wrong_left_type_err_d.out new file mode 100644 index 0000000000..26303228ce --- /dev/null +++ b/vlib/v/checker/tests/mul_op_wrong_left_type_err_d.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/mul_op_wrong_left_type_err_d.v:6:11: error: infix expr: cannot use `any_float` (right expression) as `math.complex.Complex` + 4 | fn main() { + 5 | c1 := cmplx.complex(1,-2) + 6 | c2 := c1 * 2.0 + | ^ + 7 | println(c2) + 8 | } diff --git a/vlib/v/checker/tests/mul_op_wrong_left_type_err_d.vv b/vlib/v/checker/tests/mul_op_wrong_left_type_err_d.vv new file mode 100644 index 0000000000..e1a12f9777 --- /dev/null +++ b/vlib/v/checker/tests/mul_op_wrong_left_type_err_d.vv @@ -0,0 +1,8 @@ +import math +import math.complex as cmplx + +fn main() { + c1 := cmplx.complex(1,-2) + c2 := c1 * 2.0 + println(c2) +} diff --git a/vlib/v/checker/tests/mul_op_wrong_right_type_err_a.out b/vlib/v/checker/tests/mul_op_wrong_right_type_err_a.out index ffc4e4e3f1..96cec13c52 100644 --- a/vlib/v/checker/tests/mul_op_wrong_right_type_err_a.out +++ b/vlib/v/checker/tests/mul_op_wrong_right_type_err_a.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mul_op_wrong_right_type_err_a.v:3:10: error: mismatched types `int` and `A` +vlib/v/checker/tests/mul_op_wrong_right_type_err_a.v:3:10: error: mismatched types `any_int` and `A` 1 | struct A{} 2 | fn main() { 3 | 10 * A{} diff --git a/vlib/v/checker/tests/mul_op_wrong_right_type_err_b.out b/vlib/v/checker/tests/mul_op_wrong_right_type_err_b.out index cca704c0c4..210d9022a8 100644 --- a/vlib/v/checker/tests/mul_op_wrong_right_type_err_b.out +++ b/vlib/v/checker/tests/mul_op_wrong_right_type_err_b.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mul_op_wrong_right_type_err_b.v:2:10: error: mismatched types `int` and `array_int` +vlib/v/checker/tests/mul_op_wrong_right_type_err_b.v:2:10: error: mismatched types `any_int` and `array_int` 1 | fn main() { 2 | 10 * [1,2,3] | ~~~~~~~ diff --git a/vlib/v/checker/tests/mul_op_wrong_right_type_err_c.out b/vlib/v/checker/tests/mul_op_wrong_right_type_err_c.out index 5f419e150f..c32652ebca 100644 --- a/vlib/v/checker/tests/mul_op_wrong_right_type_err_c.out +++ b/vlib/v/checker/tests/mul_op_wrong_right_type_err_c.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/mul_op_wrong_right_type_err_c.v:3:10: error: mismatched types `int` and `map_string_int` +vlib/v/checker/tests/mul_op_wrong_right_type_err_c.v:3:10: error: mismatched types `any_int` and `map_string_int` 1 | fn main() { 2 | a := map[string]int 3 | 10 * a diff --git a/vlib/v/checker/tests/mul_op_wrong_right_type_err_d.out b/vlib/v/checker/tests/mul_op_wrong_right_type_err_d.out new file mode 100644 index 0000000000..e5437495ab --- /dev/null +++ b/vlib/v/checker/tests/mul_op_wrong_right_type_err_d.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/mul_op_wrong_right_type_err_d.v:6:12: error: infix expr: cannot use `math.complex.Complex` (right expression) as `any_float` + 4 | fn main() { + 5 | c1 := cmplx.complex(1,-2) + 6 | c2 := 2.0 * c1 + | ^ + 7 | println(c2) + 8 | } diff --git a/vlib/v/checker/tests/mul_op_wrong_right_type_err_d.vv b/vlib/v/checker/tests/mul_op_wrong_right_type_err_d.vv new file mode 100644 index 0000000000..6f754fe5b9 --- /dev/null +++ b/vlib/v/checker/tests/mul_op_wrong_right_type_err_d.vv @@ -0,0 +1,8 @@ +import math +import math.complex as cmplx + +fn main() { + c1 := cmplx.complex(1,-2) + c2 := 2.0 * c1 + println(c2) +} diff --git a/vlib/v/checker/tests/return_type.out b/vlib/v/checker/tests/return_type.out index 6a0c4c4af8..01c33a2e13 100644 --- a/vlib/v/checker/tests/return_type.out +++ b/vlib/v/checker/tests/return_type.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/return_type.v:2:9: error: cannot use `int` as type `bool` in return argument +vlib/v/checker/tests/return_type.v:2:9: error: cannot use `any_int` as type `bool` in return argument 1 | fn test() bool { 2 | return 100 | ~~~ diff --git a/vlib/v/checker/tests/shift_op_wrong_left_type_err.out b/vlib/v/checker/tests/shift_op_wrong_left_type_err.out index 74da254a00..29e58a57fb 100644 --- a/vlib/v/checker/tests/shift_op_wrong_left_type_err.out +++ b/vlib/v/checker/tests/shift_op_wrong_left_type_err.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/shift_op_wrong_left_type_err.v:2:2: error: cannot shift type int into non-integer type f64 +vlib/v/checker/tests/shift_op_wrong_left_type_err.v:2:2: error: cannot shift type any_int into non-integer type any_float 1 | fn main() { 2 | 0.5 << 1 | ~~~ diff --git a/vlib/v/checker/tests/shift_op_wrong_right_type_err.out b/vlib/v/checker/tests/shift_op_wrong_right_type_err.out index 8858a01256..71ccb5e141 100644 --- a/vlib/v/checker/tests/shift_op_wrong_right_type_err.out +++ b/vlib/v/checker/tests/shift_op_wrong_right_type_err.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/shift_op_wrong_right_type_err.v:2:7: error: cannot shift non-integer type f64 into type int +vlib/v/checker/tests/shift_op_wrong_right_type_err.v:2:7: error: cannot shift non-integer type any_float into type any_int 1 | fn main() { 2 | 1 << 0.5 | ~~~ diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index b24a3702c2..657fb6d1f8 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -272,7 +272,7 @@ pub fn (mut g Gen) finish() { if g.pref.is_livemain || g.pref.is_liveshared { g.generate_hotcode_reloader_code() } - if g.fn_main != 0 { + if g.fn_main != voidptr(0) { g.out.writeln('') g.fn_decl = g.fn_main g.gen_fn_decl(g.fn_main) @@ -1728,7 +1728,7 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { } else {} } - styp := g.typ(left_type) + styp := g.typ(g.table.mktyp(left_type)) g.write('_IN($styp, ') g.expr(node.left) g.write(', ') diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 7555ca1c4a..11e8918293 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -847,7 +847,7 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl) { g.writeln('') } - g.fn_decl = 0 + g.fn_decl = voidptr(0) } fn (mut g JsGen) fn_args(args []table.Arg, is_variadic bool) { diff --git a/vlib/v/gen/x64/elf.v b/vlib/v/gen/x64/elf.v index b3ad623d53..e232cc9581 100644 --- a/vlib/v/gen/x64/elf.v +++ b/vlib/v/gen/x64/elf.v @@ -65,14 +65,14 @@ pub fn (mut g Gen) generate_elf_header() { g.write64(0) // p_offset g.write64(segment_start) // p_vaddr addr:050 g.write64(segment_start) // - g.file_size_pos = g.buf.len + g.file_size_pos = i64(g.buf.len) g.write64(0) // p_filesz PLACEHOLDER, set to file_size later // addr: 060 g.write64(0) // p_memsz g.write64(0x1000) // p_align // user code starts here at // address: 00070 and a half println('code_start_pos = $g.buf.len.hex()') - g.code_start_pos = g.buf.len + g.code_start_pos = i64(g.buf.len) g.debug_pos = g.buf.len g.call(placeholder) // call main function, it's not guaranteed to be the first, we don't know its address yet g.println('call fn main') diff --git a/vlib/v/gen/x64/gen.v b/vlib/v/gen/x64/gen.v index 742873c33c..a73a0745e5 100644 --- a/vlib/v/gen/x64/gen.v +++ b/vlib/v/gen/x64/gen.v @@ -402,7 +402,7 @@ pub fn (mut g Gen) gen_loop_end(to, label int) { } pub fn (mut g Gen) save_main_fn_addr() { - g.main_fn_addr = g.buf.len + g.main_fn_addr = i64(g.buf.len) } pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, newline bool) { diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index ab21ff2744..6150ad26f5 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -58,7 +58,7 @@ pub fn new_scanner_file(file_path string, comments_mode CommentsMode) &Scanner { } raw_text := util.read_file( file_path ) or { verror(err) - return 0 + return voidptr(0) } mut s := new_scanner(raw_text, comments_mode) // .skip_comments) // s.init_fmt() diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 95a27683be..6694023d9e 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -195,6 +195,18 @@ pub fn (t &Table) get_type_name(typ Type) string { return typ_sym.name } +[inline] +pub fn (t &Table) unalias_num_type(typ Type) Type { + sym := t.get_type_symbol(typ) + if sym.kind == .alias { + pt := (sym.info as Alias).parent_typ + if pt <= f64_type && pt >= void_type { + return pt + } + } + return typ +} + // this will override or register builtin type // allows prexisitng types added in register_builtins // to be overriden with their real type info @@ -438,6 +450,21 @@ pub fn (t &Table) value_type(typ Type) Type { return void_type } +[inline] +pub fn (t &Table) mktyp(typ Type) Type { + match typ { + any_flt_type { + return table.f64_type + } + any_int_type { + return table.int_type + } + else { + return typ + } + } +} + // Once we have a module format we can read from module file instead // this is not optimal pub fn (table &Table) qualify_module(mod, file_path string) string { diff --git a/vlib/v/tests/num_lit_call_method_test.v b/vlib/v/tests/num_lit_call_method_test.v index f717276e65..3346d3acb8 100644 --- a/vlib/v/tests/num_lit_call_method_test.v +++ b/vlib/v/tests/num_lit_call_method_test.v @@ -13,16 +13,16 @@ fn test_int_lit_call_method() { fn test_float_lit_call_method() { x1 := -123.66.str() - assert x1 == '-1.2366e+02' + assert x1 == '-123.66' x2 := 12.5e-2.str() - assert x2 == '1.25e-01' + assert x2 == '0.125' x3 := .789.str() - assert x3 == '7.89e-01' + assert x3 == '0.789' x4 := .003e2.str() - assert x4 == '3.e-01' + assert x4 == '0.3' x5 := 2.e-3.str() assert x5 == '2.e-03' x6 := 5.0.str() - assert x6 == '5.e+00' + assert x6 == '5.' // x7 := 5..str() Syntax `5.` is allowed, but do not call method on it (`5..str()` is parsed as a range). Use `5.0.str()` instead. }