diff options
| author | bors <bors@rust-lang.org> | 2016-04-28 03:38:04 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2016-04-28 03:38:04 -0700 |
| commit | 0f9ba992910b724bd198a196b5e408785911fdfc (patch) | |
| tree | c74f1c5fd4ec59d0f9693d379877884cfeda8589 /src | |
| parent | 009a64916e7f51df7e4e4e1df603eb4be1c7a6d8 (diff) | |
| parent | 78a8127ff0138dbda870e78d68809f455eec5f20 (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')
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() {} |
