diff --git a/vlib/builtin/string_test.v b/vlib/builtin/string_test.v index d52969abab..2eb58a4926 100644 --- a/vlib/builtin/string_test.v +++ b/vlib/builtin/string_test.v @@ -729,6 +729,12 @@ fn test_raw() { raw2 := r'Hello V\0' assert raw2[7] == `\\` assert raw2[8] == `0` + + raw3 := r'Hello V\x00' + assert raw3[7] == `\\` + assert raw3[8] == `x` + assert raw3[9] == `0` + assert raw3[10] == `0` } fn test_raw_with_quotes() { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 853033e49b..2b0404ebdc 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1358,7 +1358,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { return f.return_type } // println can print anything - if (fn_name == 'println' || fn_name == 'print') && call_expr.args.len > 0 { + if fn_name in ['println', 'print'] && call_expr.args.len > 0 { c.expected_type = table.string_type call_expr.args[0].typ = c.expr(call_expr.args[0].expr) // check optional argument diff --git a/vlib/v/checker/tests/string_char_null_err.out b/vlib/v/checker/tests/string_char_null_err.out index 942bfd1f99..60e1f7af1a 100644 --- a/vlib/v/checker/tests/string_char_null_err.out +++ b/vlib/v/checker/tests/string_char_null_err.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/string_char_null_err.vv:2:31: error: 0 character in a string literal +vlib/v/checker/tests/string_char_null_err.vv:2:31: error: cannot use `\0` (NULL character) in the string literal 1 | fn main() { 2 | println('Null character: \0') | ^ diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index d440629841..7b5a89e1a3 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -994,6 +994,11 @@ pub fn (mut p Parser) name_expr() ast.Expr { if p.tok.lit in ['r', 'c', 'js'] && p.peek_tok.kind == .string && !p.inside_str_interp { return p.string_expr() } + // don't allow r`byte` and c`byte` + if p.tok.lit in ['r', 'c'] && p.peek_tok.kind == .chartoken { + opt := if p.tok.lit == 'r' { '`r` (raw string)' } else { '`c` (c string)' } + p.error('cannot use $opt with `byte` and `rune`') + } known_var := p.mark_var_as_used(p.tok.lit) mut is_mod_cast := false if p.peek_tok.kind == .dot && !known_var && diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index db63722d91..0fc0cb90f4 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -1218,14 +1218,14 @@ fn (mut s Scanner) ident_string() string { if c == `0` && s.pos > 2 && s.text[s.pos - 1] == slash { if (s.pos < s.text.len - 1 && s.text[s.pos + 1].is_digit()) || s.count_symbol_before(s.pos - 1, slash) % 2 == 0 { } else if !is_cstr && !is_raw { - s.error('0 character in a string literal') + s.error(r'cannot use `\0` (NULL character) in the string literal') } } // Don't allow \x00 if c == `0` && s.pos > 5 && s.expect('\\x0', s.pos - 3) { if s.count_symbol_before(s.pos - 3, slash) % 2 == 0 { } else if !is_cstr && !is_raw { - s.error('0 character in a string literal') + s.error(r'cannot use `\x00` (NULL character) in the string literal') } } // ${var} (ignore in vfmt mode)