From f029f7e897de0f0dcebc48fd7f7cf3087ac2ad88 Mon Sep 17 00:00:00 2001 From: shadowninja55 <49539636+shadowninja55@users.noreply.github.com> Date: Wed, 30 Jun 2021 01:16:31 -0400 Subject: [PATCH] checker: prohibit `char.str()`, add tests (#10615) --- vlib/v/checker/checker.v | 14 +++++++++++--- vlib/v/checker/tests/char_str.out | 3 +++ vlib/v/checker/tests/char_str.vv | 1 + vlib/v/checker/tests/print_char.out | 3 +++ vlib/v/checker/tests/print_char.vv | 1 + 5 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 vlib/v/checker/tests/char_str.out create mode 100644 vlib/v/checker/tests/char_str.vv create mode 100644 vlib/v/checker/tests/print_char.out create mode 100644 vlib/v/checker/tests/print_char.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index d1311af330..f070c6fa42 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1839,6 +1839,10 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type { } call_expr.return_type = info.return_type return info.return_type + } else if left_type_sym.kind == .char && left_type.nr_muls() == 0 && method_name == 'str' { + c.error('calling `.str()` on type `char` is not allowed, use its address or cast it to an integer instead', + call_expr.left.position().extend(call_expr.pos)) + return ast.void_type } mut method := ast.Fn{} mut has_method := false @@ -2492,11 +2496,15 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type { c.inside_println_arg = true c.expected_type = ast.string_type call_expr.args[0].typ = c.expr(call_expr.args[0].expr) - _ := c.check_expr_opt_call(call_expr.args[0].expr, call_expr.args[0].typ) - if call_expr.args[0].typ.is_void() { + arg := call_expr.args[0] + _ := c.check_expr_opt_call(arg.expr, arg.typ) + if arg.typ.is_void() { c.error('`$fn_name` can not print void expressions', call_expr.pos) + } else if arg.typ == ast.char_type && arg.typ.nr_muls() == 0 { + c.error('`$fn_name` cannot print type `char` directly, print its address or cast it to an integer instead', + call_expr.pos) } - c.fail_if_unreadable(call_expr.args[0].expr, call_expr.args[0].typ, 'argument to print') + c.fail_if_unreadable(arg.expr, arg.typ, 'argument to print') c.inside_println_arg = false /* // TODO: optimize `struct T{} fn (t &T) str() string {return 'abc'} mut a := []&T{} a << &T{} println(a[0])` diff --git a/vlib/v/checker/tests/char_str.out b/vlib/v/checker/tests/char_str.out new file mode 100644 index 0000000000..9779e645b1 --- /dev/null +++ b/vlib/v/checker/tests/char_str.out @@ -0,0 +1,3 @@ +vlib/v/checker/tests/char_str.vv:1:1: error: calling `.str()` on type `char` is not allowed, use its address or cast it to an integer instead + 1 | char(91).str() + | ~~~~~~~~~~~~~~ diff --git a/vlib/v/checker/tests/char_str.vv b/vlib/v/checker/tests/char_str.vv new file mode 100644 index 0000000000..88d9a9bacb --- /dev/null +++ b/vlib/v/checker/tests/char_str.vv @@ -0,0 +1 @@ +char(91).str() diff --git a/vlib/v/checker/tests/print_char.out b/vlib/v/checker/tests/print_char.out new file mode 100644 index 0000000000..055ec110b5 --- /dev/null +++ b/vlib/v/checker/tests/print_char.out @@ -0,0 +1,3 @@ +vlib/v/checker/tests/print_char.vv:1:1: error: `println` cannot print type `char` directly, print its address or cast it to an integer instead + 1 | println(char(91)) + | ~~~~~~~~~~~~~~~~~ diff --git a/vlib/v/checker/tests/print_char.vv b/vlib/v/checker/tests/print_char.vv new file mode 100644 index 0000000000..9ddba8a43b --- /dev/null +++ b/vlib/v/checker/tests/print_char.vv @@ -0,0 +1 @@ +println(char(91))