diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a38666a0e94ad..664cb80593f04 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4630,7 +4630,7 @@ impl<'a> Parser<'a> { let mut attrs = self.parse_outer_attributes()?; let lo = self.span.lo; - let vis = self.parse_visibility(true)?; + let vis = self.parse_visibility()?; let defaultness = self.parse_defaultness()?; let (name, node) = if self.eat_keyword(keywords::Type) { let name = self.parse_ident()?; @@ -4963,7 +4963,7 @@ impl<'a> Parser<'a> { |p| { let attrs = p.parse_outer_attributes()?; let lo = p.span.lo; - let mut vis = p.parse_visibility(false)?; + let mut vis = p.parse_visibility()?; let ty_is_interpolated = p.token.is_interpolated() || p.look_ahead(1, |t| t.is_interpolated()); let mut ty = p.parse_ty()?; @@ -5020,38 +5020,46 @@ impl<'a> Parser<'a> { fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> { let attrs = self.parse_outer_attributes()?; let lo = self.span.lo; - let vis = self.parse_visibility(true)?; + let vis = self.parse_visibility()?; self.parse_single_struct_field(lo, vis, attrs) } - // 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.prev_span; - this.expect(&token::CloseDelim(token::Paren))?; - Ok(Visibility::Crate(span)) - }; - + // Parse `pub`, `pub(crate)` and `pub(in path)` plus shortcuts + // `pub(self)` for `pub(in self)` and `pub(super)` for `pub(in super)`. + fn parse_visibility(&mut self) -> PResult<'a, Visibility> { if !self.eat_keyword(keywords::Pub) { - Ok(Visibility::Inherited) - } 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) { - pub_crate(self) - } else { - let path = self.parse_path(PathStyle::Mod)?.default_to_global(); - self.expect(&token::CloseDelim(token::Paren))?; - Ok(Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID }) - } + return Ok(Visibility::Inherited) + } + + if self.check(&token::OpenDelim(token::Paren)) { + if self.look_ahead(1, |t| t.is_keyword(keywords::Crate)) { + // `pub(crate)` + self.bump(); // `(` + self.bump(); // `crate` + let vis = Visibility::Crate(self.prev_span); + self.expect(&token::CloseDelim(token::Paren))?; // `)` + return Ok(vis) + } else if self.look_ahead(1, |t| t.is_keyword(keywords::In)) { + // `pub(in path)` + self.bump(); // `(` + self.bump(); // `in` + let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `path` + let vis = Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID }; + self.expect(&token::CloseDelim(token::Paren))?; // `)` + return Ok(vis) + } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) && + self.look_ahead(1, |t| t.is_keyword(keywords::Super) || + t.is_keyword(keywords::SelfValue)) { + // `pub(self)` or `pub(super)` + self.bump(); // `(` + let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `super`/`self` + let vis = Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID }; + self.expect(&token::CloseDelim(token::Paren))?; // `)` + return Ok(vis) + } + } + + Ok(Visibility::Public) } /// Parse defaultness: DEFAULT or nothing @@ -5526,7 +5534,7 @@ impl<'a> Parser<'a> { let lo = self.span.lo; - let visibility = self.parse_visibility(true)?; + let visibility = self.parse_visibility()?; if self.eat_keyword(keywords::Use) { // USE ITEM @@ -5801,7 +5809,7 @@ impl<'a> Parser<'a> { fn parse_foreign_item(&mut self) -> PResult<'a, Option> { let attrs = self.parse_outer_attributes()?; let lo = self.span.lo; - let visibility = self.parse_visibility(true)?; + let visibility = self.parse_visibility()?; if self.check_keyword(keywords::Static) { // FOREIGN STATIC ITEM diff --git a/src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs b/src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs index 9dc4cf1252ec3..6f458da9b527b 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs @@ -55,7 +55,7 @@ mod m { #[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY pub(crate) b_crate: i32, #[unstable(feature = "unstable_declared", issue = "38412")] // SILLY - pub(m) c_mod: i32, + pub(in m) c_mod: i32, #[stable(feature = "unit_test", since = "0.0.0")] // SILLY d_priv: i32 } @@ -71,7 +71,7 @@ mod m { pub i32, pub(crate) i32, - pub(m) i32, + pub(in m) i32, i32); impl Record { @@ -124,7 +124,7 @@ mod m { #[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY pub(crate) fn pub_crate(&self) -> i32 { self.d_priv } #[unstable(feature = "unstable_declared", issue = "38412")] // SILLY - pub(m) fn pub_mod(&self) -> i32 { self.d_priv } + pub(in m) fn pub_mod(&self) -> i32 { self.d_priv } #[stable(feature = "unit_test", since = "0.0.0")] // SILLY fn private(&self) -> i32 { self.d_priv } } @@ -138,7 +138,7 @@ mod m { pub fn stable(&self) -> i32 { self.0 } pub(crate) fn pub_crate(&self) -> i32 { self.0 } - pub(m) fn pub_mod(&self) -> i32 { self.0 } + pub(in m) fn pub_mod(&self) -> i32 { self.0 } fn private(&self) -> i32 { self.0 } } } diff --git a/src/test/compile-fail/privacy/restricted/lookup-ignores-private.rs b/src/test/compile-fail/privacy/restricted/lookup-ignores-private.rs index 4e2a69cb79e19..2d4b5545544c6 100644 --- a/src/test/compile-fail/privacy/restricted/lookup-ignores-private.rs +++ b/src/test/compile-fail/privacy/restricted/lookup-ignores-private.rs @@ -16,10 +16,10 @@ mod foo { mod bar { #[derive(Default)] pub struct S { - pub(foo) x: i32, + pub(in foo) x: i32, } impl S { - pub(foo) fn f(&self) -> i32 { 0 } + pub(in foo) fn f(&self) -> i32 { 0 } } pub struct S2 { diff --git a/src/test/compile-fail/privacy/restricted/struct-literal-field.rs b/src/test/compile-fail/privacy/restricted/struct-literal-field.rs index e254e005656c1..53786d45c73ee 100644 --- a/src/test/compile-fail/privacy/restricted/struct-literal-field.rs +++ b/src/test/compile-fail/privacy/restricted/struct-literal-field.rs @@ -15,7 +15,7 @@ mod foo { pub mod bar { pub struct S { - pub(foo) x: i32, + pub(in foo) x: i32, } } diff --git a/src/test/compile-fail/privacy/restricted/test.rs b/src/test/compile-fail/privacy/restricted/test.rs index 01e2c6cd7e828..d55ee8221cd73 100644 --- a/src/test/compile-fail/privacy/restricted/test.rs +++ b/src/test/compile-fail/privacy/restricted/test.rs @@ -57,6 +57,6 @@ fn main() { } mod pathological { - pub(bad::path) mod m1 {} //~ ERROR failed to resolve. Maybe a missing `extern crate bad;`? - pub(foo) mod m2 {} //~ ERROR visibilities can only be restricted to ancestor modules + pub(in bad::path) mod m1 {} //~ ERROR failed to resolve. Maybe a missing `extern crate bad;`? + pub(in foo) mod m2 {} //~ ERROR visibilities can only be restricted to ancestor modules } diff --git a/src/test/compile-fail/privacy/restricted/ty-params.rs b/src/test/compile-fail/privacy/restricted/ty-params.rs index da7086cf554c3..cd0edc8fe7c44 100644 --- a/src/test/compile-fail/privacy/restricted/ty-params.rs +++ b/src/test/compile-fail/privacy/restricted/ty-params.rs @@ -11,16 +11,11 @@ #![feature(pub_restricted)] macro_rules! m { - ($p: path) => (pub($p) struct Z;) + ($p: path) => (pub(in $p) struct Z;) } struct S(T); m!{ S } //~ ERROR type or lifetime parameters in visibility path //~^ ERROR expected module, found struct `S` -mod foo { - struct S(pub(foo) ()); //~ ERROR type or lifetime parameters in visibility path - //~^ ERROR cannot find type `T` in this scope -} - fn main() {} diff --git a/src/test/compile-fail/resolve-bad-visibility.rs b/src/test/compile-fail/resolve-bad-visibility.rs index 6b5cd4dce265a..20878a91ede99 100644 --- a/src/test/compile-fail/resolve-bad-visibility.rs +++ b/src/test/compile-fail/resolve-bad-visibility.rs @@ -13,11 +13,11 @@ enum E {} trait Tr {} -pub(E) struct S; //~ ERROR expected module, found enum `E` -pub(Tr) struct Z; //~ ERROR expected module, found trait `Tr` -pub(std::vec) struct F; //~ ERROR visibilities can only be restricted to ancestor modules -pub(nonexistent) struct G; //~ ERROR cannot find module `nonexistent` in the crate root -pub(too_soon) struct H; //~ ERROR cannot find module `too_soon` in the crate root +pub(in E) struct S; //~ ERROR expected module, found enum `E` +pub(in Tr) struct Z; //~ ERROR expected module, found trait `Tr` +pub(in std::vec) struct F; //~ ERROR visibilities can only be restricted to ancestor modules +pub(in nonexistent) struct G; //~ ERROR cannot find module `nonexistent` in the crate root +pub(in too_soon) struct H; //~ ERROR cannot find module `too_soon` in the crate root // Visibilities are resolved eagerly without waiting for modules becoming fully populated. // Visibilities can only use ancestor modules legally which are always available in time, diff --git a/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs b/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs index f190f5dd0534d..383224b2f9273 100644 --- a/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs +++ b/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs @@ -14,7 +14,7 @@ pub mod m { pub struct S(u8); pub mod n { - pub(m) struct Z(pub(m::n) u8); + pub(in m) struct Z(pub(in m::n) u8); } } diff --git a/src/test/ui/resolve/privacy-struct-ctor.rs b/src/test/ui/resolve/privacy-struct-ctor.rs index 3d0c76c740ad6..68bd74719f55c 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.rs +++ b/src/test/ui/resolve/privacy-struct-ctor.rs @@ -18,7 +18,7 @@ mod m { pub struct S(u8); pub mod n { - pub(m) struct Z(pub(m::n) u8); + pub(in m) struct Z(pub(in m::n) u8); } use m::n::Z; // OK, only the type is imported