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() {