From 799e822c7b5a9c193907bed480bd357e813e5d99 Mon Sep 17 00:00:00 2001 From: 0urobor0s <0urobor0s@users.noreply.github.com> Date: Mon, 21 Dec 2020 17:42:35 +0000 Subject: [PATCH 1/7] Rustdoc render public underscore_imports as Re-exports Fixes #61592 --- src/librustdoc/clean/mod.rs | 3 ++- src/test/rustdoc/issue-61592.rs | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc/issue-61592.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index cc5f68bc29773..2b66f1b17a957 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2171,7 +2171,8 @@ impl Clean> for doctree::Import<'_> { } None => false, } - }); + }) + || (self.vis.node.is_pub() && self.name == kw::Underscore); // 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); diff --git a/src/test/rustdoc/issue-61592.rs b/src/test/rustdoc/issue-61592.rs new file mode 100644 index 0000000000000..bb64acd6e538c --- /dev/null +++ b/src/test/rustdoc/issue-61592.rs @@ -0,0 +1,7 @@ +pub mod foo { + pub struct Foo; +} + +// @has issue_61592/index.html +// @has - '//*[@href="#reexports"]' 'Re-exports' +pub use foo::Foo as _; From f502263de62b59cefed0aa5079dedcfc499fd42e Mon Sep 17 00:00:00 2001 From: 0urobor0s <0urobor0s@users.noreply.github.com> Date: Tue, 22 Dec 2020 14:17:30 +0000 Subject: [PATCH 2/7] Improve test --- src/librustdoc/clean/mod.rs | 4 ++-- src/test/rustdoc/auxiliary/issue-61592.rs | 4 ++++ src/test/rustdoc/issue-61592.rs | 18 +++++++++++++----- 3 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 src/test/rustdoc/auxiliary/issue-61592.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2b66f1b17a957..d46303e6f5025 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2162,6 +2162,7 @@ impl Clean> for doctree::Import<'_> { // #[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() + || (self.vis.node.is_pub() && self.name == kw::Underscore) || self.attrs.iter().any(|a| { a.has_name(sym::doc) && match a.meta_item_list() { @@ -2171,8 +2172,7 @@ impl Clean> for doctree::Import<'_> { } None => false, } - }) - || (self.vis.node.is_pub() && self.name == kw::Underscore); + }); // 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); diff --git a/src/test/rustdoc/auxiliary/issue-61592.rs b/src/test/rustdoc/auxiliary/issue-61592.rs new file mode 100644 index 0000000000000..6e16a4caf5948 --- /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 index bb64acd6e538c..aef038c07d891 100644 --- a/src/test/rustdoc/issue-61592.rs +++ b/src/test/rustdoc/issue-61592.rs @@ -1,7 +1,15 @@ -pub mod foo { - pub struct Foo; -} +// 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 - '//*[@href="#reexports"]' 'Re-exports' -pub use foo::Foo as _; +// @has - '//a[@href="#reexports"]' 'Re-exports' +// @has - '//code' 'pub use foo::FooStruct as _;' +// @!has - '//a[@href="struct._.html"]' +pub use foo::FooStruct as _; From 0c217a6c2d59c84e5b29b8d74afb7d5526c710c5 Mon Sep 17 00:00:00 2001 From: 0urobor0s <0urobor0s@users.noreply.github.com> Date: Tue, 22 Dec 2020 18:04:34 +0000 Subject: [PATCH 3/7] Add error code --- compiler/rustc_error_codes/src/error_codes.rs | 1 + .../src/error_codes/E0780.md | 25 +++++++++++++++++++ src/librustdoc/clean/mod.rs | 16 +++++++++++- src/test/rustdoc-ui/auxiliary/issue-61592.rs | 3 +++ src/test/rustdoc-ui/issue-61592.rs | 8 ++++++ src/test/rustdoc-ui/issue-61592.stderr | 11 ++++++++ 6 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0780.md create mode 100644 src/test/rustdoc-ui/auxiliary/issue-61592.rs create mode 100644 src/test/rustdoc-ui/issue-61592.rs create mode 100644 src/test/rustdoc-ui/issue-61592.stderr diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index fef6602b9ccbb..c669f7fed272a 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 0000000000000..19470fed41d0e --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0780.md @@ -0,0 +1,25 @@ +Cannot use `doc(inline)` with wildcard imports + +Erroneous code example: + +```compile_fail,E0780 +extern crate foo; + +#[doc(inline)] // error: invalid doc argument +pub use foo::Foo as _; +``` + +When using a wildcard import the `doc` attribute currently only supports: + + * hidden + +To fix this error either change to one of the available arguments or remove the +`doc` attribute. + +Example: + +``` +extern crate foo; + +pub use foo::Foo as _; +``` diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d46303e6f5025..b1f4ef165dd9b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2157,12 +2157,26 @@ impl Clean> for doctree::Import<'_> { return Vec::new(); } + let inlined = self.attrs.lists(sym::doc).has_word(sym::inline); + let pub_underscore = self.vis.node.is_pub() && self.name == kw::Underscore; + + if pub_underscore && inlined { + rustc_errors::struct_span_err!( + cx.tcx.sess, + self.attrs.lists(sym::doc).next().unwrap().span(), + E0780, + "inline with wildcard import" + ) + .span_label(self.span, "wildcard 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() - || (self.vis.node.is_pub() && self.name == kw::Underscore) + || pub_underscore || self.attrs.iter().any(|a| { a.has_name(sym::doc) && match a.meta_item_list() { 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 0000000000000..57a365b3f386a --- /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.rs b/src/test/rustdoc-ui/issue-61592.rs new file mode 100644 index 0000000000000..66772557f2c2f --- /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 0000000000000..c182714366c17 --- /dev/null +++ b/src/test/rustdoc-ui/issue-61592.stderr @@ -0,0 +1,11 @@ +error[E0780]: inline with wildcard import + --> $DIR/issue-61592.rs:5:7 + | +LL | #[doc(inline)] + | ^^^^^^ +LL | pub use foo::Foo as _; + | ---------------------- wildcard import + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0780`. From d2611766f11a124c3d564a60232e4e8c701e1a82 Mon Sep 17 00:00:00 2001 From: 0urobor0s <0urobor0s@users.noreply.github.com> Date: Tue, 22 Dec 2020 18:26:40 +0000 Subject: [PATCH 4/7] Formatting --- .../rustc_error_codes/src/error_codes/E0780.md | 2 +- src/librustdoc/clean/mod.rs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0780.md b/compiler/rustc_error_codes/src/error_codes/E0780.md index 19470fed41d0e..8fa39a0f8a900 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0780.md +++ b/compiler/rustc_error_codes/src/error_codes/E0780.md @@ -14,7 +14,7 @@ When using a wildcard import the `doc` attribute currently only supports: * hidden To fix this error either change to one of the available arguments or remove the -`doc` attribute. +`doc` attribute. Example: diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b1f4ef165dd9b..fa3da51959cff 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2161,14 +2161,14 @@ impl Clean> for doctree::Import<'_> { let pub_underscore = self.vis.node.is_pub() && self.name == kw::Underscore; if pub_underscore && inlined { - rustc_errors::struct_span_err!( - cx.tcx.sess, - self.attrs.lists(sym::doc).next().unwrap().span(), - E0780, - "inline with wildcard import" - ) - .span_label(self.span, "wildcard import") - .emit(); + rustc_errors::struct_span_err!( + cx.tcx.sess, + self.attrs.lists(sym::doc).next().unwrap().span(), + E0780, + "inline with wildcard import" + ) + .span_label(self.span, "wildcard import") + .emit(); } // We consider inlining the documentation of `pub use` statements, but we From b3b74a9141ea8983ac80426549300fd2ac315612 Mon Sep 17 00:00:00 2001 From: 0urobor0s <0urobor0s@users.noreply.github.com> Date: Wed, 23 Dec 2020 00:52:50 +0000 Subject: [PATCH 5/7] Refactor --- .../rustc_error_codes/src/error_codes/E0780.md | 14 +++++--------- src/librustdoc/clean/mod.rs | 10 +++++----- src/librustdoc/clean/types.rs | 12 +++++++++++- src/test/rustdoc-ui/issue-61592-2.rs | 10 ++++++++++ src/test/rustdoc-ui/issue-61592-2.stderr | 12 ++++++++++++ 5 files changed, 43 insertions(+), 15 deletions(-) create mode 100644 src/test/rustdoc-ui/issue-61592-2.rs create mode 100644 src/test/rustdoc-ui/issue-61592-2.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0780.md b/compiler/rustc_error_codes/src/error_codes/E0780.md index 8fa39a0f8a900..a8d2c5c983ce8 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0780.md +++ b/compiler/rustc_error_codes/src/error_codes/E0780.md @@ -1,24 +1,20 @@ -Cannot use `doc(inline)` with wildcard imports +Cannot use `doc(inline)` with anonymous imports Erroneous code example: -```compile_fail,E0780 +```compile_fail,E0780,edition2018 extern crate foo; #[doc(inline)] // error: invalid doc argument pub use foo::Foo as _; ``` -When using a wildcard import the `doc` attribute currently only supports: - - * hidden - -To fix this error either change to one of the available arguments or remove the -`doc` attribute. +Anonymous imports are always rendered with `#[doc(no_inline)]`. To fix this +error, remove the `#[doc(inline)]` attribute. Example: -``` +```ignore (cannot-doctest-multicrate-project) extern crate foo; pub use foo::Foo as _; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fa3da51959cff..d3358df20d060 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2157,17 +2157,17 @@ impl Clean> for doctree::Import<'_> { return Vec::new(); } - let inlined = self.attrs.lists(sym::doc).has_word(sym::inline); + let (doc_meta_item, inlined) = 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 && inlined { rustc_errors::struct_span_err!( cx.tcx.sess, - self.attrs.lists(sym::doc).next().unwrap().span(), + doc_meta_item.unwrap().span(), E0780, - "inline with wildcard import" + "anonymous imports cannot be inlined" ) - .span_label(self.span, "wildcard import") + .span_label(self.span, "anonymous import") .emit(); } @@ -2189,7 +2189,7 @@ impl Clean> 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 please_inline = inlined; 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 cd6eccea53218..d8dfdd0941be8 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, bool); } -impl> NestedAttributesExt for I { +impl + IntoIterator> + 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, 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/issue-61592-2.rs b/src/test/rustdoc-ui/issue-61592-2.rs new file mode 100644 index 0000000000000..5b4fc5ee70063 --- /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 0000000000000..1b7f8bb552c0c --- /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`. From 8a4e7a7525ab425fe5487d8cfdff30e2f1e223ce Mon Sep 17 00:00:00 2001 From: 0urobor0s <0urobor0s@users.noreply.github.com> Date: Wed, 23 Dec 2020 12:49:47 +0000 Subject: [PATCH 6/7] Fix tests --- compiler/rustc_error_codes/src/error_codes/E0780.md | 4 +--- src/librustdoc/clean/mod.rs | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0780.md b/compiler/rustc_error_codes/src/error_codes/E0780.md index a8d2c5c983ce8..704b4ae181bb2 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0780.md +++ b/compiler/rustc_error_codes/src/error_codes/E0780.md @@ -2,8 +2,7 @@ Cannot use `doc(inline)` with anonymous imports Erroneous code example: -```compile_fail,E0780,edition2018 -extern crate foo; +```ignore (cannot-doctest-multicrate-project) #[doc(inline)] // error: invalid doc argument pub use foo::Foo as _; @@ -15,7 +14,6 @@ error, remove the `#[doc(inline)]` attribute. Example: ```ignore (cannot-doctest-multicrate-project) -extern crate foo; pub use foo::Foo as _; ``` diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d3358df20d060..9a15a4bb91747 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2157,10 +2157,10 @@ impl Clean> for doctree::Import<'_> { return Vec::new(); } - let (doc_meta_item, inlined) = self.attrs.lists(sym::doc).get_word_attr(sym::inline); + 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 && inlined { + if pub_underscore && please_inline { rustc_errors::struct_span_err!( cx.tcx.sess, doc_meta_item.unwrap().span(), @@ -2189,7 +2189,6 @@ impl Clean> 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 = inlined; let path = self.path.clean(cx); let inner = if self.glob { if !denied { From 19907130af2d4e6f52a9c32b48cd4c486f397ed0 Mon Sep 17 00:00:00 2001 From: 0urobor0s <0urobor0s@users.noreply.github.com> Date: Wed, 23 Dec 2020 14:12:19 +0000 Subject: [PATCH 7/7] Fix tests --- src/test/rustdoc-ui/issue-61592.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/rustdoc-ui/issue-61592.stderr b/src/test/rustdoc-ui/issue-61592.stderr index c182714366c17..9c9c9106f8ac3 100644 --- a/src/test/rustdoc-ui/issue-61592.stderr +++ b/src/test/rustdoc-ui/issue-61592.stderr @@ -1,10 +1,10 @@ -error[E0780]: inline with wildcard import +error[E0780]: anonymous imports cannot be inlined --> $DIR/issue-61592.rs:5:7 | LL | #[doc(inline)] | ^^^^^^ LL | pub use foo::Foo as _; - | ---------------------- wildcard import + | ---------------------- anonymous import error: aborting due to previous error