summaryrefslogtreecommitdiffstats
path: root/tests/ui/pub
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /tests/ui/pub
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/pub')
-rw-r--r--tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs28
-rw-r--r--tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr30
-rw-r--r--tests/ui/pub/pub-ident-fn-2.fixed10
-rw-r--r--tests/ui/pub/pub-ident-fn-2.rs10
-rw-r--r--tests/ui/pub/pub-ident-fn-2.stderr13
-rw-r--r--tests/ui/pub/pub-ident-fn-3.rs8
-rw-r--r--tests/ui/pub/pub-ident-fn-3.stderr8
-rw-r--r--tests/ui/pub/pub-ident-fn-or-struct-2.rs4
-rw-r--r--tests/ui/pub/pub-ident-fn-or-struct-2.stderr8
-rw-r--r--tests/ui/pub/pub-ident-fn-or-struct.rs4
-rw-r--r--tests/ui/pub/pub-ident-fn-or-struct.stderr8
-rw-r--r--tests/ui/pub/pub-ident-fn-with-lifetime-2.rs6
-rw-r--r--tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr13
-rw-r--r--tests/ui/pub/pub-ident-fn-with-lifetime.fixed8
-rw-r--r--tests/ui/pub/pub-ident-fn-with-lifetime.rs8
-rw-r--r--tests/ui/pub/pub-ident-fn-with-lifetime.stderr13
-rw-r--r--tests/ui/pub/pub-ident-fn.fixed8
-rw-r--r--tests/ui/pub/pub-ident-fn.rs8
-rw-r--r--tests/ui/pub/pub-ident-fn.stderr13
-rw-r--r--tests/ui/pub/pub-ident-struct-with-lifetime.rs4
-rw-r--r--tests/ui/pub/pub-ident-struct-with-lifetime.stderr13
-rw-r--r--tests/ui/pub/pub-ident-struct.fixed6
-rw-r--r--tests/ui/pub/pub-ident-struct.rs6
-rw-r--r--tests/ui/pub/pub-ident-struct.stderr13
-rw-r--r--tests/ui/pub/pub-ident-with-lifetime-incomplete.rs5
-rw-r--r--tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr8
-rw-r--r--tests/ui/pub/pub-reexport-priv-extern-crate.rs20
-rw-r--r--tests/ui/pub/pub-reexport-priv-extern-crate.stderr37
-rw-r--r--tests/ui/pub/pub-restricted-error-fn.rs2
-rw-r--r--tests/ui/pub/pub-restricted-error-fn.stderr16
-rw-r--r--tests/ui/pub/pub-restricted-error.rs7
-rw-r--r--tests/ui/pub/pub-restricted-error.stderr10
-rw-r--r--tests/ui/pub/pub-restricted-non-path.rs5
-rw-r--r--tests/ui/pub/pub-restricted-non-path.stderr8
-rw-r--r--tests/ui/pub/pub-restricted.rs31
-rw-r--r--tests/ui/pub/pub-restricted.stderr65
36 files changed, 464 insertions, 0 deletions
diff --git a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs
new file mode 100644
index 000000000..67f888c5e
--- /dev/null
+++ b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs
@@ -0,0 +1,28 @@
+#![allow(non_camel_case_types)] // genus is always capitalized
+
+pub(crate) struct Snail;
+//~^ NOTE `Snail` declared as private
+
+mod sea {
+ pub(super) struct Turtle;
+ //~^ NOTE `Turtle` declared as crate-private
+}
+
+struct Tortoise;
+//~^ NOTE `Tortoise` declared as private
+
+pub struct Shell<T> {
+ pub(crate) creature: T,
+}
+
+pub type Helix_pomatia = Shell<Snail>;
+//~^ ERROR private type `Snail` in public interface
+//~| NOTE can't leak private type
+pub type Dermochelys_coriacea = Shell<sea::Turtle>;
+//~^ ERROR crate-private type `Turtle` in public interface
+//~| NOTE can't leak crate-private type
+pub type Testudo_graeca = Shell<Tortoise>;
+//~^ ERROR private type `Tortoise` in public interface
+//~| NOTE can't leak private type
+
+fn main() {}
diff --git a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr
new file mode 100644
index 000000000..39d4f5ac8
--- /dev/null
+++ b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr
@@ -0,0 +1,30 @@
+error[E0446]: private type `Snail` in public interface
+ --> $DIR/issue-33174-restricted-type-in-public-interface.rs:18:1
+ |
+LL | pub(crate) struct Snail;
+ | ----------------------- `Snail` declared as private
+...
+LL | pub type Helix_pomatia = Shell<Snail>;
+ | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: crate-private type `Turtle` in public interface
+ --> $DIR/issue-33174-restricted-type-in-public-interface.rs:21:1
+ |
+LL | pub(super) struct Turtle;
+ | ------------------------ `Turtle` declared as crate-private
+...
+LL | pub type Dermochelys_coriacea = Shell<sea::Turtle>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak crate-private type
+
+error[E0446]: private type `Tortoise` in public interface
+ --> $DIR/issue-33174-restricted-type-in-public-interface.rs:24:1
+ |
+LL | struct Tortoise;
+ | --------------- `Tortoise` declared as private
+...
+LL | pub type Testudo_graeca = Shell<Tortoise>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/tests/ui/pub/pub-ident-fn-2.fixed b/tests/ui/pub/pub-ident-fn-2.fixed
new file mode 100644
index 000000000..afd75a41f
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-2.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+
+pub fn foo(_s: usize) { bar() }
+//~^ ERROR missing `fn` for function definition
+
+fn bar() {}
+
+fn main() {
+ foo(2);
+}
diff --git a/tests/ui/pub/pub-ident-fn-2.rs b/tests/ui/pub/pub-ident-fn-2.rs
new file mode 100644
index 000000000..e7b86a909
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-2.rs
@@ -0,0 +1,10 @@
+// run-rustfix
+
+pub foo(_s: usize) { bar() }
+//~^ ERROR missing `fn` for function definition
+
+fn bar() {}
+
+fn main() {
+ foo(2);
+}
diff --git a/tests/ui/pub/pub-ident-fn-2.stderr b/tests/ui/pub/pub-ident-fn-2.stderr
new file mode 100644
index 000000000..b5b667b41
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-2.stderr
@@ -0,0 +1,13 @@
+error: missing `fn` for function definition
+ --> $DIR/pub-ident-fn-2.rs:3:4
+ |
+LL | pub foo(_s: usize) { bar() }
+ | ^
+ |
+help: add `fn` here to parse `foo` as a public function
+ |
+LL | pub fn foo(_s: usize) { bar() }
+ | ++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-ident-fn-3.rs b/tests/ui/pub/pub-ident-fn-3.rs
new file mode 100644
index 000000000..fdbea7cf4
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-3.rs
@@ -0,0 +1,8 @@
+// #60115
+
+mod foo {
+ pub bar();
+ //~^ ERROR missing `fn` or `struct` for function or struct definition
+}
+
+fn main() {}
diff --git a/tests/ui/pub/pub-ident-fn-3.stderr b/tests/ui/pub/pub-ident-fn-3.stderr
new file mode 100644
index 000000000..6d3d4e592
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-3.stderr
@@ -0,0 +1,8 @@
+error: missing `fn` or `struct` for function or struct definition
+ --> $DIR/pub-ident-fn-3.rs:4:8
+ |
+LL | pub bar();
+ | ---^--- help: if you meant to call a macro, try: `bar!`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-ident-fn-or-struct-2.rs b/tests/ui/pub/pub-ident-fn-or-struct-2.rs
new file mode 100644
index 000000000..8f67cdd29
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-or-struct-2.rs
@@ -0,0 +1,4 @@
+pub S();
+//~^ ERROR missing `fn` or `struct` for function or struct definition
+
+fn main() {}
diff --git a/tests/ui/pub/pub-ident-fn-or-struct-2.stderr b/tests/ui/pub/pub-ident-fn-or-struct-2.stderr
new file mode 100644
index 000000000..047e66b18
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-or-struct-2.stderr
@@ -0,0 +1,8 @@
+error: missing `fn` or `struct` for function or struct definition
+ --> $DIR/pub-ident-fn-or-struct-2.rs:1:4
+ |
+LL | pub S();
+ | ---^- help: if you meant to call a macro, try: `S!`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-ident-fn-or-struct.rs b/tests/ui/pub/pub-ident-fn-or-struct.rs
new file mode 100644
index 000000000..832831d29
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-or-struct.rs
@@ -0,0 +1,4 @@
+pub S (foo) bar
+//~^ ERROR missing `fn` or `struct` for function or struct definition
+
+fn main() {}
diff --git a/tests/ui/pub/pub-ident-fn-or-struct.stderr b/tests/ui/pub/pub-ident-fn-or-struct.stderr
new file mode 100644
index 000000000..c4a196eb2
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-or-struct.stderr
@@ -0,0 +1,8 @@
+error: missing `fn` or `struct` for function or struct definition
+ --> $DIR/pub-ident-fn-or-struct.rs:1:4
+ |
+LL | pub S (foo) bar
+ | ---^- help: if you meant to call a macro, try: `S!`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime-2.rs b/tests/ui/pub/pub-ident-fn-with-lifetime-2.rs
new file mode 100644
index 000000000..1ee8c84f1
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-with-lifetime-2.rs
@@ -0,0 +1,6 @@
+pub bar<'a>(&self, _s: &'a usize) -> bool { true }
+//~^ ERROR missing `fn` for method definition
+
+fn main() {
+ bar(2);
+}
diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr b/tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr
new file mode 100644
index 000000000..6a9aeaf4a
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr
@@ -0,0 +1,13 @@
+error: missing `fn` for method definition
+ --> $DIR/pub-ident-fn-with-lifetime-2.rs:1:4
+ |
+LL | pub bar<'a>(&self, _s: &'a usize) -> bool { true }
+ | ^^^
+ |
+help: add `fn` here to parse `bar` as a public method
+ |
+LL | pub fn bar<'a>(&self, _s: &'a usize) -> bool { true }
+ | ++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime.fixed b/tests/ui/pub/pub-ident-fn-with-lifetime.fixed
new file mode 100644
index 000000000..e510ace5f
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-with-lifetime.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+pub fn foo<'a>(_s: &'a usize) -> bool { true }
+//~^ ERROR missing `fn` for function definition
+
+fn main() {
+ foo(&2);
+}
diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime.rs b/tests/ui/pub/pub-ident-fn-with-lifetime.rs
new file mode 100644
index 000000000..63e6eca15
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-with-lifetime.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+pub foo<'a>(_s: &'a usize) -> bool { true }
+//~^ ERROR missing `fn` for function definition
+
+fn main() {
+ foo(&2);
+}
diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime.stderr b/tests/ui/pub/pub-ident-fn-with-lifetime.stderr
new file mode 100644
index 000000000..c1ca0136b
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn-with-lifetime.stderr
@@ -0,0 +1,13 @@
+error: missing `fn` for function definition
+ --> $DIR/pub-ident-fn-with-lifetime.rs:3:4
+ |
+LL | pub foo<'a>(_s: &'a usize) -> bool { true }
+ | ^^^
+ |
+help: add `fn` here to parse `foo` as a public function
+ |
+LL | pub fn foo<'a>(_s: &'a usize) -> bool { true }
+ | ++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-ident-fn.fixed b/tests/ui/pub/pub-ident-fn.fixed
new file mode 100644
index 000000000..65ed8c7b4
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+pub fn foo(_s: usize) -> bool { true }
+//~^ ERROR missing `fn` for function definition
+
+fn main() {
+ foo(2);
+}
diff --git a/tests/ui/pub/pub-ident-fn.rs b/tests/ui/pub/pub-ident-fn.rs
new file mode 100644
index 000000000..2fe4d34fb
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+pub foo(_s: usize) -> bool { true }
+//~^ ERROR missing `fn` for function definition
+
+fn main() {
+ foo(2);
+}
diff --git a/tests/ui/pub/pub-ident-fn.stderr b/tests/ui/pub/pub-ident-fn.stderr
new file mode 100644
index 000000000..cb94c48ad
--- /dev/null
+++ b/tests/ui/pub/pub-ident-fn.stderr
@@ -0,0 +1,13 @@
+error: missing `fn` for function definition
+ --> $DIR/pub-ident-fn.rs:3:4
+ |
+LL | pub foo(_s: usize) -> bool { true }
+ | ^^^
+ |
+help: add `fn` here to parse `foo` as a public function
+ |
+LL | pub fn foo(_s: usize) -> bool { true }
+ | ++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-ident-struct-with-lifetime.rs b/tests/ui/pub/pub-ident-struct-with-lifetime.rs
new file mode 100644
index 000000000..2feb02660
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct-with-lifetime.rs
@@ -0,0 +1,4 @@
+pub S<'a> {
+//~^ ERROR missing `struct` for struct definition
+}
+fn main() {}
diff --git a/tests/ui/pub/pub-ident-struct-with-lifetime.stderr b/tests/ui/pub/pub-ident-struct-with-lifetime.stderr
new file mode 100644
index 000000000..562b68e35
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct-with-lifetime.stderr
@@ -0,0 +1,13 @@
+error: missing `struct` for struct definition
+ --> $DIR/pub-ident-struct-with-lifetime.rs:1:4
+ |
+LL | pub S<'a> {
+ | ^
+ |
+help: add `struct` here to parse `S` as a public struct
+ |
+LL | pub struct S<'a> {
+ | ++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-ident-struct.fixed b/tests/ui/pub/pub-ident-struct.fixed
new file mode 100644
index 000000000..58cde8fd6
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+
+pub struct S {
+//~^ ERROR missing `struct` for struct definition
+}
+fn main() {}
diff --git a/tests/ui/pub/pub-ident-struct.rs b/tests/ui/pub/pub-ident-struct.rs
new file mode 100644
index 000000000..3930e556e
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct.rs
@@ -0,0 +1,6 @@
+// run-rustfix
+
+pub S {
+//~^ ERROR missing `struct` for struct definition
+}
+fn main() {}
diff --git a/tests/ui/pub/pub-ident-struct.stderr b/tests/ui/pub/pub-ident-struct.stderr
new file mode 100644
index 000000000..d3a378786
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct.stderr
@@ -0,0 +1,13 @@
+error: missing `struct` for struct definition
+ --> $DIR/pub-ident-struct.rs:3:4
+ |
+LL | pub S {
+ | ^
+ |
+help: add `struct` here to parse `S` as a public struct
+ |
+LL | pub struct S {
+ | ++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-ident-with-lifetime-incomplete.rs b/tests/ui/pub/pub-ident-with-lifetime-incomplete.rs
new file mode 100644
index 000000000..c86a9f2fd
--- /dev/null
+++ b/tests/ui/pub/pub-ident-with-lifetime-incomplete.rs
@@ -0,0 +1,5 @@
+fn main() {
+}
+
+pub foo<'a>
+//~^ ERROR missing `fn` or `struct` for function or struct definition
diff --git a/tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr b/tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr
new file mode 100644
index 000000000..0e0b12705
--- /dev/null
+++ b/tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr
@@ -0,0 +1,8 @@
+error: missing `fn` or `struct` for function or struct definition
+ --> $DIR/pub-ident-with-lifetime-incomplete.rs:4:4
+ |
+LL | pub foo<'a>
+ | ^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.rs b/tests/ui/pub/pub-reexport-priv-extern-crate.rs
new file mode 100644
index 000000000..dd5cd420f
--- /dev/null
+++ b/tests/ui/pub/pub-reexport-priv-extern-crate.rs
@@ -0,0 +1,20 @@
+extern crate core;
+pub use core as reexported_core; //~ ERROR `core` is private, and cannot be re-exported
+ //~^ WARN this was previously accepted
+
+mod foo1 {
+ extern crate core;
+}
+
+mod foo2 {
+ use foo1::core; //~ ERROR crate import `core` is private
+ pub mod bar {
+ extern crate core;
+ }
+}
+
+mod baz {
+ pub use foo2::bar::core; //~ ERROR crate import `core` is private
+}
+
+fn main() {}
diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
new file mode 100644
index 000000000..c7fadc6f9
--- /dev/null
+++ b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
@@ -0,0 +1,37 @@
+error[E0603]: crate import `core` is private
+ --> $DIR/pub-reexport-priv-extern-crate.rs:10:15
+ |
+LL | use foo1::core;
+ | ^^^^ private crate import
+ |
+note: the crate import `core` is defined here
+ --> $DIR/pub-reexport-priv-extern-crate.rs:6:5
+ |
+LL | extern crate core;
+ | ^^^^^^^^^^^^^^^^^^
+
+error[E0603]: crate import `core` is private
+ --> $DIR/pub-reexport-priv-extern-crate.rs:17:24
+ |
+LL | pub use foo2::bar::core;
+ | ^^^^ private crate import
+ |
+note: the crate import `core` is defined here
+ --> $DIR/pub-reexport-priv-extern-crate.rs:12:9
+ |
+LL | extern crate core;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: extern crate `core` is private, and cannot be re-exported (error E0365), consider declaring with `pub`
+ --> $DIR/pub-reexport-priv-extern-crate.rs:2:9
+ |
+LL | pub use core as reexported_core;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+ = note: `#[deny(pub_use_of_private_extern_crate)]` on by default
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/tests/ui/pub/pub-restricted-error-fn.rs b/tests/ui/pub/pub-restricted-error-fn.rs
new file mode 100644
index 000000000..fc1aeae2b
--- /dev/null
+++ b/tests/ui/pub/pub-restricted-error-fn.rs
@@ -0,0 +1,2 @@
+pub(crate) () fn foo() {} //~ ERROR visibility `pub(crate)` is not followed by an item
+//~^ ERROR expected item, found `(`
diff --git a/tests/ui/pub/pub-restricted-error-fn.stderr b/tests/ui/pub/pub-restricted-error-fn.stderr
new file mode 100644
index 000000000..0511a821a
--- /dev/null
+++ b/tests/ui/pub/pub-restricted-error-fn.stderr
@@ -0,0 +1,16 @@
+error: visibility `pub(crate)` is not followed by an item
+ --> $DIR/pub-restricted-error-fn.rs:1:1
+ |
+LL | pub(crate) () fn foo() {}
+ | ^^^^^^^^^^ the visibility
+ |
+ = help: you likely meant to define an item, e.g., `pub(crate) fn foo() {}`
+
+error: expected item, found `(`
+ --> $DIR/pub-restricted-error-fn.rs:1:12
+ |
+LL | pub(crate) () fn foo() {}
+ | ^ expected item
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/pub/pub-restricted-error.rs b/tests/ui/pub/pub-restricted-error.rs
new file mode 100644
index 000000000..60fce3f51
--- /dev/null
+++ b/tests/ui/pub/pub-restricted-error.rs
@@ -0,0 +1,7 @@
+struct Bar(pub(()));
+
+struct Foo {
+ pub(crate) () foo: usize, //~ ERROR expected identifier
+}
+
+fn main() {}
diff --git a/tests/ui/pub/pub-restricted-error.stderr b/tests/ui/pub/pub-restricted-error.stderr
new file mode 100644
index 000000000..b47328f34
--- /dev/null
+++ b/tests/ui/pub/pub-restricted-error.stderr
@@ -0,0 +1,10 @@
+error: expected identifier, found `(`
+ --> $DIR/pub-restricted-error.rs:4:16
+ |
+LL | struct Foo {
+ | --- while parsing this struct
+LL | pub(crate) () foo: usize,
+ | ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-restricted-non-path.rs b/tests/ui/pub/pub-restricted-non-path.rs
new file mode 100644
index 000000000..bdad18dbe
--- /dev/null
+++ b/tests/ui/pub/pub-restricted-non-path.rs
@@ -0,0 +1,5 @@
+#![feature(pub_restricted)]
+
+pub (.) fn afn() {} //~ ERROR expected identifier
+
+fn main() {}
diff --git a/tests/ui/pub/pub-restricted-non-path.stderr b/tests/ui/pub/pub-restricted-non-path.stderr
new file mode 100644
index 000000000..e0ea50621
--- /dev/null
+++ b/tests/ui/pub/pub-restricted-non-path.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `.`
+ --> $DIR/pub-restricted-non-path.rs:3:6
+ |
+LL | pub (.) fn afn() {}
+ | ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-restricted.rs b/tests/ui/pub/pub-restricted.rs
new file mode 100644
index 000000000..bcd21082f
--- /dev/null
+++ b/tests/ui/pub/pub-restricted.rs
@@ -0,0 +1,31 @@
+mod a {}
+
+pub (a) fn afn() {} //~ incorrect visibility restriction
+pub (b) fn bfn() {} //~ incorrect visibility restriction
+pub (crate::a) fn cfn() {} //~ incorrect visibility restriction
+
+pub fn privfn() {}
+mod x {
+ mod y {
+ pub (in x) fn foo() {}
+ pub (super) fn bar() {}
+ pub (crate) fn qux() {}
+ }
+}
+
+mod y {
+ struct Foo {
+ pub (crate) c: usize,
+ pub (super) s: usize,
+ valid_private: usize,
+ pub (in y) valid_in_x: usize,
+ pub (a) invalid: usize, //~ incorrect visibility restriction
+ pub (in x) non_parent_invalid: usize, //~ ERROR visibilities can only be restricted
+ }
+}
+
+fn main() {}
+
+// test multichar names
+mod xyz {}
+pub (xyz) fn xyz() {} //~ incorrect visibility restriction
diff --git a/tests/ui/pub/pub-restricted.stderr b/tests/ui/pub/pub-restricted.stderr
new file mode 100644
index 000000000..4694530e5
--- /dev/null
+++ b/tests/ui/pub/pub-restricted.stderr
@@ -0,0 +1,65 @@
+error[E0704]: incorrect visibility restriction
+ --> $DIR/pub-restricted.rs:3:6
+ |
+LL | pub (a) fn afn() {}
+ | ^ help: make this visible only to module `a` with `in`: `in a`
+ |
+ = help: some possible visibility restrictions are:
+ `pub(crate)`: visible only on the current crate
+ `pub(super)`: visible only in the current module's parent
+ `pub(in path::to::module)`: visible only on the specified path
+
+error[E0704]: incorrect visibility restriction
+ --> $DIR/pub-restricted.rs:4:6
+ |
+LL | pub (b) fn bfn() {}
+ | ^ help: make this visible only to module `b` with `in`: `in b`
+ |
+ = help: some possible visibility restrictions are:
+ `pub(crate)`: visible only on the current crate
+ `pub(super)`: visible only in the current module's parent
+ `pub(in path::to::module)`: visible only on the specified path
+
+error[E0704]: incorrect visibility restriction
+ --> $DIR/pub-restricted.rs:5:6
+ |
+LL | pub (crate::a) fn cfn() {}
+ | ^^^^^^^^ help: make this visible only to module `crate::a` with `in`: `in crate::a`
+ |
+ = help: some possible visibility restrictions are:
+ `pub(crate)`: visible only on the current crate
+ `pub(super)`: visible only in the current module's parent
+ `pub(in path::to::module)`: visible only on the specified path
+
+error[E0704]: incorrect visibility restriction
+ --> $DIR/pub-restricted.rs:22:14
+ |
+LL | pub (a) invalid: usize,
+ | ^ help: make this visible only to module `a` with `in`: `in a`
+ |
+ = help: some possible visibility restrictions are:
+ `pub(crate)`: visible only on the current crate
+ `pub(super)`: visible only in the current module's parent
+ `pub(in path::to::module)`: visible only on the specified path
+
+error[E0704]: incorrect visibility restriction
+ --> $DIR/pub-restricted.rs:31:6
+ |
+LL | pub (xyz) fn xyz() {}
+ | ^^^ help: make this visible only to module `xyz` with `in`: `in xyz`
+ |
+ = help: some possible visibility restrictions are:
+ `pub(crate)`: visible only on the current crate
+ `pub(super)`: visible only in the current module's parent
+ `pub(in path::to::module)`: visible only on the specified path
+
+error[E0742]: visibilities can only be restricted to ancestor modules
+ --> $DIR/pub-restricted.rs:23:17
+ |
+LL | pub (in x) non_parent_invalid: usize,
+ | ^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0704, E0742.
+For more information about an error, try `rustc --explain E0704`.