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
This commit is contained in:
Greg Chapple 2016-01-07 16:12:28 +00:00
parent d3c83fef24
commit acc9428c6a
6 changed files with 81 additions and 16 deletions

View file

@ -1195,6 +1195,7 @@ impl<'a> StringReader<'a> {
} }
'\'' => { '\'' => {
// Either a character constant 'a' OR a lifetime name 'abc // Either a character constant 'a' OR a lifetime name 'abc
let start_with_quote = self.last_pos;
self.bump(); self.bump();
let start = self.last_pos; let start = self.last_pos;
@ -1208,6 +1209,14 @@ impl<'a> StringReader<'a> {
while ident_continue(self.curr) { while ident_continue(self.curr) {
self.bump(); 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 // Include the leading `'` in the real identifier, for macro
// expansion purposes. See #12512 for the gory details of why // 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) { !keyword_checking_token.is_keyword(token::keywords::Static) {
self.err_span_(start, last_bpos, "invalid lifetime name"); self.err_span_(start, last_bpos, "invalid lifetime name");
} }
return token::Lifetime(ident); return token::Lifetime(ident);
} }
// Otherwise it is a character constant:
let valid = self.scan_char_or_byte(start, let valid = self.scan_char_or_byte(start,
c2, c2,
// ascii_only = // ascii_only =
false, 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 \ if !self.curr_is('\'') {
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 { let id = if valid {
self.name_from(start) self.name_from(start)
} else { } else {

View file

@ -1,4 +1,4 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
@ -25,8 +25,3 @@ static s: &'static str =
"\" //~ ERROR: unknown character escape "\" //~ ERROR: unknown character escape
; ;
// THIS MUST BE LAST, since it kills the lexer
static c: char =
' //~ ERROR: character literal may only contain one codepoint
;

View file

@ -0,0 +1,17 @@
// Copyright 2016 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Z parse-only
// This test needs to the last one appearing in this file as it kills the parser
static c: char =
'nope' //~ ERROR: character literal may only contain one codepoint: 'nope'
;

View file

@ -0,0 +1,16 @@
// Copyright 2016 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Z parse-only
// This test needs to the last one appearing in this file as it kills the parser
static c: char =
'' //~ ERROR: character literal may only contain one codepoint: '●
;

View file

@ -0,0 +1,16 @@
// Copyright 2016 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Z parse-only
//
// This test needs to the last one appearing in this file as it kills the parser
static c: char =
' //~ ERROR: character literal may only contain one codepoint: '●
;

View file

@ -0,0 +1,16 @@
// Copyright 2016 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Z parse-only
//
// This test needs to the last one appearing in this file as it kills the parser
static c: char =
'\x10\x10' //~ ERROR: character literal may only contain one codepoint: '\x10
;