From 32db83b16e06cb5cca72d0e6a648a8008eda0fac Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 1 Jan 2018 17:42:32 +0300 Subject: Support `extern` in paths --- src/libsyntax/feature_gate.rs | 6 ++++++ src/libsyntax/parse/parser.rs | 15 +++++++++++---- src/libsyntax/parse/token.rs | 1 + 3 files changed, 18 insertions(+), 4 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e5ef9393e7b..08eec0f9117 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -450,6 +450,9 @@ declare_features! ( // Allows use of the :lifetime macro fragment specifier (active, macro_lifetime_matcher, "1.24.0", Some(46895)), + + // `extern` in paths + (active, extern_in_paths, "1.23.0", Some(44660)), ); declare_features! ( @@ -1790,6 +1793,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if segment.identifier.name == keywords::Crate.name() { gate_feature_post!(&self, crate_in_paths, segment.span, "`crate` in paths is experimental"); + } else if segment.identifier.name == keywords::Extern.name() { + gate_feature_post!(&self, extern_in_paths, segment.span, + "`extern` in paths is experimental"); } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 812e3c4967a..e7c648d5e37 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1387,7 +1387,7 @@ impl<'a> Parser<'a> { None }; (ident, TraitItemKind::Const(ty, default), ast::Generics::default()) - } else if self.token.is_path_start() { + } else if self.token.is_path_start() && !self.is_extern_non_path() { // trait item macro. // code copied from parse_macro_use_or_failure... abstraction! let prev_span = self.prev_span; @@ -4037,6 +4037,10 @@ impl<'a> Parser<'a> { self.token.is_keyword(keywords::Crate) && self.look_ahead(1, |t| t != &token::ModSep) } + fn is_extern_non_path(&self) -> bool { + self.token.is_keyword(keywords::Extern) && self.look_ahead(1, |t| t != &token::ModSep) + } + fn eat_auto_trait(&mut self) -> bool { if self.token.is_keyword(keywords::Auto) && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) @@ -4152,10 +4156,12 @@ impl<'a> Parser<'a> { // like a path (1 token), but it fact not a path. // `union::b::c` - path, `union U { ... }` - not a path. // `crate::b::c` - path, `crate struct S;` - not a path. + // `extern::b::c` - path, `extern crate c;` - not a path. } else if self.token.is_path_start() && !self.token.is_qpath_start() && !self.is_union_item() && - !self.is_crate_vis() { + !self.is_crate_vis() && + !self.is_extern_non_path() { let pth = self.parse_path(PathStyle::Expr)?; if !self.eat(&token::Not) { @@ -5236,7 +5242,7 @@ impl<'a> Parser<'a> { -> PResult<'a, (Ident, Vec, ast::Generics, ast::ImplItemKind)> { // code copied from parse_macro_use_or_failure... abstraction! - if self.token.is_path_start() { + if self.token.is_path_start() && !self.is_extern_non_path() { // Method macro. let prev_span = self.prev_span; @@ -6238,7 +6244,8 @@ impl<'a> Parser<'a> { return Ok(Some(item)); } - if self.eat_keyword(keywords::Extern) { + if self.check_keyword(keywords::Extern) && self.is_extern_non_path() { + self.bump(); // `extern` if self.eat_keyword(keywords::Crate) { return Ok(Some(self.parse_item_extern_crate(lo, visibility, attrs)?)); } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index bd4f7f9853d..2be93c07d5a 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -359,6 +359,7 @@ impl Token { Some(id) => 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::DollarCrate.name(), None => false, -- cgit 1.4.1-3-g733a5