Skip to content

Commit acc9428

Browse files
committed
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 rust-lang#30033
1 parent d3c83fe commit acc9428

File tree

6 files changed

+81
-16
lines changed

6 files changed

+81
-16
lines changed

src/libsyntax/parse/lexer/mod.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,7 @@ impl<'a> StringReader<'a> {
11951195
}
11961196
'\'' => {
11971197
// Either a character constant 'a' OR a lifetime name 'abc
1198+
let start_with_quote = self.last_pos;
11981199
self.bump();
11991200
let start = self.last_pos;
12001201

@@ -1208,6 +1209,14 @@ impl<'a> StringReader<'a> {
12081209
while ident_continue(self.curr) {
12091210
self.bump();
12101211
}
1212+
// lifetimes shouldn't end with a single quote
1213+
// if we find one, then this is an invalid character literal
1214+
if self.curr_is('\'') {
1215+
panic!(self.fatal_span_verbose(
1216+
start_with_quote, self.pos,
1217+
String::from("character literal may only contain one codepoint")));
1218+
1219+
}
12111220

12121221
// Include the leading `'` in the real identifier, for macro
12131222
// expansion purposes. See #12512 for the gory details of why
@@ -1233,26 +1242,22 @@ impl<'a> StringReader<'a> {
12331242
!keyword_checking_token.is_keyword(token::keywords::Static) {
12341243
self.err_span_(start, last_bpos, "invalid lifetime name");
12351244
}
1245+
12361246
return token::Lifetime(ident);
12371247
}
12381248

1239-
// Otherwise it is a character constant:
12401249
let valid = self.scan_char_or_byte(start,
12411250
c2,
12421251
// ascii_only =
12431252
false,
12441253
'\'');
1254+
12451255
if !self.curr_is('\'') {
1246-
let last_bpos = self.last_pos;
1247-
panic!(self.fatal_span_verbose(// Byte offsetting here is okay because the
1248-
// character before position `start` is an
1249-
// ascii single quote.
1250-
start - BytePos(1),
1251-
last_bpos,
1252-
1253-
String::from("character literal may only \
1254-
contain one codepoint")));
1256+
panic!(self.fatal_span_verbose(
1257+
start_with_quote, self.last_pos,
1258+
String::from("character literal may only contain one codepoint")));
12551259
}
1260+
12561261
let id = if valid {
12571262
self.name_from(start)
12581263
} else {

src/test/parse-fail/lex-bad-char-literals.rs renamed to src/test/parse-fail/lex-bad-char-literals-1.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -25,8 +25,3 @@ static s: &'static str =
2525
"\●" //~ ERROR: unknown character escape
2626
;
2727

28-
// THIS MUST BE LAST, since it kills the lexer
29-
30-
static c: char =
31-
'//~ ERROR: character literal may only contain one codepoint
32-
;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z parse-only
12+
13+
// This test needs to the last one appearing in this file as it kills the parser
14+
static c: char =
15+
'nope' //~ ERROR: character literal may only contain one codepoint: 'nope'
16+
;
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z parse-only
12+
13+
// This test needs to the last one appearing in this file as it kills the parser
14+
static c: char =
15+
'●●' //~ ERROR: character literal may only contain one codepoint: '●
16+
;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z parse-only
12+
//
13+
// This test needs to the last one appearing in this file as it kills the parser
14+
static c: char =
15+
'//~ ERROR: character literal may only contain one codepoint: '●
16+
;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z parse-only
12+
//
13+
// This test needs to the last one appearing in this file as it kills the parser
14+
static c: char =
15+
'\x10\x10' //~ ERROR: character literal may only contain one codepoint: '\x10
16+
;

0 commit comments

Comments
 (0)