From f89e3562450b4fddd36b536087d782c934dd6477 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 29 Apr 2018 02:20:46 +0300 Subject: Add two keywords specific to editions 2015 and 2018 respectively --- src/libsyntax/parse/token.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index a1c056cbb2c..cbafad253b8 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -15,13 +15,14 @@ pub use self::Lit::*; pub use self::Token::*; use ast::{self}; +use edition::Edition; use parse::ParseSess; use print::pprust; use ptr::P; use serialize::{Decodable, Decoder, Encodable, Encoder}; use symbol::keywords; use syntax::parse::parse_stream_from_source_str; -use syntax_pos::{self, Span, FileName}; +use syntax_pos::{self, hygiene, Span, FileName}; use tokenstream::{TokenStream, TokenTree}; use tokenstream; @@ -168,7 +169,11 @@ pub fn is_used_keyword(id: ast::Ident) -> bool { /// Returns `true` if the token is a keyword reserved for possible future use. pub fn is_unused_keyword(id: ast::Ident) -> bool { - id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name() + let edition = || id.span.ctxt().outer().expn_info().map_or_else(|| hygiene::default_edition(), + |einfo| einfo.callee.edition); + id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name() || + id.name == keywords::Proc.name() && edition() == Edition::Edition2015 || + id.name == keywords::Async.name() && edition() == Edition::Edition2018 } /// Returns `true` if the token is either a special identifier or a keyword. -- cgit 1.4.1-3-g733a5 From c4352ff198e4725393f4f6fbadab7312b30b538c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 13 May 2018 16:14:43 +0300 Subject: Turn some functions from `token.rs` into methods on `Ident` --- src/librustc/hir/print.rs | 4 +-- src/librustc_passes/ast_validation.rs | 6 ++-- src/librustc_resolve/lib.rs | 3 +- src/librustc_resolve/resolve_imports.rs | 7 ++-- src/libsyntax/ast.rs | 3 +- src/libsyntax/parse/lexer/mod.rs | 2 +- src/libsyntax/parse/token.rs | 57 ++++----------------------------- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax_pos/lib.rs | 6 ++++ src/libsyntax_pos/symbol.rs | 57 ++++++++++++++++++++++++++++++++- 10 files changed, 80 insertions(+), 67 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 9cd9e0dce54..940a68e8ce5 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -13,7 +13,7 @@ pub use self::AnnNode::*; use rustc_target::spec::abi::Abi; use syntax::ast; use syntax::codemap::{CodeMap, Spanned}; -use syntax::parse::{token, ParseSess}; +use syntax::parse::ParseSess; use syntax::parse::lexer::comments; use syntax::print::pp::{self, Breaks}; use syntax::print::pp::Breaks::{Consistent, Inconsistent}; @@ -1559,7 +1559,7 @@ impl<'a> State<'a> { } pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { - if token::is_raw_guess(ast::Ident::with_empty_ctxt(name)) { + if name.to_ident().is_raw_guess() { self.s.word(&format!("r#{}", name))?; } else { self.s.word(&name.as_str())?; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 4789e2e50ca..4f239a0868e 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -21,7 +21,6 @@ use rustc::session::Session; use syntax::ast::*; use syntax::attr; use syntax::codemap::Spanned; -use syntax::parse::token; use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax_pos::Span; @@ -40,14 +39,13 @@ impl<'a> AstValidator<'a> { let valid_names = [keywords::UnderscoreLifetime.name(), keywords::StaticLifetime.name(), keywords::Invalid.name()]; - if !valid_names.contains(&ident.name) && - token::is_reserved_ident(ident.without_first_quote()) { + if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() { self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names"); } } fn check_label(&self, ident: Ident) { - if token::is_reserved_ident(ident.without_first_quote()) { + if ident.without_first_quote().is_reserved() { self.err_handler() .span_err(ident.span, &format!("invalid label name `{}`", ident.name)); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5a5f5ce2e38..e13e6bc6b74 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -58,7 +58,6 @@ use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path}; use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; use syntax::feature_gate::{feature_err, GateIssue}; -use syntax::parse::token; use syntax::ptr::P; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; @@ -3274,7 +3273,7 @@ impl<'a> Resolver<'a> { // `$crate::a::b` module = Some(self.resolve_crate_root(ident.span.ctxt(), true)); continue - } else if i == 1 && !token::is_path_segment_keyword(ident) { + } else if i == 1 && !ident.is_path_segment_keyword() { let prev_name = path[0].name; if prev_name == keywords::Extern.name() || prev_name == keywords::CrateRoot.name() && diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 09c421fba47..16d5d3fa043 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -27,7 +27,6 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet}; use syntax::ast::{Ident, Name, NodeId}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::hygiene::Mark; -use syntax::parse::token; use syntax::symbol::keywords; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; @@ -667,7 +666,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } else { Some(self.resolve_crate_root(source.span.ctxt().modern(), false)) } - } else if is_extern && !token::is_path_segment_keyword(source) { + } else if is_extern && !source.is_path_segment_keyword() { let crate_id = self.resolver.crate_loader.process_use_extern( source.name, @@ -715,8 +714,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } PathResult::Failed(span, msg, true) => { let (mut self_path, mut self_result) = (module_path.clone(), None); - let is_special = |ident| token::is_path_segment_keyword(ident) && - ident.name != keywords::CrateRoot.name(); + let is_special = |ident: Ident| ident.is_path_segment_keyword() && + ident.name != keywords::CrateRoot.name(); if !self_path.is_empty() && !is_special(self_path[0]) && !(self_path.len() > 1 && is_special(self_path[1])) { self_path[0].name = keywords::SelfValue.name(); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2b6635ec783..1817726d6a1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -107,8 +107,7 @@ impl Path { // or starts with something like `self`/`super`/`$crate`/etc. pub fn make_root(&self) -> Option { if let Some(ident) = self.segments.get(0).map(|seg| seg.ident) { - if ::parse::token::is_path_segment_keyword(ident) && - ident.name != keywords::Crate.name() { + if ident.is_path_segment_keyword() && ident.name != keywords::Crate.name() { return None; } } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 3e22598043a..7bef9e34d5a 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1149,7 +1149,7 @@ impl<'a> StringReader<'a> { return Ok(self.with_str_from(start, |string| { // FIXME: perform NFKC normalization here. (Issue #2253) let ident = self.mk_ident(string); - if is_raw_ident && (token::is_path_segment_keyword(ident) || + if is_raw_ident && (ident.is_path_segment_keyword() || ident.name == keywords::Underscore.name()) { self.fatal_span_(raw_start, self.pos, &format!("`r#{}` is not currently supported.", ident.name) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index cbafad253b8..5575614a4d4 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -15,14 +15,13 @@ pub use self::Lit::*; pub use self::Token::*; use ast::{self}; -use edition::Edition; use parse::ParseSess; use print::pprust; use ptr::P; use serialize::{Decodable, Decoder, Encodable, Encoder}; use symbol::keywords; use syntax::parse::parse_stream_from_source_str; -use syntax_pos::{self, hygiene, Span, FileName}; +use syntax_pos::{self, Span, FileName}; use tokenstream::{TokenStream, TokenTree}; use tokenstream; @@ -139,48 +138,6 @@ fn ident_can_begin_type(ident: ast::Ident, is_raw: bool) -> bool { ].contains(&ident.name) } -pub fn is_path_segment_keyword(id: ast::Ident) -> bool { - id.name == keywords::Super.name() || - id.name == keywords::SelfValue.name() || - id.name == keywords::SelfType.name() || - id.name == keywords::Extern.name() || - id.name == keywords::Crate.name() || - id.name == keywords::CrateRoot.name() || - id.name == keywords::DollarCrate.name() -} - -// We see this identifier in a normal identifier position, like variable name or a type. -// How was it written originally? Did it use the raw form? Let's try to guess. -pub fn is_raw_guess(ident: ast::Ident) -> bool { - ident.name != keywords::Invalid.name() && - is_reserved_ident(ident) && !is_path_segment_keyword(ident) -} - -// Returns true for reserved identifiers used internally for elided lifetimes, -// unnamed method parameters, crate root module, error recovery etc. -pub fn is_special_ident(id: ast::Ident) -> bool { - id.name <= keywords::Underscore.name() -} - -/// Returns `true` if the token is a keyword used in the language. -pub fn is_used_keyword(id: ast::Ident) -> bool { - id.name >= keywords::As.name() && id.name <= keywords::While.name() -} - -/// Returns `true` if the token is a keyword reserved for possible future use. -pub fn is_unused_keyword(id: ast::Ident) -> bool { - let edition = || id.span.ctxt().outer().expn_info().map_or_else(|| hygiene::default_edition(), - |einfo| einfo.callee.edition); - id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name() || - id.name == keywords::Proc.name() && edition() == Edition::Edition2015 || - id.name == keywords::Async.name() && edition() == Edition::Edition2018 -} - -/// Returns `true` if the token is either a special identifier or a keyword. -pub fn is_reserved_ident(id: ast::Ident) -> bool { - is_special_ident(id) || is_used_keyword(id) || is_unused_keyword(id) -} - #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug)] pub enum Token { /* Expression-operator symbols. */ @@ -256,7 +213,7 @@ impl Token { /// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary. pub fn from_ast_ident(ident: ast::Ident) -> Token { - Ident(ident, is_raw_guess(ident)) + Ident(ident, ident.is_raw_guess()) } /// Returns `true` if the token starts with '>'. @@ -436,7 +393,7 @@ impl Token { pub fn is_path_segment_keyword(&self) -> bool { match self.ident() { - Some((id, false)) => is_path_segment_keyword(id), + Some((id, false)) => id.is_path_segment_keyword(), _ => false, } } @@ -445,7 +402,7 @@ impl Token { // unnamed method parameters, crate root module, error recovery etc. pub fn is_special_ident(&self) -> bool { match self.ident() { - Some((id, false)) => is_special_ident(id), + Some((id, false)) => id.is_special(), _ => false, } } @@ -453,7 +410,7 @@ impl Token { /// Returns `true` if the token is a keyword used in the language. pub fn is_used_keyword(&self) -> bool { match self.ident() { - Some((id, false)) => is_used_keyword(id), + Some((id, false)) => id.is_used_keyword(), _ => false, } } @@ -461,7 +418,7 @@ impl Token { /// Returns `true` if the token is a keyword reserved for possible future use. pub fn is_unused_keyword(&self) -> bool { match self.ident() { - Some((id, false)) => is_unused_keyword(id), + Some((id, false)) => id.is_unused_keyword(), _ => false, } } @@ -469,7 +426,7 @@ impl Token { /// Returns `true` if the token is either a special identifier or a keyword. pub fn is_reserved_ident(&self) -> bool { match self.ident() { - Some((id, false)) => is_reserved_ident(id), + Some((id, false)) => id.is_reserved(), _ => false, } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a700799cde5..17f83a09c77 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2374,7 +2374,7 @@ impl<'a> State<'a> { } pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { - if token::is_raw_guess(ident) { + if ident.is_raw_guess() { self.s.word(&format!("r#{}", ident))?; } else { self.s.word(&ident.name.as_str())?; diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index d2e768dda3c..e2656e2236e 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -300,6 +300,12 @@ impl Span { self.ctxt().outer().expn_info().map(|i| i.call_site) } + /// Edition of the crate from which this span came. + pub fn edition(self) -> edition::Edition { + self.ctxt().outer().expn_info().map_or_else(|| hygiene::default_edition(), + |einfo| einfo.callee.edition) + } + /// Return the source callee. /// /// Returns None if the supplied span has no expansion trace, diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index b3687d2962c..35c94457e6e 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -12,6 +12,7 @@ //! allows bidirectional lookup; i.e. given a value, one can easily find the //! type, and vice versa. +use edition::Edition; use hygiene::SyntaxContext; use {Span, DUMMY_SP, GLOBALS}; @@ -318,7 +319,7 @@ 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_special_ident`, `is_used_keyword`/`is_unused_keyword`, +// After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`, // this should be rarely necessary though if the keywords are kept in alphabetic order. declare_keywords! { // Special reserved identifiers used internally for elided lifetimes, @@ -399,6 +400,60 @@ declare_keywords! { (63, Union, "union") } +impl Symbol { + fn is_unused_keyword_2015(self) -> bool { + self == keywords::Proc.name() + } + + fn is_unused_keyword_2018(self) -> bool { + self == keywords::Async.name() + } +} + +impl Ident { + // Returns true for reserved identifiers used internally for elided lifetimes, + // unnamed method parameters, crate root module, error recovery etc. + pub fn is_special(self) -> bool { + self.name <= keywords::Underscore.name() + } + + /// Returns `true` if the token is a keyword used in the language. + pub fn is_used_keyword(self) -> bool { + self.name >= keywords::As.name() && self.name <= keywords::While.name() + } + + /// Returns `true` if the token is a keyword reserved for possible future use. + pub fn is_unused_keyword(self) -> bool { + // Note: `span.edition()` is relatively expensive, don't call it unless necessary. + self.name >= keywords::Abstract.name() && self.name <= keywords::Yield.name() || + self.name.is_unused_keyword_2015() && self.span.edition() == Edition::Edition2015 || + self.name.is_unused_keyword_2018() && self.span.edition() == Edition::Edition2018 + } + + /// Returns `true` if the token is either a special identifier or a keyword. + pub fn is_reserved(self) -> bool { + self.is_special() || self.is_used_keyword() || self.is_unused_keyword() + } + + /// A keyword or reserved identifier that can be used as a path segment. + pub fn is_path_segment_keyword(self) -> bool { + self.name == keywords::Super.name() || + self.name == keywords::SelfValue.name() || + self.name == keywords::SelfType.name() || + self.name == keywords::Extern.name() || + self.name == keywords::Crate.name() || + self.name == keywords::CrateRoot.name() || + self.name == keywords::DollarCrate.name() + } + + // We see this identifier in a normal identifier position, like variable name or a type. + // How was it written originally? Did it use the raw form? Let's try to guess. + pub fn is_raw_guess(self) -> bool { + self.name != keywords::Invalid.name() && + self.is_reserved() && !self.is_path_segment_keyword() + } +} + // If an interner exists, return it. Otherwise, prepare a fresh one. #[inline] fn with_interner T>(f: F) -> T { -- cgit 1.4.1-3-g733a5