about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-01-07 00:51:42 +0000
committerbors <bors@rust-lang.org>2018-01-07 00:51:42 +0000
commita704583d43dda19c2542845d8efd61bd4e1d82f1 (patch)
tree7f934100750e46fe9662f968413c5a99afd181a6 /src/libsyntax/parse/parser.rs
parent6828cf90146c7fefc4ba4f16dffe75f763f2d910 (diff)
parentef2b131144bc0d3d7814c9967e47a8d4e834caa5 (diff)
downloadrust-a704583d43dda19c2542845d8efd61bd4e1d82f1.tar.gz
rust-a704583d43dda19c2542845d8efd61bd4e1d82f1.zip
Auto merge of #47156 - petrochenkov:extpath, r=nikomatsakis
Support `extern` in paths

Implement the primary alternative to https://github.com/rust-lang/rust/pull/46613 + https://github.com/rust-lang/rust/pull/45771, achieving the same effect without requiring changes to other imports.
Both need to be experimentally evaluated before making further progress.

The PR also adds docs for all these related features into the unstable book.

cc https://github.com/rust-lang/rust/issues/44660
r? @nikomatsakis
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs15
1 files changed, 11 insertions, 4 deletions
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)?));
             }