about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-01-01 17:42:32 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-01-03 18:09:20 +0300
commit32db83b16e06cb5cca72d0e6a648a8008eda0fac (patch)
tree28ad66a5b4c14a728cbdb3d4665458ffd5fbe4b4 /src/libsyntax
parentb107f720e5422bff4fa0671e54ff5458f682f603 (diff)
downloadrust-32db83b16e06cb5cca72d0e6a648a8008eda0fac.tar.gz
rust-32db83b16e06cb5cca72d0e6a648a8008eda0fac.zip
Support `extern` in paths
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/feature_gate.rs6
-rw-r--r--src/libsyntax/parse/parser.rs15
-rw-r--r--src/libsyntax/parse/token.rs1
3 files changed, 18 insertions, 4 deletions
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::Attribute>, 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,