about summary refs log tree commit diff
path: root/src/libsyntax/parse/lexer
diff options
context:
space:
mode:
authorGreg Chapple <gregchapple1@gmail.com>2016-01-07 16:12:28 +0000
committerGreg Chapple <gregchapple1@gmail.com>2016-01-14 17:34:42 +0000
commitacc9428c6a99d199f35032ec7f794385e4c9fd24 (patch)
treeea9da6f39079fa1f203a7ada38a6da79a6d7ada1 /src/libsyntax/parse/lexer
parentd3c83fef245f1cb2e523c8913b8968c98faec1f4 (diff)
downloadrust-acc9428c6a99d199f35032ec7f794385e4c9fd24.tar.gz
rust-acc9428c6a99d199f35032ec7f794385e4c9fd24.zip
Display better snippet for invalid char literal
Given this code:

    fn main() {
        let _ = 'abcd';
    }

The compiler would give a message like:

    error: character literal may only contain one codepoint: ';
    let _ = 'abcd';
                 ^~

With this change, the message now displays:

    error: character literal may only contain one codepoint: 'abcd'
    let _ = 'abcd'
            ^~~~~~

Fixes #30033
Diffstat (limited to 'src/libsyntax/parse/lexer')
-rw-r--r--src/libsyntax/parse/lexer/mod.rs25
1 files changed, 15 insertions, 10 deletions
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 1402b7888dd..3183dfbd954 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1195,6 +1195,7 @@ impl<'a> StringReader<'a> {
             }
             '\'' => {
                 // Either a character constant 'a' OR a lifetime name 'abc
+                let start_with_quote = self.last_pos;
                 self.bump();
                 let start = self.last_pos;
 
@@ -1208,6 +1209,14 @@ impl<'a> StringReader<'a> {
                     while ident_continue(self.curr) {
                         self.bump();
                     }
+                    // lifetimes shouldn't end with a single quote
+                    // if we find one, then this is an invalid character literal
+                    if self.curr_is('\'') {
+                        panic!(self.fatal_span_verbose(
+                               start_with_quote, self.pos,
+                               String::from("character literal may only contain one codepoint")));
+
+                    }
 
                     // Include the leading `'` in the real identifier, for macro
                     // expansion purposes. See #12512 for the gory details of why
@@ -1233,26 +1242,22 @@ impl<'a> StringReader<'a> {
                        !keyword_checking_token.is_keyword(token::keywords::Static) {
                         self.err_span_(start, last_bpos, "invalid lifetime name");
                     }
+
                     return token::Lifetime(ident);
                 }
 
-                // Otherwise it is a character constant:
                 let valid = self.scan_char_or_byte(start,
                                                    c2,
                                                    // ascii_only =
                                                    false,
                                                    '\'');
+
                 if !self.curr_is('\'') {
-                    let last_bpos = self.last_pos;
-                    panic!(self.fatal_span_verbose(// Byte offsetting here is okay because the
-                                                   // character before position `start` is an
-                                                   // ascii single quote.
-                                                   start - BytePos(1),
-                                                   last_bpos,
-
-                                                   String::from("character literal may only \
-                                                                 contain one codepoint")));
+                    panic!(self.fatal_span_verbose(
+                           start_with_quote, self.last_pos,
+                           String::from("character literal may only contain one codepoint")));
                 }
+
                 let id = if valid {
                     self.name_from(start)
                 } else {