Skip to content

Commit a70a60a

Browse files
committed
Auto merge of #30763 - gchp:issue/30033, r=nagisa
This is achieved by adding the scan_back method. This method looks back through the source_text of the StringReader until it finds the target char, returning it's offset in the source. We use this method to find the offset of the opening single quote, and use that offset as the start of the error. Given this code: ```rust 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
2 parents d8869d3 + acc9428 commit a70a60a

File tree

6 files changed

+81
-16
lines changed

6 files changed

+81
-16
lines changed

Diff for: 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 {

Diff for: 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-
;

Diff for: src/test/parse-fail/lex-bad-char-literals-2.rs

+17
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+

Diff for: src/test/parse-fail/lex-bad-char-literals-3.rs

+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+
;

Diff for: src/test/parse-fail/lex-bad-char-literals-4.rs

+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+
;

Diff for: src/test/parse-fail/lex-bad-char-literals-5.rs

+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)