about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-12-31 09:07:51 +0000
committerbors <bors@rust-lang.org>2020-12-31 09:07:51 +0000
commitcb4553bdae56b41c295137ab694fab0050f7c29d (patch)
tree8340f8f0d6ee330704a00443a253db9990f1e5fc
parent11c94a197726b6a981828cb1837d7c3eed1b841d (diff)
downloadrust-cb4553bdae56b41c295137ab694fab0050f7c29d.tar.gz
rust-cb4553bdae56b41c295137ab694fab0050f7c29d.zip
Rustdoc render public underscore_imports as Re-exports
Fixes #61592
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs1
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0780.md19
-rw-r--r--src/librustdoc/clean/mod.rs16
-rw-r--r--src/librustdoc/clean/types.rs12
-rw-r--r--src/test/rustdoc-ui/auxiliary/issue-61592.rs3
-rw-r--r--src/test/rustdoc-ui/issue-61592-2.rs10
-rw-r--r--src/test/rustdoc-ui/issue-61592-2.stderr12
-rw-r--r--src/test/rustdoc-ui/issue-61592.rs8
-rw-r--r--src/test/rustdoc-ui/issue-61592.stderr11
-rw-r--r--src/test/rustdoc/auxiliary/issue-61592.rs4
-rw-r--r--src/test/rustdoc/issue-61592.rs15
11 files changed, 109 insertions, 2 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index fef6602b9cc..c669f7fed27 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -464,6 +464,7 @@ E0776: include_str!("./error_codes/E0776.md"),
 E0777: include_str!("./error_codes/E0777.md"),
 E0778: include_str!("./error_codes/E0778.md"),
 E0779: include_str!("./error_codes/E0779.md"),
+E0780: include_str!("./error_codes/E0780.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/compiler/rustc_error_codes/src/error_codes/E0780.md b/compiler/rustc_error_codes/src/error_codes/E0780.md
new file mode 100644
index 00000000000..704b4ae181b
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0780.md
@@ -0,0 +1,19 @@
+Cannot use `doc(inline)` with anonymous imports
+
+Erroneous code example:
+
+```ignore (cannot-doctest-multicrate-project)
+
+#[doc(inline)] // error: invalid doc argument
+pub use foo::Foo as _;
+```
+
+Anonymous imports are always rendered with `#[doc(no_inline)]`. To fix this
+error, remove the `#[doc(inline)]` attribute.
+
+Example:
+
+```ignore (cannot-doctest-multicrate-project)
+
+pub use foo::Foo as _;
+```
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index cc5f68bc297..9a15a4bb917 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2157,11 +2157,26 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
             return Vec::new();
         }
 
+        let (doc_meta_item, please_inline) = self.attrs.lists(sym::doc).get_word_attr(sym::inline);
+        let pub_underscore = self.vis.node.is_pub() && self.name == kw::Underscore;
+
+        if pub_underscore && please_inline {
+            rustc_errors::struct_span_err!(
+                cx.tcx.sess,
+                doc_meta_item.unwrap().span(),
+                E0780,
+                "anonymous imports cannot be inlined"
+            )
+            .span_label(self.span, "anonymous import")
+            .emit();
+        }
+
         // We consider inlining the documentation of `pub use` statements, but we
         // forcefully don't inline if this is not public or if the
         // #[doc(no_inline)] attribute is present.
         // Don't inline doc(hidden) imports so they can be stripped at a later stage.
         let mut denied = !self.vis.node.is_pub()
+            || pub_underscore
             || self.attrs.iter().any(|a| {
                 a.has_name(sym::doc)
                     && match a.meta_item_list() {
@@ -2174,7 +2189,6 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
             });
         // Also check whether imports were asked to be inlined, in case we're trying to re-export a
         // crate in Rust 2018+
-        let please_inline = self.attrs.lists(sym::doc).has_word(sym::inline);
         let path = self.path.clean(cx);
         let inner = if self.glob {
             if !denied {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index cd6eccea532..d8dfdd0941b 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -431,12 +431,22 @@ impl AttributesExt for [ast::Attribute] {
 crate trait NestedAttributesExt {
     /// Returns `true` if the attribute list contains a specific `Word`
     fn has_word(self, word: Symbol) -> bool;
+    fn get_word_attr(self, word: Symbol) -> (Option<ast::NestedMetaItem>, bool);
 }
 
-impl<I: IntoIterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
+impl<I: Iterator<Item = ast::NestedMetaItem> + IntoIterator<Item = ast::NestedMetaItem>>
+    NestedAttributesExt for I
+{
     fn has_word(self, word: Symbol) -> bool {
         self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
     }
+
+    fn get_word_attr(mut self, word: Symbol) -> (Option<ast::NestedMetaItem>, bool) {
+        match self.find(|attr| attr.is_word() && attr.has_name(word)) {
+            Some(a) => (Some(a), true),
+            None => (None, false),
+        }
+    }
 }
 
 /// A portion of documentation, extracted from a `#[doc]` attribute.
diff --git a/src/test/rustdoc-ui/auxiliary/issue-61592.rs b/src/test/rustdoc-ui/auxiliary/issue-61592.rs
new file mode 100644
index 00000000000..57a365b3f38
--- /dev/null
+++ b/src/test/rustdoc-ui/auxiliary/issue-61592.rs
@@ -0,0 +1,3 @@
+#![crate_name = "foo"]
+
+pub trait Foo {}
diff --git a/src/test/rustdoc-ui/issue-61592-2.rs b/src/test/rustdoc-ui/issue-61592-2.rs
new file mode 100644
index 00000000000..5b4fc5ee700
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592-2.rs
@@ -0,0 +1,10 @@
+// aux-build:issue-61592.rs
+
+extern crate foo;
+
+#[doc = "bar"]
+#[doc(inline)] //~ ERROR
+#[doc = "baz"]
+pub use foo::Foo as _;
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/issue-61592-2.stderr b/src/test/rustdoc-ui/issue-61592-2.stderr
new file mode 100644
index 00000000000..1b7f8bb552c
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592-2.stderr
@@ -0,0 +1,12 @@
+error[E0780]: anonymous imports cannot be inlined
+  --> $DIR/issue-61592-2.rs:6:7
+   |
+LL | #[doc(inline)]
+   |       ^^^^^^
+LL | #[doc = "baz"]
+LL | pub use foo::Foo as _;
+   | ---------------------- anonymous import
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0780`.
diff --git a/src/test/rustdoc-ui/issue-61592.rs b/src/test/rustdoc-ui/issue-61592.rs
new file mode 100644
index 00000000000..66772557f2c
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-61592.rs
+
+extern crate foo;
+
+#[doc(inline)] //~ ERROR
+pub use foo::Foo as _;
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/issue-61592.stderr b/src/test/rustdoc-ui/issue-61592.stderr
new file mode 100644
index 00000000000..9c9c9106f8a
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592.stderr
@@ -0,0 +1,11 @@
+error[E0780]: anonymous imports cannot be inlined
+  --> $DIR/issue-61592.rs:5:7
+   |
+LL | #[doc(inline)]
+   |       ^^^^^^
+LL | pub use foo::Foo as _;
+   | ---------------------- anonymous import
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0780`.
diff --git a/src/test/rustdoc/auxiliary/issue-61592.rs b/src/test/rustdoc/auxiliary/issue-61592.rs
new file mode 100644
index 00000000000..6e16a4caf59
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/issue-61592.rs
@@ -0,0 +1,4 @@
+#![crate_name = "foo"]
+
+pub trait FooTrait {}
+pub struct FooStruct;
diff --git a/src/test/rustdoc/issue-61592.rs b/src/test/rustdoc/issue-61592.rs
new file mode 100644
index 00000000000..aef038c07d8
--- /dev/null
+++ b/src/test/rustdoc/issue-61592.rs
@@ -0,0 +1,15 @@
+// aux-build:issue-61592.rs
+
+extern crate foo;
+
+// @has issue_61592/index.html
+// @has - '//a[@href="#reexports"]' 'Re-exports'
+// @has - '//code' 'pub use foo::FooTrait as _;'
+// @!has - '//a[@href="trait._.html"]'
+pub use foo::FooTrait as _;
+
+// @has issue_61592/index.html
+// @has - '//a[@href="#reexports"]' 'Re-exports'
+// @has - '//code' 'pub use foo::FooStruct as _;'
+// @!has - '//a[@href="struct._.html"]'
+pub use foo::FooStruct as _;