about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_passes/messages.ftl5
-rw-r--r--compiler/rustc_passes/src/check_attr.rs41
-rw-r--r--compiler/rustc_passes/src/errors.rs12
-rw-r--r--src/doc/rustdoc/src/write-documentation/the-doc-attribute.md51
-rw-r--r--tests/rustdoc-ui/lints/invalid-doc-attr.rs4
-rw-r--r--tests/rustdoc-ui/lints/invalid-doc-attr.stderr32
-rw-r--r--tests/ui/lint/unused/useless-comment.rs7
-rw-r--r--tests/ui/lint/unused/useless-comment.stderr73
-rw-r--r--tests/ui/rustdoc/doc-test-attr-pass.rs38
9 files changed, 147 insertions, 116 deletions
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 2f264ed4fc0..6d815e510ea 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -46,11 +46,6 @@ passes_attr_crate_level =
     .suggestion = to apply to the crate, use an inner attribute
     .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
 
-passes_attr_mod_level =
-    this attribute can only be applied at module level
-    .suggestion = to apply to the crate, use an inner attribute at the crate level
-    .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-module-level> for more information
-
 passes_attr_only_in_functions =
     `{$attr}` attribute can only be used on functions
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 376b424a1af..29063ea8d29 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1252,7 +1252,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             let bang_span = attr.span().lo() + BytePos(1);
             let sugg = (attr.style() == AttrStyle::Outer
                 && self.tcx.hir_get_parent_item(hir_id) == CRATE_OWNER_ID)
-                .then_some(errors::AttrCrateLevelSugg {
+                .then_some(errors::AttrCrateLevelOnlySugg {
                     attr: attr.span().with_lo(bang_span).with_hi(bang_span),
                 });
             self.tcx.emit_node_span_lint(
@@ -1266,46 +1266,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         true
     }
 
-    /// Checks that an attribute is used at module level. Returns `true` if valid.
-    fn check_attr_mod_level(
-        &self,
-        attr: &Attribute,
-        meta: &MetaItemInner,
-        hir_id: HirId,
-        target: Target,
-    ) -> bool {
-        if target != Target::Mod {
-            // insert a bang between `#` and `[...`
-            let bang_span = attr.span().lo() + BytePos(1);
-            let sugg = (attr.style() == AttrStyle::Outer
-                && self.tcx.hir_get_parent_item(hir_id) == CRATE_OWNER_ID)
-                .then_some(errors::AttrCrateLevelSugg {
-                    attr: attr.span().with_lo(bang_span).with_hi(bang_span),
-                });
-            self.tcx.emit_node_span_lint(
-                INVALID_DOC_ATTRIBUTES,
-                hir_id,
-                meta.span(),
-                errors::AttrModLevelOnly { sugg },
-            );
-            return false;
-        }
-        true
-    }
-
     /// Checks that `doc(test(...))` attribute contains only valid attributes and are at the right place.
-    fn check_test_attr(
-        &self,
-        attr: &Attribute,
-        meta: &MetaItemInner,
-        hir_id: HirId,
-        target: Target,
-    ) {
+    fn check_test_attr(&self, attr: &Attribute, meta: &MetaItemInner, hir_id: HirId) {
         if let Some(metas) = meta.meta_item_list() {
             for i_meta in metas {
                 match (i_meta.name(), i_meta.meta_item()) {
                     (Some(sym::attr), _) => {
-                        self.check_attr_mod_level(attr, meta, hir_id, target);
+                        // Allowed everywhere like `#[doc]`
                     }
                     (Some(sym::no_crate_inject), _) => {
                         self.check_attr_crate_level(attr, meta, hir_id);
@@ -1396,7 +1363,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         }
 
                         Some(sym::test) => {
-                            self.check_test_attr(attr, meta, hir_id, target);
+                            self.check_test_attr(attr, meta, hir_id);
                         }
 
                         Some(
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 38b0db37e12..00682a9c7a7 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1890,20 +1890,12 @@ pub(crate) struct UnusedVarTryIgnoreSugg {
 #[note]
 pub(crate) struct AttrCrateLevelOnly {
     #[subdiagnostic]
-    pub sugg: Option<AttrCrateLevelSugg>,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(passes_attr_mod_level)]
-#[note]
-pub(crate) struct AttrModLevelOnly {
-    #[subdiagnostic]
-    pub sugg: Option<AttrCrateLevelSugg>,
+    pub sugg: Option<AttrCrateLevelOnlySugg>,
 }
 
 #[derive(Subdiagnostic)]
 #[suggestion(passes_suggestion, applicability = "maybe-incorrect", code = "!", style = "verbose")]
-pub(crate) struct AttrCrateLevelSugg {
+pub(crate) struct AttrCrateLevelOnlySugg {
     #[primary_span]
     pub attr: Span,
 }
diff --git a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
index afbcf4000c5..a70861faa76 100644
--- a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
+++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
@@ -141,34 +141,6 @@ But if you include this:
 
 it will not.
 
-## At the module level
-
-These forms of the `#[doc]` attribute are used on individual modules, to control how
-they are documented.
-
-### `test(attr(...))`
-
-This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For
-example, if you want your doctests to fail if they have dead code, you could add this:
-
-```rust,no_run
-#![doc(test(attr(deny(dead_code))))]
-
-mod my_mod {
-    #![doc(test(attr(allow(dead_code))))] // but allow `dead_code` for this module
-}
-```
-
-`test(attr(..))` attributes are appended to the parent module's, they do not replace the current
-list of attributes. In the previous example, both attributes would be present:
-
-```rust,no_run
-// For every doctest in `my_mod`
-
-#![deny(dead_code)] // from the crate-root
-#![allow(dead_code)] // from `my_mod`
-```
-
 ## At the item level
 
 These forms of the `#[doc]` attribute are used on individual items, to control how
@@ -300,3 +272,26 @@ To get around this limitation, we just add `#[doc(alias = "lib_name_do_something
 on the `do_something` method and then it's all good!
 Users can now look for `lib_name_do_something` in our crate directly and find
 `Obj::do_something`.
+
+### `test(attr(...))`
+
+This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For
+example, if you want your doctests to fail if they have dead code, you could add this:
+
+```rust,no_run
+#![doc(test(attr(deny(dead_code))))]
+
+mod my_mod {
+    #![doc(test(attr(allow(dead_code))))] // but allow `dead_code` for this module
+}
+```
+
+`test(attr(..))` attributes are appended to the parent module's, they do not replace the current
+list of attributes. In the previous example, both attributes would be present:
+
+```rust,no_run
+// For every doctest in `my_mod`
+
+#![deny(dead_code)] // from the crate-root
+#![allow(dead_code)] // from `my_mod`
+```
diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.rs b/tests/rustdoc-ui/lints/invalid-doc-attr.rs
index cd5ae44b126..e1cc08ca242 100644
--- a/tests/rustdoc-ui/lints/invalid-doc-attr.rs
+++ b/tests/rustdoc-ui/lints/invalid-doc-attr.rs
@@ -4,10 +4,6 @@
 #![doc(masked)]
 //~^ ERROR this attribute can only be applied to an `extern crate` item
 
-#[doc(test(attr(allow(warnings))))]
-//~^ ERROR can only be applied at module level
-//~| HELP to apply to the crate, use an inner attribute
-//~| SUGGESTION !
 #[doc(test(no_crate_inject))]
 //~^ ERROR can only be applied at the crate level
 //~| HELP to apply to the crate, use an inner attribute
diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
index 0fd55ff94d8..7621999a8ca 100644
--- a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
+++ b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
@@ -1,30 +1,18 @@
-error: this attribute can only be applied at module level
-  --> $DIR/invalid-doc-attr.rs:7:7
-   |
-LL | #[doc(test(attr(allow(warnings))))]
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-module-level> for more information
-   = note: `#[deny(invalid_doc_attributes)]` on by default
-help: to apply to the crate, use an inner attribute at the crate level
-   |
-LL | #![doc(test(attr(allow(warnings))))]
-   |  +
-
 error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:11:7
+  --> $DIR/invalid-doc-attr.rs:7:7
    |
 LL | #[doc(test(no_crate_inject))]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
+   = note: `#[deny(invalid_doc_attributes)]` on by default
 help: to apply to the crate, use an inner attribute
    |
 LL | #![doc(test(no_crate_inject))]
    |  +
 
 error: this attribute can only be applied to a `use` item
-  --> $DIR/invalid-doc-attr.rs:15:7
+  --> $DIR/invalid-doc-attr.rs:11:7
    |
 LL | #[doc(inline)]
    |       ^^^^^^ only applicable on `use` items
@@ -35,7 +23,7 @@ LL | pub fn foo() {}
    = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
 
 error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:20:12
+  --> $DIR/invalid-doc-attr.rs:16:12
    |
 LL |     #![doc(test(no_crate_inject))]
    |            ^^^^^^^^^^^^^^^^^^^^^
@@ -43,7 +31,7 @@ LL |     #![doc(test(no_crate_inject))]
    = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
 
 error: conflicting doc inlining attributes
-  --> $DIR/invalid-doc-attr.rs:30:7
+  --> $DIR/invalid-doc-attr.rs:26:7
    |
 LL | #[doc(inline)]
    |       ^^^^^^ this attribute...
@@ -53,7 +41,7 @@ LL | #[doc(no_inline)]
    = help: remove one of the conflicting attributes
 
 error: this attribute can only be applied to an `extern crate` item
-  --> $DIR/invalid-doc-attr.rs:36:7
+  --> $DIR/invalid-doc-attr.rs:32:7
    |
 LL | #[doc(masked)]
    |       ^^^^^^ only applicable on `extern crate` items
@@ -64,7 +52,7 @@ LL | pub struct Masked;
    = note: read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
 
 error: this attribute cannot be applied to an `extern crate self` item
-  --> $DIR/invalid-doc-attr.rs:40:7
+  --> $DIR/invalid-doc-attr.rs:36:7
    |
 LL | #[doc(masked)]
    |       ^^^^^^ not applicable on `extern crate self` items
@@ -81,7 +69,7 @@ LL | #![doc(masked)]
    = note: read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
 
 error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:23:11
+  --> $DIR/invalid-doc-attr.rs:19:11
    |
 LL |     #[doc(test(no_crate_inject))]
    |           ^^^^^^^^^^^^^^^^^^^^^
@@ -89,7 +77,7 @@ LL |     #[doc(test(no_crate_inject))]
    = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
 
 error: this attribute can only be applied to a `use` item
-  --> $DIR/invalid-doc-attr.rs:25:11
+  --> $DIR/invalid-doc-attr.rs:21:11
    |
 LL |     #[doc(inline)]
    |           ^^^^^^ only applicable on `use` items
@@ -99,5 +87,5 @@ LL |     pub fn baz() {}
    |
    = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
 
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/tests/ui/lint/unused/useless-comment.rs b/tests/ui/lint/unused/useless-comment.rs
index 4ec52f20747..898665278e3 100644
--- a/tests/ui/lint/unused/useless-comment.rs
+++ b/tests/ui/lint/unused/useless-comment.rs
@@ -9,8 +9,13 @@ macro_rules! mac {
 /// foo //~ ERROR unused doc comment
 mac!();
 
+/// a //~ ERROR unused doc comment
+#[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
+unsafe extern "C" { }
+
 fn foo() {
     /// a //~ ERROR unused doc comment
+    #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
     let x = 12;
 
     /// multi-line //~ ERROR unused doc comment
@@ -19,6 +24,7 @@ fn foo() {
     match x {
         /// c //~ ERROR unused doc comment
         1 => {},
+        #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
         _ => {}
     }
 
@@ -32,6 +38,7 @@ fn foo() {
     /// bar //~ ERROR unused doc comment
     mac!();
 
+    #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
     let x = /** comment */ 47; //~ ERROR unused doc comment
 
     /// dox //~ ERROR unused doc comment
diff --git a/tests/ui/lint/unused/useless-comment.stderr b/tests/ui/lint/unused/useless-comment.stderr
index 8bb5bdaeb25..39873b82b75 100644
--- a/tests/ui/lint/unused/useless-comment.stderr
+++ b/tests/ui/lint/unused/useless-comment.stderr
@@ -12,7 +12,28 @@ LL | #![deny(unused_doc_comments)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: unused doc comment
-  --> $DIR/useless-comment.rs:32:5
+  --> $DIR/useless-comment.rs:12:1
+   |
+LL | /// a
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[doc(test(attr(allow(dead_code))))]
+LL | unsafe extern "C" { }
+   | --------------------- rustdoc does not generate documentation for extern blocks
+   |
+   = help: use `//` for a plain comment
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:13:1
+   |
+LL | #[doc(test(attr(allow(dead_code))))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | unsafe extern "C" { }
+   | --------------------- rustdoc does not generate documentation for extern blocks
+   |
+   = help: use `//` for a plain comment
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:38:5
    |
 LL |     /// bar
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations
@@ -20,17 +41,28 @@ LL |     /// bar
    = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
 
 error: unused doc comment
-  --> $DIR/useless-comment.rs:13:5
+  --> $DIR/useless-comment.rs:17:5
    |
 LL |     /// a
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[doc(test(attr(allow(dead_code))))]
 LL |     let x = 12;
    |     ----------- rustdoc does not generate documentation for statements
    |
    = help: use `//` for a plain comment
 
 error: unused doc comment
-  --> $DIR/useless-comment.rs:16:5
+  --> $DIR/useless-comment.rs:18:5
+   |
+LL |     #[doc(test(attr(allow(dead_code))))]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let x = 12;
+   |     ----------- rustdoc does not generate documentation for statements
+   |
+   = help: use `//` for a plain comment
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:21:5
    |
 LL | /     /// multi-line
 LL | |     /// doc comment
@@ -39,6 +71,7 @@ LL | |     /// that is unused
 LL | /     match x {
 LL | |         /// c
 LL | |         1 => {},
+LL | |         #[doc(test(attr(allow(dead_code))))]
 LL | |         _ => {}
 LL | |     }
    | |_____- rustdoc does not generate documentation for expressions
@@ -46,7 +79,7 @@ LL | |     }
    = help: use `//` for a plain comment
 
 error: unused doc comment
-  --> $DIR/useless-comment.rs:20:9
+  --> $DIR/useless-comment.rs:25:9
    |
 LL |         /// c
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -56,7 +89,17 @@ LL |         1 => {},
    = help: use `//` for a plain comment
 
 error: unused doc comment
-  --> $DIR/useless-comment.rs:25:5
+  --> $DIR/useless-comment.rs:27:9
+   |
+LL |         #[doc(test(attr(allow(dead_code))))]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         _ => {}
+   |         ------- rustdoc does not generate documentation for match arms
+   |
+   = help: use `//` for a plain comment
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:31:5
    |
 LL |     /// foo
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +109,7 @@ LL |     unsafe {}
    = help: use `//` for a plain comment
 
 error: unused doc comment
-  --> $DIR/useless-comment.rs:28:5
+  --> $DIR/useless-comment.rs:34:5
    |
 LL |     #[doc = "foo"]
    |     ^^^^^^^^^^^^^^
@@ -77,7 +120,7 @@ LL |     3;
    = help: use `//` for a plain comment
 
 error: unused doc comment
-  --> $DIR/useless-comment.rs:29:5
+  --> $DIR/useless-comment.rs:35:5
    |
 LL |     #[doc = "bar"]
    |     ^^^^^^^^^^^^^^
@@ -87,7 +130,17 @@ LL |     3;
    = help: use `//` for a plain comment
 
 error: unused doc comment
-  --> $DIR/useless-comment.rs:35:13
+  --> $DIR/useless-comment.rs:41:5
+   |
+LL |     #[doc(test(attr(allow(dead_code))))]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let x = /** comment */ 47;
+   |     -------------------------- rustdoc does not generate documentation for statements
+   |
+   = help: use `//` for a plain comment
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:42:13
    |
 LL |     let x = /** comment */ 47;
    |             ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions
@@ -95,7 +148,7 @@ LL |     let x = /** comment */ 47;
    = help: use `/* */` for a plain comment
 
 error: unused doc comment
-  --> $DIR/useless-comment.rs:37:5
+  --> $DIR/useless-comment.rs:44:5
    |
 LL |       /// dox
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -106,5 +159,5 @@ LL | |     }
    |
    = help: use `//` for a plain comment
 
-error: aborting due to 10 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/tests/ui/rustdoc/doc-test-attr-pass.rs b/tests/ui/rustdoc/doc-test-attr-pass.rs
index 40ffd5b2572..60d1e3722bd 100644
--- a/tests/ui/rustdoc/doc-test-attr-pass.rs
+++ b/tests/ui/rustdoc/doc-test-attr-pass.rs
@@ -10,4 +10,42 @@ mod test {
     #![doc(test(attr(allow(warnings))))]
 }
 
+#[doc(test(attr(allow(dead_code))))]
+static S: u32 = 5;
+
+#[doc(test(attr(allow(dead_code))))]
+const C: u32 = 5;
+
+#[doc(test(attr(deny(dead_code))))]
+struct A {
+    #[doc(test(attr(allow(dead_code))))]
+    field: u32
+}
+
+#[doc(test(attr(deny(dead_code))))]
+union U {
+    #[doc(test(attr(allow(dead_code))))]
+    field: u32,
+    field2: u64,
+}
+
+#[doc(test(attr(deny(dead_code))))]
+enum Enum {
+    #[doc(test(attr(allow(dead_code))))]
+    Variant1,
+}
+
+#[doc(test(attr(deny(dead_code))))]
+impl A {
+    #[doc(test(attr(deny(dead_code))))]
+    fn method() {}
+}
+
+#[doc(test(attr(deny(dead_code))))]
+trait MyTrait {
+    #[doc(test(attr(deny(dead_code))))]
+    fn my_trait_fn();
+}
+
+#[doc(test(attr(deny(dead_code))))]
 pub fn foo() {}