about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_passes/src/check_attr.rs87
-rw-r--r--src/test/rustdoc-ui/doc-attr2.rs11
-rw-r--r--src/test/rustdoc-ui/doc-attr2.stderr26
-rw-r--r--src/test/rustdoc-ui/invalid-doc-attr.rs26
-rw-r--r--src/test/rustdoc-ui/invalid-doc-attr.stderr68
5 files changed, 169 insertions, 49 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index d57cba6420f..f68b79b6043 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -8,7 +8,7 @@ use rustc_middle::hir::map::Map;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 
-use rustc_ast::{Attribute, Lit, LitKind, NestedMetaItem};
+use rustc_ast::{AttrStyle, Attribute, Lit, LitKind, NestedMetaItem};
 use rustc_errors::{pluralize, struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -564,7 +564,7 @@ impl CheckAttrVisitor<'tcx> {
         true
     }
 
-    fn check_attr_crate_level(
+    fn check_attr_not_crate_level(
         &self,
         meta: &NestedMetaItem,
         hir_id: HirId,
@@ -586,6 +586,48 @@ impl CheckAttrVisitor<'tcx> {
         true
     }
 
+    fn check_attr_crate_level(
+        &self,
+        attr: &Attribute,
+        meta: &NestedMetaItem,
+        hir_id: HirId,
+    ) -> bool {
+        if hir_id != CRATE_HIR_ID {
+            self.tcx.struct_span_lint_hir(
+                INVALID_DOC_ATTRIBUTES,
+                hir_id,
+                meta.span(),
+                |lint| {
+                    let mut err = lint.build(
+                        "this attribute can only be applied at the crate level",
+                    );
+                    if attr.style == AttrStyle::Outer && self.tcx.hir().get_parent_item(hir_id) == CRATE_HIR_ID {
+                        if let Ok(mut src) =
+                            self.tcx.sess.source_map().span_to_snippet(attr.span)
+                        {
+                            src.insert(1, '!');
+                            err.span_suggestion_verbose(
+                                attr.span,
+                                "to apply to the crate, use an inner attribute",
+                                src,
+                                Applicability::MaybeIncorrect,
+                            );
+                        } else {
+                            err.span_help(
+                                attr.span,
+                                "to apply to the crate, use an inner attribute",
+                            );
+                        }
+                    }
+                    err.note("read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level for more information")
+                        .emit();
+                },
+            );
+            return false;
+        }
+        true
+    }
+
     fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bool {
         let mut is_valid = true;
 
@@ -594,35 +636,58 @@ impl CheckAttrVisitor<'tcx> {
                 if let Some(i_meta) = meta.meta_item() {
                     match i_meta.name_or_empty() {
                         sym::alias
-                            if !self.check_attr_crate_level(&meta, hir_id, "alias")
+                            if !self.check_attr_not_crate_level(&meta, hir_id, "alias")
                                 || !self.check_doc_alias(&meta, hir_id, target) =>
                         {
                             is_valid = false
                         }
 
                         sym::keyword
-                            if !self.check_attr_crate_level(&meta, hir_id, "keyword")
+                            if !self.check_attr_not_crate_level(&meta, hir_id, "keyword")
                                 || !self.check_doc_keyword(&meta, hir_id) =>
                         {
                             is_valid = false
                         }
 
-                        sym::test if CRATE_HIR_ID != hir_id => {
+                        sym::html_favicon_url
+                        | sym::html_logo_url
+                        | sym::html_playground_url
+                        | sym::issue_tracker_base_url
+                        | sym::html_root_url
+                        | sym::html_no_source
+                        | sym::test
+                            if !self.check_attr_crate_level(&attr, &meta, hir_id) =>
+                        {
+                            is_valid = false;
+                        }
+
+                        sym::inline | sym::no_inline if target != Target::Use => {
                             self.tcx.struct_span_lint_hir(
                                 INVALID_DOC_ATTRIBUTES,
                                 hir_id,
                                 meta.span(),
                                 |lint| {
-                                    lint.build(
-                                        "`#![doc(test(...)]` is only allowed \
-                                         as a crate-level attribute",
-                                    )
-                                    .emit();
+                                    let mut err = lint.build(
+                                        "this attribute can only be applied to a `use` item",
+                                    );
+                                    err.span_label(meta.span(), "only applicable on `use` items");
+                                    if attr.style == AttrStyle::Outer {
+                                        err.span_label(
+                                            self.tcx.hir().span(hir_id),
+                                            "not a `use` item",
+                                        );
+                                    }
+                                    err.note("read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information")
+                                        .emit();
                                 },
                             );
                             is_valid = false;
                         }
 
+                        sym::inline | sym::no_inline => {
+                            // FIXME(#80275): conflicting inline attributes
+                        }
+
                         // no_default_passes: deprecated
                         // passes: deprecated
                         // plugins: removed, but rustdoc warns about it itself
@@ -635,12 +700,10 @@ impl CheckAttrVisitor<'tcx> {
                         | sym::html_playground_url
                         | sym::html_root_url
                         | sym::include
-                        | sym::inline
                         | sym::issue_tracker_base_url
                         | sym::keyword
                         | sym::masked
                         | sym::no_default_passes
-                        | sym::no_inline
                         | sym::notable_trait
                         | sym::passes
                         | sym::plugins
diff --git a/src/test/rustdoc-ui/doc-attr2.rs b/src/test/rustdoc-ui/doc-attr2.rs
deleted file mode 100644
index 3fb484644d7..00000000000
--- a/src/test/rustdoc-ui/doc-attr2.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#![crate_type = "lib"]
-#![deny(warnings)]
-
-#[doc(test(no_crate_inject))] //~ ERROR
-//~^ WARN
-pub fn foo() {}
-
-pub mod bar {
-    #![doc(test(no_crate_inject))] //~ ERROR
-    //~^ WARN
-}
diff --git a/src/test/rustdoc-ui/doc-attr2.stderr b/src/test/rustdoc-ui/doc-attr2.stderr
deleted file mode 100644
index 643107318b9..00000000000
--- a/src/test/rustdoc-ui/doc-attr2.stderr
+++ /dev/null
@@ -1,26 +0,0 @@
-error: `#![doc(test(...)]` is only allowed as a crate-level attribute
-  --> $DIR/doc-attr2.rs:4:7
-   |
-LL | #[doc(test(no_crate_inject))]
-   |       ^^^^^^^^^^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/doc-attr2.rs:2:9
-   |
-LL | #![deny(warnings)]
-   |         ^^^^^^^^
-   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
-   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
-
-error: `#![doc(test(...)]` is only allowed as a crate-level attribute
-  --> $DIR/doc-attr2.rs:9:12
-   |
-LL |     #![doc(test(no_crate_inject))]
-   |            ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/rustdoc-ui/invalid-doc-attr.rs b/src/test/rustdoc-ui/invalid-doc-attr.rs
new file mode 100644
index 00000000000..b8c6f7bf2ed
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-doc-attr.rs
@@ -0,0 +1,26 @@
+#![crate_type = "lib"]
+#![deny(warnings)]
+
+#[doc(test(no_crate_inject))]
+//~^ ERROR can only be applied at the crate level
+//~| WARN is being phased out
+//~| HELP to apply to the crate, use an inner attribute
+//~| SUGGESTION #![doc(test(no_crate_inject))]
+#[doc(inline)]
+//~^ ERROR can only be applied to a `use` item
+//~| WARN is being phased out
+pub fn foo() {}
+
+pub mod bar {
+    #![doc(test(no_crate_inject))]
+    //~^ ERROR can only be applied at the crate level
+    //~| WARN is being phased out
+
+    #[doc(test(no_crate_inject))]
+    //~^ ERROR can only be applied at the crate level
+    //~| WARN is being phased out
+    #[doc(inline)]
+    //~^ ERROR can only be applied to a `use` item
+    //~| WARN is being phased out
+    pub fn baz() {}
+}
diff --git a/src/test/rustdoc-ui/invalid-doc-attr.stderr b/src/test/rustdoc-ui/invalid-doc-attr.stderr
new file mode 100644
index 00000000000..3d2230aa4d2
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-doc-attr.stderr
@@ -0,0 +1,68 @@
+error: this attribute can only be applied at the crate level
+  --> $DIR/invalid-doc-attr.rs:4:7
+   |
+LL | #[doc(test(no_crate_inject))]
+   |       ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/invalid-doc-attr.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
+   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level for more information
+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:9:7
+   |
+LL | #[doc(inline)]
+   |       ^^^^^^ only applicable on `use` items
+...
+LL | pub fn foo() {}
+   | ------------ not a `use` item
+   |
+   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information
+
+error: this attribute can only be applied at the crate level
+  --> $DIR/invalid-doc-attr.rs:15:12
+   |
+LL |     #![doc(test(no_crate_inject))]
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = 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 at the crate level
+  --> $DIR/invalid-doc-attr.rs:19:11
+   |
+LL |     #[doc(test(no_crate_inject))]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = 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:22:11
+   |
+LL |     #[doc(inline)]
+   |           ^^^^^^ only applicable on `use` items
+...
+LL |     pub fn baz() {}
+   |     ------------ not a `use` item
+   |
+   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information
+
+error: aborting due to 5 previous errors
+