From 2661b633c50f6c43b95aca1381f25fc314544331 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 19 Sep 2013 11:55:03 -0700 Subject: [PATCH] Disallow char literals which should be escaped As documented in issue #7945, these literal identifiers are all accepted by rust today, but they should probably be disallowed (especially `'''`). This changes all escapable sequences to being *required* to be escaped. Closes #7945 --- src/libsyntax/parse/lexer.rs | 49 ++++++++++++--------- src/test/compile-fail/bad-char-literals.rs | 15 +++++++ src/test/compile-fail/bad-char-literals2.rs | 16 +++++++ src/test/compile-fail/bad-char-literals3.rs | 15 +++++++ src/test/compile-fail/bad-char-literals4.rs | 15 +++++++ 5 files changed, 89 insertions(+), 21 deletions(-) create mode 100644 src/test/compile-fail/bad-char-literals.rs create mode 100644 src/test/compile-fail/bad-char-literals2.rs create mode 100644 src/test/compile-fail/bad-char-literals3.rs create mode 100644 src/test/compile-fail/bad-char-literals4.rs diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index d3b0866d4a79c..c848f52b3eaca 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -747,27 +747,34 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token { } // Otherwise it is a character constant: - if c2 == '\\' { - // '\X' for some X must be a character constant: - let escaped = rdr.curr; - let escaped_pos = rdr.last_pos; - bump(rdr); - match escaped { - 'n' => { c2 = '\n'; } - 'r' => { c2 = '\r'; } - 't' => { c2 = '\t'; } - '\\' => { c2 = '\\'; } - '\'' => { c2 = '\''; } - '"' => { c2 = '"'; } - '0' => { c2 = '\x00'; } - 'x' => { c2 = scan_numeric_escape(rdr, 2u); } - 'u' => { c2 = scan_numeric_escape(rdr, 4u); } - 'U' => { c2 = scan_numeric_escape(rdr, 8u); } - c2 => { - fatal_span_char(rdr, escaped_pos, rdr.last_pos, - ~"unknown character escape", c2); - } + match c2 { + '\\' => { + // '\X' for some X must be a character constant: + let escaped = rdr.curr; + let escaped_pos = rdr.last_pos; + bump(rdr); + match escaped { + 'n' => { c2 = '\n'; } + 'r' => { c2 = '\r'; } + 't' => { c2 = '\t'; } + '\\' => { c2 = '\\'; } + '\'' => { c2 = '\''; } + '"' => { c2 = '"'; } + '0' => { c2 = '\x00'; } + 'x' => { c2 = scan_numeric_escape(rdr, 2u); } + 'u' => { c2 = scan_numeric_escape(rdr, 4u); } + 'U' => { c2 = scan_numeric_escape(rdr, 8u); } + c2 => { + fatal_span_char(rdr, escaped_pos, rdr.last_pos, + ~"unknown character escape", c2); + } + } + } + '\t' | '\n' | '\r' | '\'' => { + fatal_span_char(rdr, start, rdr.last_pos, + ~"character constant must be escaped", c2); } + _ => {} } if rdr.curr != '\'' { fatal_span_verbose(rdr, @@ -973,7 +980,7 @@ mod test { } #[test] fn character_escaped() { - let env = setup(@"'\n'"); + let env = setup(@"'\\n'"); let TokenAndSpan {tok, sp: _} = env.string_reader.next_token(); assert_eq!(tok, token::LIT_CHAR('\n' as u32)); diff --git a/src/test/compile-fail/bad-char-literals.rs b/src/test/compile-fail/bad-char-literals.rs new file mode 100644 index 0000000000000..53723c87a521b --- /dev/null +++ b/src/test/compile-fail/bad-char-literals.rs @@ -0,0 +1,15 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + // these literals are just silly. + '''; + //~^ ERROR: character constant must be escaped +} diff --git a/src/test/compile-fail/bad-char-literals2.rs b/src/test/compile-fail/bad-char-literals2.rs new file mode 100644 index 0000000000000..c5226cfec457b --- /dev/null +++ b/src/test/compile-fail/bad-char-literals2.rs @@ -0,0 +1,16 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + // note that this is a literal "\n" byte + ' +'; + //~^^ ERROR: character constant must be escaped +} diff --git a/src/test/compile-fail/bad-char-literals3.rs b/src/test/compile-fail/bad-char-literals3.rs new file mode 100644 index 0000000000000..9bbe5c75b1723 --- /dev/null +++ b/src/test/compile-fail/bad-char-literals3.rs @@ -0,0 +1,15 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + // note that this is a literal "\r" byte + ' '; + //~^ ERROR: character constant must be escaped +} diff --git a/src/test/compile-fail/bad-char-literals4.rs b/src/test/compile-fail/bad-char-literals4.rs new file mode 100644 index 0000000000000..675ff742d5cca --- /dev/null +++ b/src/test/compile-fail/bad-char-literals4.rs @@ -0,0 +1,15 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + // note that this is a literal tab character here + ' '; + //~^ ERROR: character constant must be escaped +}