diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index a40d1e6bdc9..de8749c43d9 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -300,7 +300,7 @@ impl<'a> Classifier<'a> {
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal,
"$crate" => Class::KeyWord,
- _ if tas.tok.is_any_keyword() => Class::KeyWord,
+ _ if tas.tok.is_reserved_ident() => Class::KeyWord,
_ => {
if self.in_macro_nonterminal {
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index e2656bea483..a35b278a4b0 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1283,7 +1283,7 @@ impl<'a> StringReader<'a> {
});
let keyword_checking_token = &token::Ident(keyword_checking_ident);
let last_bpos = self.pos;
- if keyword_checking_token.is_any_keyword() &&
+ if keyword_checking_token.is_reserved_ident() &&
!keyword_checking_token.is_keyword(keywords::Static) {
self.err_span_(start, last_bpos, "lifetimes cannot use keyword names");
}
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 5b0031b2f17..64506c4af46 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -511,14 +511,13 @@ impl<'a> Parser<'a> {
}
pub fn this_token_descr(&self) -> String {
- let s = self.this_token_to_string();
- if self.token.is_strict_keyword() {
- format!("keyword `{}`", s)
- } else if self.token.is_reserved_keyword() {
- format!("reserved keyword `{}`", s)
- } else {
- format!("`{}`", s)
- }
+ let prefix = match &self.token {
+ t if t.is_special_ident() => "reserved identifier ",
+ t if t.is_used_keyword() => "keyword ",
+ t if t.is_unused_keyword() => "reserved keyword ",
+ _ => "",
+ };
+ format!("{}`{}`", prefix, self.this_token_to_string())
}
pub fn unexpected_last(&self, t: &token::Token) -> PResult<'a, T> {
@@ -637,10 +636,12 @@ impl<'a> Parser<'a> {
}
pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
- self.check_strict_keywords();
- self.check_reserved_keywords();
match self.token {
token::Ident(i) => {
+ if self.token.is_reserved_ident() {
+ self.span_err(self.span, &format!("expected identifier, found {}",
+ self.this_token_descr()));
+ }
self.bump();
Ok(i)
}
@@ -713,25 +714,6 @@ impl<'a> Parser<'a> {
}
}
- /// Signal an error if the given string is a strict keyword
- pub fn check_strict_keywords(&mut self) {
- if self.token.is_strict_keyword() {
- let token_str = self.this_token_to_string();
- let span = self.span;
- self.span_err(span,
- &format!("expected identifier, found keyword `{}`",
- token_str));
- }
- }
-
- /// Signal an error if the current token is a reserved keyword
- pub fn check_reserved_keywords(&mut self) {
- if self.token.is_reserved_keyword() {
- let token_str = self.this_token_to_string();
- self.fatal(&format!("`{}` is a reserved keyword", token_str)).emit()
- }
- }
-
fn check_ident(&mut self) -> bool {
if self.token.is_ident() {
true
@@ -2301,7 +2283,7 @@ impl<'a> Parser<'a> {
ex = ExprKind::Break(lt, e);
hi = self.prev_span;
} else if self.token.is_keyword(keywords::Let) {
- // Catch this syntax error here, instead of in `check_strict_keywords`, so
+ // Catch this syntax error here, instead of in `parse_ident`, so
// that we can explicitly mention that let is not to be used as an expression
let mut db = self.fatal("expected expression, found statement (`let`)");
db.note("variable declaration using `let` is a statement");
@@ -3540,7 +3522,7 @@ impl<'a> Parser<'a> {
// Parse box pat
let subpat = self.parse_pat()?;
pat = PatKind::Box(subpat);
- } else if self.token.is_ident() && !self.token.is_any_keyword() &&
+ } else if self.token.is_ident() && !self.token.is_reserved_ident() &&
self.parse_as_ident() {
// Parse ident @ pat
// This can give false positives and parse nullary enums,
@@ -3815,7 +3797,7 @@ impl<'a> Parser<'a> {
fn is_union_item(&self) -> bool {
self.token.is_keyword(keywords::Union) &&
- self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword())
+ self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
}
fn is_defaultness(&self) -> bool {
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index d6a4dc2ee96..75969cf2eb8 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -87,7 +87,7 @@ impl Lit {
fn ident_can_begin_expr(ident: ast::Ident) -> bool {
let ident_token: Token = Ident(ident);
- !ident_token.is_any_keyword() ||
+ !ident_token.is_reserved_ident() ||
ident_token.is_path_segment_keyword() ||
[
keywords::Do.name(),
@@ -110,7 +110,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool {
fn ident_can_begin_type(ident: ast::Ident) -> bool {
let ident_token: Token = Ident(ident);
- !ident_token.is_any_keyword() ||
+ !ident_token.is_reserved_ident() ||
ident_token.is_path_segment_keyword() ||
[
keywords::For.name(),
@@ -315,7 +315,7 @@ impl Token {
pub fn is_path_start(&self) -> bool {
self == &ModSep || self.is_qpath_start() || self.is_path() ||
- self.is_path_segment_keyword() || self.is_ident() && !self.is_any_keyword()
+ self.is_path_segment_keyword() || self.is_ident() && !self.is_reserved_ident()
}
/// Returns `true` if the token is a given keyword, `kw`.
@@ -333,13 +333,17 @@ impl Token {
}
}
- /// Returns `true` if the token is either a strict or reserved keyword.
- pub fn is_any_keyword(&self) -> bool {
- self.is_strict_keyword() || self.is_reserved_keyword()
+ // Returns true for reserved identifiers used internally for elided lifetimes,
+ // unnamed method parameters, crate root module, error recovery etc.
+ pub fn is_special_ident(&self) -> bool {
+ match self.ident() {
+ Some(id) => id.name <= keywords::DollarCrate.name(),
+ _ => false,
+ }
}
- /// Returns `true` if the token is a strict keyword.
- pub fn is_strict_keyword(&self) -> bool {
+ /// Returns `true` if the token is a keyword used in the language.
+ pub fn is_used_keyword(&self) -> bool {
match self.ident() {
Some(id) => id.name >= keywords::As.name() && id.name <= keywords::While.name(),
_ => false,
@@ -347,12 +351,17 @@ impl Token {
}
/// Returns `true` if the token is a keyword reserved for possible future use.
- pub fn is_reserved_keyword(&self) -> bool {
+ pub fn is_unused_keyword(&self) -> bool {
match self.ident() {
Some(id) => id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name(),
_ => false,
}
}
+
+ /// Returns `true` if the token is either a special identifier or a keyword.
+ pub fn is_reserved_ident(&self) -> bool {
+ self.is_special_ident() || self.is_used_keyword() || self.is_unused_keyword()
+ }
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 5e2e448f741..debac70545a 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -237,77 +237,76 @@ macro_rules! declare_keywords {(
// NB: leaving holes in the ident table is bad! a different ident will get
// interned with the id from the hole, but it will be between the min and max
// of the reserved words, and thus tagged as "reserved".
-// After modifying this list adjust `is_strict_keyword`/`is_reserved_keyword`,
+// After modifying this list adjust `is_special_ident`, `is_used_keyword`/`is_unused_keyword`,
// this should be rarely necessary though if the keywords are kept in alphabetic order.
declare_keywords! {
- // Invalid identifier
+ // Special reserved identifiers used internally for elided lifetimes,
+ // unnamed method parameters, crate root module, error recovery etc.
(0, Invalid, "")
+ (1, CrateRoot, "{{root}}")
+ (2, DollarCrate, "$crate")
- // Strict keywords used in the language.
- (1, As, "as")
- (2, Box, "box")
- (3, Break, "break")
- (4, Const, "const")
- (5, Continue, "continue")
- (6, Crate, "crate")
- (7, DollarCrate, "$crate")
- (8, Else, "else")
- (9, Enum, "enum")
- (10, Extern, "extern")
- (11, False, "false")
- (12, Fn, "fn")
- (13, For, "for")
- (14, If, "if")
- (15, Impl, "impl")
- (16, In, "in")
- (17, Let, "let")
- (18, Loop, "loop")
- (19, Match, "match")
- (20, Mod, "mod")
- (21, Move, "move")
- (22, Mut, "mut")
- (23, Pub, "pub")
- (24, Ref, "ref")
- (25, Return, "return")
- (26, SelfValue, "self")
- (27, SelfType, "Self")
- (28, Static, "static")
- (29, Struct, "struct")
- (30, Super, "super")
- (31, Trait, "trait")
- (32, True, "true")
- (33, Type, "type")
- (34, Unsafe, "unsafe")
- (35, Use, "use")
- (36, Where, "where")
- (37, While, "while")
+ // Keywords used in the language.
+ (3, As, "as")
+ (4, Box, "box")
+ (5, Break, "break")
+ (6, Const, "const")
+ (7, Continue, "continue")
+ (8, Crate, "crate")
+ (9, Else, "else")
+ (10, Enum, "enum")
+ (11, Extern, "extern")
+ (12, False, "false")
+ (13, Fn, "fn")
+ (14, For, "for")
+ (15, If, "if")
+ (16, Impl, "impl")
+ (17, In, "in")
+ (18, Let, "let")
+ (19, Loop, "loop")
+ (20, Match, "match")
+ (21, Mod, "mod")
+ (22, Move, "move")
+ (23, Mut, "mut")
+ (24, Pub, "pub")
+ (25, Ref, "ref")
+ (26, Return, "return")
+ (27, SelfValue, "self")
+ (28, SelfType, "Self")
+ (29, Static, "static")
+ (30, Struct, "struct")
+ (31, Super, "super")
+ (32, Trait, "trait")
+ (33, True, "true")
+ (34, Type, "type")
+ (35, Unsafe, "unsafe")
+ (36, Use, "use")
+ (37, Where, "where")
+ (38, While, "while")
// Keywords reserved for future use.
- (38, Abstract, "abstract")
- (39, Alignof, "alignof")
- (40, Become, "become")
- (41, Do, "do")
- (42, Final, "final")
- (43, Macro, "macro")
- (44, Offsetof, "offsetof")
- (45, Override, "override")
- (46, Priv, "priv")
- (47, Proc, "proc")
- (48, Pure, "pure")
- (49, Sizeof, "sizeof")
- (50, Typeof, "typeof")
- (51, Unsized, "unsized")
- (52, Virtual, "virtual")
- (53, Yield, "yield")
+ (39, Abstract, "abstract")
+ (40, Alignof, "alignof")
+ (41, Become, "become")
+ (42, Do, "do")
+ (43, Final, "final")
+ (44, Macro, "macro")
+ (45, Offsetof, "offsetof")
+ (46, Override, "override")
+ (47, Priv, "priv")
+ (48, Proc, "proc")
+ (49, Pure, "pure")
+ (50, Sizeof, "sizeof")
+ (51, Typeof, "typeof")
+ (52, Unsized, "unsized")
+ (53, Virtual, "virtual")
+ (54, Yield, "yield")
// Weak keywords, have special meaning only in specific contexts.
- (54, Default, "default")
- (55, StaticLifetime, "'static")
- (56, Union, "union")
- (57, Catch, "catch")
-
- // A virtual keyword that resolves to the crate root when used in a lexical scope.
- (58, CrateRoot, "{{root}}")
+ (55, Default, "default")
+ (56, StaticLifetime, "'static")
+ (57, Union, "union")
+ (58, Catch, "catch")
}
// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
diff --git a/src/test/compile-fail/dollar-crate-is-keyword.rs b/src/test/compile-fail/dollar-crate-is-keyword.rs
index 0bd47a0e11a..70597a230a8 100644
--- a/src/test/compile-fail/dollar-crate-is-keyword.rs
+++ b/src/test/compile-fail/dollar-crate-is-keyword.rs
@@ -10,11 +10,11 @@
macro_rules! m {
() => {
- struct $crate {} //~ ERROR expected identifier, found keyword `$crate`
+ struct $crate {} //~ ERROR expected identifier, found reserved identifier `$crate`
use $crate; // OK
//~^ WARN `$crate` may not be imported
- use $crate as $crate; //~ ERROR expected identifier, found keyword `$crate`
+ use $crate as $crate; //~ ERROR expected identifier, found reserved identifier `$crate`
//~^ WARN `$crate` may not be imported
}
}
diff --git a/src/test/parse-fail/macro-keyword.rs b/src/test/parse-fail/macro-keyword.rs
index 6a7ccff1554..c7dcaf4137e 100644
--- a/src/test/parse-fail/macro-keyword.rs
+++ b/src/test/parse-fail/macro-keyword.rs
@@ -10,7 +10,7 @@
// compile-flags: -Z parse-only
-fn macro() { //~ ERROR `macro` is a reserved keyword
+fn macro() { //~ ERROR expected identifier, found reserved keyword `macro`
}
pub fn main() {