about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-04-28 03:38:04 -0700
committerbors <bors@rust-lang.org>2016-04-28 03:38:04 -0700
commit0f9ba992910b724bd198a196b5e408785911fdfc (patch)
treec74f1c5fd4ec59d0f9693d379877884cfeda8589 /src
parent009a64916e7f51df7e4e4e1df603eb4be1c7a6d8 (diff)
parent78a8127ff0138dbda870e78d68809f455eec5f20 (diff)
Auto merge of #33161 - jseyfried:parse_tuple_struct_field_vis, r=nikomatsakis
Parse `pub(restricted)` visibilities on tuple struct fields

Parse `pub(restricted)` on tuple struct fields (cc #32409).

r? @nikomatsakis
Diffstat (limited to 'src')
-rw-r--r--src/libsyntax/parse/parser.rs45
-rw-r--r--src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs18
-rw-r--r--src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs24
-rw-r--r--src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs24
-rw-r--r--src/test/compile-fail/privacy/restricted/ty-params.rs4
5 files changed, 108 insertions, 7 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 8722fe9d79d..671a11b57de 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5218,8 +5218,25 @@ impl<'a> Parser<'a> {
             |p| {
                 let attrs = p.parse_outer_attributes()?;
                 let lo = p.span.lo;
-                let vis = p.parse_visibility(false)?;
-                let ty = p.parse_ty_sum()?;
+                let mut vis = p.parse_visibility(false)?;
+                let ty_is_interpolated =
+                    p.token.is_interpolated() || p.look_ahead(1, |t| t.is_interpolated());
+                let mut ty = p.parse_ty_sum()?;
+
+                // Handle `pub(path) type`, in which `vis` will be `pub` and `ty` will be `(path)`.
+                if vis == Visibility::Public && !ty_is_interpolated &&
+                   p.token != token::Comma && p.token != token::CloseDelim(token::Paren) {
+                    ty = if let TyKind::Paren(ref path_ty) = ty.node {
+                        if let TyKind::Path(None, ref path) = path_ty.node {
+                            vis = Visibility::Restricted { path: P(path.clone()), id: path_ty.id };
+                            Some(p.parse_ty_sum()?)
+                        } else {
+                            None
+                        }
+                    } else {
+                        None
+                    }.unwrap_or(ty);
+                }
                 Ok(StructField {
                     span: mk_sp(lo, p.span.hi),
                     vis: vis,
@@ -5263,15 +5280,29 @@ impl<'a> Parser<'a> {
         self.parse_single_struct_field(vis, attrs)
     }
 
-    fn parse_visibility(&mut self, allow_restricted: bool) -> PResult<'a, Visibility> {
+    // If `allow_path` is false, just parse the `pub` in `pub(path)` (but still parse `pub(crate)`)
+    fn parse_visibility(&mut self, allow_path: bool) -> PResult<'a, Visibility> {
+        let pub_crate = |this: &mut Self| {
+            let span = this.last_span;
+            this.expect(&token::CloseDelim(token::Paren))?;
+            Ok(Visibility::Crate(span))
+        };
+
         if !self.eat_keyword(keywords::Pub) {
             Ok(Visibility::Inherited)
-        } else if !allow_restricted || !self.eat(&token::OpenDelim(token::Paren)) {
+        } else if !allow_path {
+            // Look ahead to avoid eating the `(` in `pub(path)` while still parsing `pub(crate)`
+            if self.token == token::OpenDelim(token::Paren) &&
+               self.look_ahead(1, |t| t.is_keyword(keywords::Crate)) {
+                self.bump(); self.bump();
+                pub_crate(self)
+            } else {
+                Ok(Visibility::Public)
+            }
+        } else if !self.eat(&token::OpenDelim(token::Paren)) {
             Ok(Visibility::Public)
         } else if self.eat_keyword(keywords::Crate) {
-            let span = self.last_span;
-            self.expect(&token::CloseDelim(token::Paren))?;
-            Ok(Visibility::Crate(span))
+            pub_crate(self)
         } else {
             let path = self.parse_path(PathStyle::Mod)?;
             self.expect(&token::CloseDelim(token::Paren))?;
diff --git a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs
new file mode 100644
index 00000000000..9cc53386d46
--- /dev/null
+++ b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs
@@ -0,0 +1,18 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(pub_restricted, type_macros)]
+
+mod foo {
+    type T = ();
+    struct S1(pub(foo) (), pub(T), pub(crate) (), pub(((), T)));
+    struct S2(pub((foo)) ()); //~ ERROR expected one of `+` or `,`, found `(`
+                              //~| ERROR expected one of `+`, `;`, or `where`, found `(`
+}
diff --git a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs
new file mode 100644
index 00000000000..01466c6a85a
--- /dev/null
+++ b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs
@@ -0,0 +1,24 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(pub_restricted, type_macros)]
+
+macro_rules! define_struct {
+    ($t:ty) => {
+        struct S1(pub $t);
+        struct S2(pub (foo) ());
+        struct S3(pub $t ()); //~ ERROR expected one of `+` or `,`, found `(`
+                              //~| ERROR expected one of `+`, `;`, or `where`, found `(`
+    }
+}
+
+mod foo {
+    define_struct! { (foo) }
+}
diff --git a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs
new file mode 100644
index 00000000000..ef187a1daed
--- /dev/null
+++ b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs
@@ -0,0 +1,24 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(pub_restricted, type_macros)]
+
+macro_rules! define_struct {
+    ($t:ty) => {
+        struct S1(pub($t));
+        struct S2(pub (foo) ());
+        struct S3(pub($t) ()); //~ ERROR expected one of `+` or `,`, found `(`
+                               //~| ERROR expected one of `+`, `;`, or `where`, found `(`
+    }
+}
+
+mod foo {
+    define_struct! { foo }
+}
diff --git a/src/test/compile-fail/privacy/restricted/ty-params.rs b/src/test/compile-fail/privacy/restricted/ty-params.rs
index 04d8e983304..ab423620d68 100644
--- a/src/test/compile-fail/privacy/restricted/ty-params.rs
+++ b/src/test/compile-fail/privacy/restricted/ty-params.rs
@@ -17,4 +17,8 @@ macro_rules! m {
 struct S<T>(T);
 m!{ S<u8> } //~ ERROR type or lifetime parameters in visibility path
 
+mod foo {
+    struct S(pub(foo<T>) ()); //~ ERROR type or lifetime parameters in visibility path
+}
+
 fn main() {}