Skip to content

Commit 0a505a7

Browse files
committed
Parse lifetimes that start with a number and give specific error
1 parent 2a65cbe commit 0a505a7

File tree

3 files changed

+50
-6
lines changed

3 files changed

+50
-6
lines changed

src/libsyntax/parse/lexer/mod.rs

+18-6
Original file line numberDiff line numberDiff line change
@@ -1423,15 +1423,17 @@ impl<'a> StringReader<'a> {
14231423

14241424
// If the character is an ident start not followed by another single
14251425
// quote, then this is a lifetime name:
1426-
if ident_start(Some(c2)) && !self.ch_is('\'') {
1426+
if (ident_start(Some(c2)) || c2.is_numeric()) && !self.ch_is('\'') {
14271427
while ident_continue(self.ch) {
14281428
self.bump();
14291429
}
14301430
// lifetimes shouldn't end with a single quote
14311431
// if we find one, then this is an invalid character literal
14321432
if self.ch_is('\'') {
1433-
self.err_span_(start_with_quote, self.next_pos,
1434-
"character literal may only contain one codepoint");
1433+
self.err_span_(
1434+
start_with_quote,
1435+
self.next_pos,
1436+
"character literal may only contain one codepoint");
14351437
self.bump();
14361438
return Ok(token::Literal(token::Err(Symbol::intern("??")), None))
14371439

@@ -1444,6 +1446,16 @@ impl<'a> StringReader<'a> {
14441446
self.mk_ident(&format!("'{}", lifetime_name))
14451447
});
14461448

1449+
if c2.is_numeric() {
1450+
// this is a recovered lifetime written `'1`, error but accept it
1451+
self.err_span_(
1452+
start_with_quote,
1453+
self.pos,
1454+
"lifetimes can't start with a number",
1455+
);
1456+
}
1457+
1458+
14471459
return Ok(token::Lifetime(ident));
14481460
}
14491461

@@ -1873,13 +1885,14 @@ fn is_block_doc_comment(s: &str) -> bool {
18731885
res
18741886
}
18751887

1888+
/// Determine whether `c` is a valid start for an ident.
18761889
fn ident_start(c: Option<char>) -> bool {
18771890
let c = match c {
18781891
Some(c) => c,
18791892
None => return false,
18801893
};
18811894

1882-
(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c > '\x7f' && c.is_xid_start())
1895+
(c.is_alphabetic() || c == '_' || (c > '\x7f' && c.is_xid_start()))
18831896
}
18841897

18851898
fn ident_continue(c: Option<char>) -> bool {
@@ -1888,8 +1901,7 @@ fn ident_continue(c: Option<char>) -> bool {
18881901
None => return false,
18891902
};
18901903

1891-
(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' ||
1892-
(c > '\x7f' && c.is_xid_continue())
1904+
(c.is_alphabetic() || c.is_numeric() || c == '_' || (c > '\x7f' && c.is_xid_continue()))
18931905
}
18941906

18951907
#[inline]
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
struct S<'1> { s: &'1 usize }
2+
//~^ ERROR lifetimes can't start with a number
3+
//~| ERROR lifetimes can't start with a number
4+
fn main() {
5+
// verify that the parse error doesn't stop type checking
6+
let x: usize = "";
7+
//~^ ERROR mismatched types
8+
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: lifetimes can't start with a number
2+
--> $DIR/numeric-lifetime.rs:1:10
3+
|
4+
LL | struct S<'1> { s: &'1 usize }
5+
| ^^
6+
7+
error: lifetimes can't start with a number
8+
--> $DIR/numeric-lifetime.rs:1:20
9+
|
10+
LL | struct S<'1> { s: &'1 usize }
11+
| ^^
12+
13+
error[E0308]: mismatched types
14+
--> $DIR/numeric-lifetime.rs:6:20
15+
|
16+
LL | let x: usize = "";
17+
| ^^ expected usize, found reference
18+
|
19+
= note: expected type `usize`
20+
found type `&'static str`
21+
22+
error: aborting due to 3 previous errors
23+
24+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)