From d5a421e3f5add133598cef6596d01ff3fe89abb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A4schle?= Date: Mon, 2 Nov 2020 01:17:35 +0100 Subject: [PATCH] checker: add alias cast type check (closes #6705) (#6709) --- vlib/time/stopwatch.v | 6 +- vlib/v/checker/checker.v | 151 ++++++++++-------- vlib/v/checker/tests/cannot_cast_to_alias.out | 6 + vlib/v/checker/tests/cannot_cast_to_alias.vv | 7 + .../v/checker/tests/cannot_cast_to_struct.out | 18 +-- vlib/v/checker/tests/cast_err.out | 14 +- vlib/v/checker/tests/cast_string_err.out | 6 +- .../tests/cast_string_with_byte_err.out | 6 +- vlib/v/checker/tests/float_modulo_err.out | 8 +- vlib/v/checker/tests/none_type_cast_err.out | 46 +++--- .../struct_cast_to_struct_generic_err.out | 4 +- .../tests/struct_cast_to_struct_mut_err_a.out | 4 +- .../tests/struct_cast_to_struct_mut_err_b.out | 4 +- .../tests/struct_cast_to_struct_pub_err_a.out | 4 +- .../tests/struct_cast_to_struct_pub_err_b.out | 4 +- vlib/v/checker/tests/sum.out | 8 +- .../tests/warnings_for_string_c2v_calls.out | 10 +- vlib/v/parser/parser.v | 4 +- 18 files changed, 167 insertions(+), 143 deletions(-) create mode 100644 vlib/v/checker/tests/cannot_cast_to_alias.out create mode 100644 vlib/v/checker/tests/cannot_cast_to_alias.vv diff --git a/vlib/time/stopwatch.v b/vlib/time/stopwatch.v index fcd7299d59..81bcc85692 100644 --- a/vlib/time/stopwatch.v +++ b/vlib/time/stopwatch.v @@ -57,11 +57,11 @@ pub fn (mut t StopWatch) pause() { pub fn (t StopWatch) elapsed() Duration { if t.start > 0 { if t.end == 0 { - return Duration(time.sys_mono_now() - t.start + t.elapsed) + return Duration(i64(time.sys_mono_now() - t.start + t.elapsed)) } else { - return Duration(t.end - t.start + t.elapsed) + return Duration(i64(t.end - t.start + t.elapsed)) } } - return Duration(t.elapsed) + return Duration(i64(t.elapsed)) } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index eec4f29b78..15fe11d9cf 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2683,77 +2683,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { return table.bool_type } ast.CastExpr { - node.expr_type = c.expr(node.expr) - from_type_sym := c.table.get_type_symbol(node.expr_type) - to_type_sym := c.table.get_type_symbol(node.typ) - expr_is_ptr := node.expr_type.is_ptr() || node.expr_type.idx() in table.pointer_type_idxs - if expr_is_ptr && to_type_sym.kind == .string && !node.in_prexpr { - if node.has_arg { - c.warn('to convert a C string buffer pointer to a V string, please use x.vstring_with_len(len) instead of string(x,len)', - node.pos) - } else { - c.warn('to convert a C string buffer pointer to a V string, please use x.vstring() instead of string(x)', - node.pos) - } - } - if node.expr_type == table.byte_type && to_type_sym.kind == .string { - c.error('can not cast type `byte` to string, use `${node.expr.str()}.str()` instead.', - node.pos) - } - if to_type_sym.kind == .sum_type { - if node.expr_type in [table.any_int_type, table.any_flt_type] { - node.expr_type = c.promote_num(node.expr_type, if node.expr_type == table.any_int_type { table.int_type } else { table.f64_type }) - } - if !c.table.sumtype_has_variant(node.typ, node.expr_type) { - c.error('cannot cast `$from_type_sym.source_name` to `$to_type_sym.source_name`', - node.pos) - } - } else if node.typ == table.string_type && - (from_type_sym.kind in [.any_int, .int, .byte, .byteptr] || - (from_type_sym.kind == .array && from_type_sym.name == 'array_byte')) { - type_name := c.table.type_to_str(node.expr_type) - c.error('cannot cast type `$type_name` to string, use `x.str()` instead', - node.pos) - } else if node.expr_type == table.string_type { - if to_type_sym.kind != .alias { - mut error_msg := 'cannot cast a string' - if node.expr is ast.StringLiteral { - str_lit := node.expr as ast.StringLiteral - if str_lit.val.len == 1 { - error_msg += ", for denoting characters use `$str_lit.val` instead of '$str_lit.val'" - } - } - c.error(error_msg, node.pos) - } - } else if to_type_sym.kind == .byte && - node.expr_type != table.voidptr_type && from_type_sym.kind != .enum_ && !node.expr_type.is_int() && - !node.expr_type.is_float() && !node.expr_type.is_ptr() { - type_name := c.table.type_to_str(node.expr_type) - c.error('cannot cast type `$type_name` to `byte`', node.pos) - } else if to_type_sym.kind == .struct_ && !node.typ.is_ptr() && !(to_type_sym.info as table.Struct).is_typedef { - // For now we ignore C typedef because of `C.Window(C.None)` in vlib/clipboard - if from_type_sym.kind == .struct_ && !node.expr_type.is_ptr() { - from_type_info := from_type_sym.info as table.Struct - to_type_info := to_type_sym.info as table.Struct - if !c.check_struct_signature(from_type_info, to_type_info) { - c.error('cannot convert struct `$from_type_sym.source_name` to struct `$to_type_sym.source_name`', - node.pos) - } - } else { - type_name := c.table.type_to_str(node.expr_type) - c.error('cannot cast `$type_name` to struct', node.pos) - } - } else if node.typ == table.bool_type { - c.error('cannot cast to bool - use e.g. `some_int != 0` instead', node.pos) - } else if node.expr_type == table.none_type { - type_name := c.table.type_to_str(node.typ) - c.error('cannot cast `none` to `$type_name`', node.pos) - } - if node.has_arg { - c.expr(node.arg) - } - node.typname = c.table.get_type_symbol(node.typ).name - return node.typ + return c.cast_expr(mut node) } ast.CallExpr { return c.call_expr(mut node) @@ -2959,6 +2889,85 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { return table.void_type } +pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) table.Type { + node.expr_type = c.expr(node.expr) + from_type_sym := c.table.get_type_symbol(node.expr_type) + to_type_sym := c.table.get_type_symbol(node.typ) + expr_is_ptr := node.expr_type.is_ptr() || node.expr_type.idx() in table.pointer_type_idxs + if expr_is_ptr && to_type_sym.kind == .string && !node.in_prexpr { + if node.has_arg { + c.warn('to convert a C string buffer pointer to a V string, please use x.vstring_with_len(len) instead of string(x,len)', + node.pos) + } else { + c.warn('to convert a C string buffer pointer to a V string, please use x.vstring() instead of string(x)', + node.pos) + } + } + if node.expr_type == table.byte_type && to_type_sym.kind == .string { + c.error('can not cast type `byte` to string, use `${node.expr.str()}.str()` instead.', + node.pos) + } + if to_type_sym.kind == .sum_type { + if node.expr_type in [table.any_int_type, table.any_flt_type] { + node.expr_type = c.promote_num(node.expr_type, if node.expr_type == table.any_int_type { table.int_type } else { table.f64_type }) + } + if !c.table.sumtype_has_variant(node.typ, node.expr_type) { + c.error('cannot cast `$from_type_sym.source_name` to `$to_type_sym.source_name`', + node.pos) + } + } else if to_type_sym.info is table.Alias as alias_info { + if !c.check_types(node.expr_type, alias_info.parent_type) { + parent_type_sym := c.table.get_type_symbol(alias_info.parent_type) + c.error('cannot convert type `$from_type_sym.source_name` to `$to_type_sym.source_name` (alias to `$parent_type_sym.source_name`)', + node.pos) + } + } else if node.typ == table.string_type && + (from_type_sym.kind in [.any_int, .int, .byte, .byteptr] || + (from_type_sym.kind == .array && from_type_sym.name == 'array_byte')) { + type_name := c.table.type_to_str(node.expr_type) + c.error('cannot cast type `$type_name` to string, use `x.str()` instead', node.pos) + } else if node.expr_type == table.string_type { + if to_type_sym.kind != .alias { + mut error_msg := 'cannot cast a string' + if node.expr is ast.StringLiteral { + str_lit := node.expr as ast.StringLiteral + if str_lit.val.len == 1 { + error_msg += ", for denoting characters use `$str_lit.val` instead of '$str_lit.val'" + } + } + c.error(error_msg, node.pos) + } + } else if to_type_sym.kind == .byte && + node.expr_type != table.voidptr_type && from_type_sym.kind != .enum_ && !node.expr_type.is_int() && + !node.expr_type.is_float() && !node.expr_type.is_ptr() { + type_name := c.table.type_to_str(node.expr_type) + c.error('cannot cast type `$type_name` to `byte`', node.pos) + } else if to_type_sym.kind == .struct_ && !node.typ.is_ptr() && !(to_type_sym.info as table.Struct).is_typedef { + // For now we ignore C typedef because of `C.Window(C.None)` in vlib/clipboard + if from_type_sym.kind == .struct_ && !node.expr_type.is_ptr() { + from_type_info := from_type_sym.info as table.Struct + to_type_info := to_type_sym.info as table.Struct + if !c.check_struct_signature(from_type_info, to_type_info) { + c.error('cannot convert struct `$from_type_sym.source_name` to struct `$to_type_sym.source_name`', + node.pos) + } + } else { + type_name := c.table.type_to_str(node.expr_type) + c.error('cannot cast `$type_name` to struct', node.pos) + } + } else if node.typ == table.bool_type { + c.error('cannot cast to bool - use e.g. `some_int != 0` instead', node.pos) + } else if node.expr_type == table.none_type { + type_name := c.table.type_to_str(node.typ) + c.error('cannot cast `none` to `$type_name`', node.pos) + } + if node.has_arg { + c.expr(node.arg) + } + node.typname = c.table.get_type_symbol(node.typ).name + return node.typ +} + pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type { // TODO: move this if c.const_deps.len > 0 { diff --git a/vlib/v/checker/tests/cannot_cast_to_alias.out b/vlib/v/checker/tests/cannot_cast_to_alias.out new file mode 100644 index 0000000000..9f4ccddf5f --- /dev/null +++ b/vlib/v/checker/tests/cannot_cast_to_alias.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/cannot_cast_to_alias.vv:6:7: error: cannot convert type `any_int` to `MyType` (alias to `string`) + 4 | + 5 | fn main() { + 6 | _ := MyType(5) + | ~~~~~~~~~ + 7 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/cannot_cast_to_alias.vv b/vlib/v/checker/tests/cannot_cast_to_alias.vv new file mode 100644 index 0000000000..11985706f6 --- /dev/null +++ b/vlib/v/checker/tests/cannot_cast_to_alias.vv @@ -0,0 +1,7 @@ +module main + +type MyType = string + +fn main() { + _ := MyType(5) +} diff --git a/vlib/v/checker/tests/cannot_cast_to_struct.out b/vlib/v/checker/tests/cannot_cast_to_struct.out index e631940eaf..3acdc7a116 100644 --- a/vlib/v/checker/tests/cannot_cast_to_struct.out +++ b/vlib/v/checker/tests/cannot_cast_to_struct.out @@ -1,27 +1,27 @@ -vlib/v/checker/tests/cannot_cast_to_struct.vv:10:12: error: cannot convert struct `Abc` to struct `Test` +vlib/v/checker/tests/cannot_cast_to_struct.vv:10:7: error: cannot convert struct `Abc` to struct `Test` 8 | 9 | fn main() { 10 | _ := Test(Abc{}) - | ~~~~~ + | ~~~~~~~~~~~ 11 | sum := Alphabet(Xyz{}) 12 | _ = Xyz(sum) -vlib/v/checker/tests/cannot_cast_to_struct.vv:12:10: error: cannot cast `Alphabet` to struct +vlib/v/checker/tests/cannot_cast_to_struct.vv:12:6: error: cannot cast `Alphabet` to struct 10 | _ := Test(Abc{}) 11 | sum := Alphabet(Xyz{}) 12 | _ = Xyz(sum) - | ~~~ + | ~~~~~~~~ 13 | _ = Xyz(5) 14 | s := Abc{} -vlib/v/checker/tests/cannot_cast_to_struct.vv:13:10: error: cannot cast `any_int` to struct +vlib/v/checker/tests/cannot_cast_to_struct.vv:13:6: error: cannot cast `any_int` to struct 11 | sum := Alphabet(Xyz{}) 12 | _ = Xyz(sum) 13 | _ = Xyz(5) - | ^ + | ~~~~~~ 14 | s := Abc{} 15 | _ = Xyz(&s) -vlib/v/checker/tests/cannot_cast_to_struct.vv:15:10: error: cannot cast `&Abc` to struct +vlib/v/checker/tests/cannot_cast_to_struct.vv:15:6: error: cannot cast `&Abc` to struct 13 | _ = Xyz(5) 14 | s := Abc{} 15 | _ = Xyz(&s) - | ^ - 16 | } + | ~~~~~~~ + 16 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/cast_err.out b/vlib/v/checker/tests/cast_err.out index 638f8804a0..86b7fdadbe 100644 --- a/vlib/v/checker/tests/cast_err.out +++ b/vlib/v/checker/tests/cast_err.out @@ -1,20 +1,20 @@ -vlib/v/checker/tests/cast_err.vv:3:11: error: cannot cast to bool - use e.g. `some_int != 0` instead +vlib/v/checker/tests/cast_err.vv:3:6: error: cannot cast to bool - use e.g. `some_int != 0` instead 1 | fn test_bool_cast() { 2 | v := 3 3 | _ = bool(v) - | ^ + | ~~~~~~~ 4 | _ = bool(&v) 5 | _ = bool([2]) -vlib/v/checker/tests/cast_err.vv:4:11: error: cannot cast to bool - use e.g. `some_int != 0` instead +vlib/v/checker/tests/cast_err.vv:4:6: error: cannot cast to bool - use e.g. `some_int != 0` instead 2 | v := 3 3 | _ = bool(v) 4 | _ = bool(&v) - | ^ + | ~~~~~~~~ 5 | _ = bool([2]) 6 | } -vlib/v/checker/tests/cast_err.vv:5:11: error: cannot cast to bool - use e.g. `some_int != 0` instead +vlib/v/checker/tests/cast_err.vv:5:6: error: cannot cast to bool - use e.g. `some_int != 0` instead 3 | _ = bool(v) 4 | _ = bool(&v) 5 | _ = bool([2]) - | ~~~ - 6 | } + | ~~~~~~~~~ + 6 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/cast_string_err.out b/vlib/v/checker/tests/cast_string_err.out index 0d3402f608..da7902e0cc 100644 --- a/vlib/v/checker/tests/cast_string_err.out +++ b/vlib/v/checker/tests/cast_string_err.out @@ -1,6 +1,6 @@ -vlib/v/checker/tests/cast_string_err.vv:2:14: error: cannot cast type `any_int` to string, use `x.str()` instead +vlib/v/checker/tests/cast_string_err.vv:2:7: error: cannot cast type `any_int` to string, use `x.str()` instead 1 | fn main() { 2 | a := string(1) - | ^ + | ~~~~~~~~~ 3 | println(a) - 4 | } + 4 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/cast_string_with_byte_err.out b/vlib/v/checker/tests/cast_string_with_byte_err.out index 8761fb78cc..1b042184f2 100644 --- a/vlib/v/checker/tests/cast_string_with_byte_err.out +++ b/vlib/v/checker/tests/cast_string_with_byte_err.out @@ -1,5 +1,5 @@ -vlib/v/checker/tests/cast_string_with_byte_err.vv:2:19: error: can not cast type `byte` to string, use `by.str()` instead. +vlib/v/checker/tests/cast_string_with_byte_err.vv:2:12: error: can not cast type `byte` to string, use `by.str()` instead. 1 | for by in 'abc' { 2 | println(string(by)) - | ~~ - 3 | } + | ~~~~~~~~~~ + 3 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/float_modulo_err.out b/vlib/v/checker/tests/float_modulo_err.out index 33ae5625d2..4186414acc 100644 --- a/vlib/v/checker/tests/float_modulo_err.out +++ b/vlib/v/checker/tests/float_modulo_err.out @@ -1,12 +1,12 @@ -vlib/v/checker/tests/float_modulo_err.vv:2:13: error: float modulo not allowed, use math.fmod() instead +vlib/v/checker/tests/float_modulo_err.vv:2:13: error: float modulo not allowed, use math.fmod() instead 1 | fn main() { 2 | println(3.0 % 2.0) | ~~~ 3 | println(f32(3.0) % f32(2.0)) 4 | } -vlib/v/checker/tests/float_modulo_err.vv:3:17: error: float modulo not allowed, use math.fmod() instead +vlib/v/checker/tests/float_modulo_err.vv:3:13: error: float modulo not allowed, use math.fmod() instead 1 | fn main() { 2 | println(3.0 % 2.0) 3 | println(f32(3.0) % f32(2.0)) - | ~~~ - 4 | } + | ~~~~~~~~ + 4 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/none_type_cast_err.out b/vlib/v/checker/tests/none_type_cast_err.out index 2d25d700d7..914cb4dc8f 100644 --- a/vlib/v/checker/tests/none_type_cast_err.out +++ b/vlib/v/checker/tests/none_type_cast_err.out @@ -1,75 +1,75 @@ -vlib/v/checker/tests/none_type_cast_err.vv:2:14: error: cannot cast `none` to `string` +vlib/v/checker/tests/none_type_cast_err.vv:2:7: error: cannot cast `none` to `string` 1 | fn main() { 2 | _ := string(none) - | ~~~~ + | ~~~~~~~~~~~~ 3 | _ := int(none) 4 | _ := i8(none) -vlib/v/checker/tests/none_type_cast_err.vv:3:11: error: cannot cast `none` to `int` +vlib/v/checker/tests/none_type_cast_err.vv:3:7: error: cannot cast `none` to `int` 1 | fn main() { 2 | _ := string(none) 3 | _ := int(none) - | ~~~~ + | ~~~~~~~~~ 4 | _ := i8(none) 5 | _ := i16(none) -vlib/v/checker/tests/none_type_cast_err.vv:4:10: error: cannot cast `none` to `i8` +vlib/v/checker/tests/none_type_cast_err.vv:4:7: error: cannot cast `none` to `i8` 2 | _ := string(none) 3 | _ := int(none) 4 | _ := i8(none) - | ~~~~ + | ~~~~~~~~ 5 | _ := i16(none) 6 | _ := i64(none) -vlib/v/checker/tests/none_type_cast_err.vv:5:11: error: cannot cast `none` to `i16` +vlib/v/checker/tests/none_type_cast_err.vv:5:7: error: cannot cast `none` to `i16` 3 | _ := int(none) 4 | _ := i8(none) 5 | _ := i16(none) - | ~~~~ + | ~~~~~~~~~ 6 | _ := i64(none) 7 | _ := u16(none) -vlib/v/checker/tests/none_type_cast_err.vv:6:11: error: cannot cast `none` to `i64` +vlib/v/checker/tests/none_type_cast_err.vv:6:7: error: cannot cast `none` to `i64` 4 | _ := i8(none) 5 | _ := i16(none) 6 | _ := i64(none) - | ~~~~ + | ~~~~~~~~~ 7 | _ := u16(none) 8 | _ := u32(none) -vlib/v/checker/tests/none_type_cast_err.vv:7:11: error: cannot cast `none` to `u16` +vlib/v/checker/tests/none_type_cast_err.vv:7:7: error: cannot cast `none` to `u16` 5 | _ := i16(none) 6 | _ := i64(none) 7 | _ := u16(none) - | ~~~~ + | ~~~~~~~~~ 8 | _ := u32(none) 9 | _ := u64(none) -vlib/v/checker/tests/none_type_cast_err.vv:8:11: error: cannot cast `none` to `u32` +vlib/v/checker/tests/none_type_cast_err.vv:8:7: error: cannot cast `none` to `u32` 6 | _ := i64(none) 7 | _ := u16(none) 8 | _ := u32(none) - | ~~~~ + | ~~~~~~~~~ 9 | _ := u64(none) 10 | _ := rune(none) -vlib/v/checker/tests/none_type_cast_err.vv:9:11: error: cannot cast `none` to `u64` +vlib/v/checker/tests/none_type_cast_err.vv:9:7: error: cannot cast `none` to `u64` 7 | _ := u16(none) 8 | _ := u32(none) 9 | _ := u64(none) - | ~~~~ + | ~~~~~~~~~ 10 | _ := rune(none) 11 | _ := f32(none) -vlib/v/checker/tests/none_type_cast_err.vv:10:12: error: cannot cast `none` to `rune` +vlib/v/checker/tests/none_type_cast_err.vv:10:7: error: cannot cast `none` to `rune` 8 | _ := u32(none) 9 | _ := u64(none) 10 | _ := rune(none) - | ~~~~ + | ~~~~~~~~~~ 11 | _ := f32(none) 12 | _ := f64(none) -vlib/v/checker/tests/none_type_cast_err.vv:11:11: error: cannot cast `none` to `f32` +vlib/v/checker/tests/none_type_cast_err.vv:11:7: error: cannot cast `none` to `f32` 9 | _ := u64(none) 10 | _ := rune(none) 11 | _ := f32(none) - | ~~~~ + | ~~~~~~~~~ 12 | _ := f64(none) 13 | } -vlib/v/checker/tests/none_type_cast_err.vv:12:11: error: cannot cast `none` to `f64` +vlib/v/checker/tests/none_type_cast_err.vv:12:7: error: cannot cast `none` to `f64` 10 | _ := rune(none) 11 | _ := f32(none) 12 | _ := f64(none) - | ~~~~ - 13 | } + | ~~~~~~~~~ + 13 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/struct_cast_to_struct_generic_err.out b/vlib/v/checker/tests/struct_cast_to_struct_generic_err.out index 8d8cd9048c..b87dc3beaa 100644 --- a/vlib/v/checker/tests/struct_cast_to_struct_generic_err.out +++ b/vlib/v/checker/tests/struct_cast_to_struct_generic_err.out @@ -1,6 +1,6 @@ -vlib/v/checker/tests/struct_cast_to_struct_generic_err.vv:11:11: error: cannot convert struct `Abc` to struct `Xyz` +vlib/v/checker/tests/struct_cast_to_struct_generic_err.vv:11:7: error: cannot convert struct `Abc` to struct `Xyz` 9 | fn main() { 10 | abc := Abc{} 11 | _ := Xyz(abc) - | ~~~ + | ~~~~~~~~ 12 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/struct_cast_to_struct_mut_err_a.out b/vlib/v/checker/tests/struct_cast_to_struct_mut_err_a.out index 09ba707ae3..e5e5b8478f 100644 --- a/vlib/v/checker/tests/struct_cast_to_struct_mut_err_a.out +++ b/vlib/v/checker/tests/struct_cast_to_struct_mut_err_a.out @@ -1,6 +1,6 @@ -vlib/v/checker/tests/struct_cast_to_struct_mut_err_a.vv:12:11: error: cannot convert struct `Abc` to struct `Xyz` +vlib/v/checker/tests/struct_cast_to_struct_mut_err_a.vv:12:7: error: cannot convert struct `Abc` to struct `Xyz` 10 | fn main() { 11 | abc := Abc{} 12 | _ := Xyz(abc) - | ~~~ + | ~~~~~~~~ 13 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/struct_cast_to_struct_mut_err_b.out b/vlib/v/checker/tests/struct_cast_to_struct_mut_err_b.out index bf90a932aa..766b1249aa 100644 --- a/vlib/v/checker/tests/struct_cast_to_struct_mut_err_b.out +++ b/vlib/v/checker/tests/struct_cast_to_struct_mut_err_b.out @@ -1,6 +1,6 @@ -vlib/v/checker/tests/struct_cast_to_struct_mut_err_b.vv:12:11: error: cannot convert struct `Abc` to struct `Xyz` +vlib/v/checker/tests/struct_cast_to_struct_mut_err_b.vv:12:7: error: cannot convert struct `Abc` to struct `Xyz` 10 | fn main() { 11 | abc := Abc{} 12 | _ := Xyz(abc) - | ~~~ + | ~~~~~~~~ 13 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/struct_cast_to_struct_pub_err_a.out b/vlib/v/checker/tests/struct_cast_to_struct_pub_err_a.out index 078cd12868..9ed7491fac 100644 --- a/vlib/v/checker/tests/struct_cast_to_struct_pub_err_a.out +++ b/vlib/v/checker/tests/struct_cast_to_struct_pub_err_a.out @@ -1,6 +1,6 @@ -vlib/v/checker/tests/struct_cast_to_struct_pub_err_a.vv:12:11: error: cannot convert struct `Abc` to struct `Xyz` +vlib/v/checker/tests/struct_cast_to_struct_pub_err_a.vv:12:7: error: cannot convert struct `Abc` to struct `Xyz` 10 | fn main() { 11 | abc := Abc{} 12 | _ := Xyz(abc) - | ~~~ + | ~~~~~~~~ 13 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/struct_cast_to_struct_pub_err_b.out b/vlib/v/checker/tests/struct_cast_to_struct_pub_err_b.out index f704603af7..f59dd7eb81 100644 --- a/vlib/v/checker/tests/struct_cast_to_struct_pub_err_b.out +++ b/vlib/v/checker/tests/struct_cast_to_struct_pub_err_b.out @@ -1,6 +1,6 @@ -vlib/v/checker/tests/struct_cast_to_struct_pub_err_b.vv:12:11: error: cannot convert struct `Abc` to struct `Xyz` +vlib/v/checker/tests/struct_cast_to_struct_pub_err_b.vv:12:7: error: cannot convert struct `Abc` to struct `Xyz` 10 | fn main() { 11 | abc := Abc{} 12 | _ := Xyz(abc) - | ~~~ + | ~~~~~~~~ 13 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/sum.out b/vlib/v/checker/tests/sum.out index 670c58ed71..8f57bcfb49 100644 --- a/vlib/v/checker/tests/sum.out +++ b/vlib/v/checker/tests/sum.out @@ -12,11 +12,11 @@ vlib/v/checker/tests/sum.vv:6:8: error: cannot cast non-sum type `int` using `as | ~~ 7 | } 8 | -vlib/v/checker/tests/sum.vv:10:11: error: cannot cast `rune` to `Var` - 8 | +vlib/v/checker/tests/sum.vv:10:7: error: cannot cast `rune` to `Var` + 8 | 9 | fn sum() { 10 | _ := Var(`J`) - | ~~~ + | ~~~~~~~~ 11 | mut s2 := Var('') 12 | s2 = true vlib/v/checker/tests/sum.vv:12:7: error: cannot assign to `s2`: expected `Var`, not `bool` @@ -24,4 +24,4 @@ vlib/v/checker/tests/sum.vv:12:7: error: cannot assign to `s2`: expected `Var`, 11 | mut s2 := Var('') 12 | s2 = true | ~~~~ - 13 | } + 13 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/warnings_for_string_c2v_calls.out b/vlib/v/checker/tests/warnings_for_string_c2v_calls.out index da7a6ae3d9..6cafd50b02 100644 --- a/vlib/v/checker/tests/warnings_for_string_c2v_calls.out +++ b/vlib/v/checker/tests/warnings_for_string_c2v_calls.out @@ -1,14 +1,14 @@ -vlib/v/checker/tests/warnings_for_string_c2v_calls.vv:8:14: error: to convert a C string buffer pointer to a V string, please use x.vstring() instead of string(x) +vlib/v/checker/tests/warnings_for_string_c2v_calls.vv:8:7: error: to convert a C string buffer pointer to a V string, please use x.vstring() instead of string(x) 6 | p[2] = `z` 7 | } 8 | x := string(p) - | ^ + | ~~~~~~~~~ 9 | y := string(p, 10) 10 | eprintln('x: $x | y: $y') -vlib/v/checker/tests/warnings_for_string_c2v_calls.vv:9:14: error: to convert a C string buffer pointer to a V string, please use x.vstring_with_len(len) instead of string(x,len) +vlib/v/checker/tests/warnings_for_string_c2v_calls.vv:9:7: error: to convert a C string buffer pointer to a V string, please use x.vstring_with_len(len) instead of string(x,len) 7 | } 8 | x := string(p) 9 | y := string(p, 10) - | ^ + | ~~~~~~~~~~~~~ 10 | eprintln('x: $x | y: $y') - 11 | eprintln('x.len: $x.len | y.len: $y.len') + 11 | eprintln('x.len: $x.len | y.len: $y.len') \ No newline at end of file diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 089684f747..c24b569a6a 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1059,6 +1059,7 @@ pub fn (mut p Parser) name_expr() ast.Expr { is_mod_cast || (!(name.len > 1 && name[0] == `C` && name[1] == `.`) && name[0].is_capital()) { // MainLetter(x) is *always* a cast, as long as it is not `C.` // TODO handle C.stat() + start_pos := p.tok.position() mut to_typ := p.parse_type() if p.is_amp { // Handle `&Foo(0)` @@ -1079,13 +1080,14 @@ pub fn (mut p Parser) name_expr() ast.Expr { arg = p.expr(0) // len has_arg = true } + end_pos := p.tok.position() p.check(.rpar) node = ast.CastExpr{ typ: to_typ expr: expr arg: arg has_arg: has_arg - pos: expr.position() + pos: start_pos.extend(end_pos) } p.expr_mod = '' return node