about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs9
-rw-r--r--compiler/rustc_passes/messages.ftl11
-rw-r--r--compiler/rustc_passes/src/check_attr.rs49
-rw-r--r--compiler/rustc_passes/src/errors.rs19
-rw-r--r--compiler/rustc_resolve/src/late.rs13
-rw-r--r--src/librustdoc/clean/mod.rs15
-rw-r--r--src/librustdoc/clean/utils.rs12
-rw-r--r--src/librustdoc/html/format.rs10
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs10
-rw-r--r--tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.rs16
-rw-r--r--tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr27
-rw-r--r--tests/rustdoc-ui/lints/invalid-doc-attr.rs15
-rw-r--r--tests/rustdoc-ui/lints/invalid-doc-attr.stderr49
-rw-r--r--tests/rustdoc/intra-doc/nested-use.rs16
-rw-r--r--tests/rustdoc/issue-33178.rs9
-rw-r--r--tests/ui/attributes/invalid-doc-attr.rs32
-rw-r--r--tests/ui/attributes/invalid-doc-attr.stderr78
17 files changed, 246 insertions, 144 deletions
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index ac86110f2bd..8f065dd6b58 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2244,13 +2244,12 @@ pub fn provide(providers: &mut Providers) {
             tcx.resolutions(())
                 .doc_link_resolutions
                 .get(&def_id)
-                .expect("no resolutions for a doc link")
+                .unwrap_or_else(|| span_bug!(tcx.def_span(def_id), "no resolutions for a doc link"))
         },
         doc_link_traits_in_scope: |tcx, def_id| {
-            tcx.resolutions(())
-                .doc_link_traits_in_scope
-                .get(&def_id)
-                .expect("no traits in scope for a doc link")
+            tcx.resolutions(()).doc_link_traits_in_scope.get(&def_id).unwrap_or_else(|| {
+                span_bug!(tcx.def_span(def_id), "no traits in scope for a doc link")
+            })
         },
         traits: |tcx, LocalCrate| {
             let mut traits = Vec::new();
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 0aa3d6265dc..5b3cc5d99cc 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -211,6 +211,17 @@ passes_doc_keyword_not_mod =
 passes_doc_keyword_only_impl =
     `#[doc(keyword = "...")]` should be used on impl blocks
 
+passes_doc_masked_not_extern_crate_self =
+    this attribute cannot be applied to an `extern crate self` item
+    .label = not applicable on `extern crate self` items
+    .extern_crate_self_label = `extern crate self` defined here
+
+passes_doc_masked_only_extern_crate =
+    this attribute can only be applied to an `extern crate` item
+    .label = only applicable on `extern crate` items
+    .not_an_extern_crate_label = not an `extern crate` item
+    .note = read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
+
 passes_doc_test_literal = `#![doc(test(...)]` does not take a literal
 
 passes_doc_test_takes_list =
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 4d7ebe3fefe..cbb030958c6 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -878,6 +878,44 @@ impl CheckAttrVisitor<'_> {
         }
     }
 
+    fn check_doc_masked(
+        &self,
+        attr: &Attribute,
+        meta: &NestedMetaItem,
+        hir_id: HirId,
+        target: Target,
+    ) -> bool {
+        if target != Target::ExternCrate {
+            self.tcx.emit_spanned_lint(
+                INVALID_DOC_ATTRIBUTES,
+                hir_id,
+                meta.span(),
+                errors::DocMaskedOnlyExternCrate {
+                    attr_span: meta.span(),
+                    item_span: (attr.style == AttrStyle::Outer)
+                        .then(|| self.tcx.hir().span(hir_id)),
+                },
+            );
+            return false;
+        }
+
+        if self.tcx.extern_mod_stmt_cnum(hir_id.owner).is_none() {
+            self.tcx.emit_spanned_lint(
+                INVALID_DOC_ATTRIBUTES,
+                hir_id,
+                meta.span(),
+                errors::DocMaskedNotExternCrateSelf {
+                    attr_span: meta.span(),
+                    item_span: (attr.style == AttrStyle::Outer)
+                        .then(|| self.tcx.hir().span(hir_id)),
+                },
+            );
+            return false;
+        }
+
+        true
+    }
+
     /// Checks that an attribute is *not* used at the crate level. Returns `true` if valid.
     fn check_attr_not_crate_level(
         &self,
@@ -1048,6 +1086,17 @@ impl CheckAttrVisitor<'_> {
                             is_valid = false;
                         }
 
+                        sym::masked
+                            if !self.check_doc_masked(
+                                attr,
+                                meta,
+                                hir_id,
+                                target,
+                            ) =>
+                        {
+                            is_valid = false;
+                        }
+
                         // no_default_passes: deprecated
                         // passes: deprecated
                         // plugins: removed, but rustdoc warns about it itself
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index eae13f86049..4f5514372d1 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -267,6 +267,25 @@ pub struct DocInlineOnlyUse {
     pub item_span: Option<Span>,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(passes_doc_masked_only_extern_crate)]
+#[note]
+pub struct DocMaskedOnlyExternCrate {
+    #[label]
+    pub attr_span: Span,
+    #[label(passes_not_an_extern_crate_label)]
+    pub item_span: Option<Span>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(passes_doc_masked_not_extern_crate_self)]
+pub struct DocMaskedNotExternCrateSelf {
+    #[label]
+    pub attr_span: Span,
+    #[label(passes_extern_crate_self_label)]
+    pub item_span: Option<Span>,
+}
+
 #[derive(Diagnostic)]
 #[diag(passes_doc_attr_not_crate_level)]
 pub struct DocAttrNotCrateLevel<'a> {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index be7ef92d175..aab71494fd3 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -549,6 +549,7 @@ enum MaybeExported<'a> {
     Ok(NodeId),
     Impl(Option<DefId>),
     ImplItem(Result<DefId, &'a Visibility>),
+    NestedUse(&'a Visibility),
 }
 
 impl MaybeExported<'_> {
@@ -559,7 +560,9 @@ impl MaybeExported<'_> {
                 trait_def_id.as_local()
             }
             MaybeExported::Impl(None) => return true,
-            MaybeExported::ImplItem(Err(vis)) => return vis.kind.is_pub(),
+            MaybeExported::ImplItem(Err(vis)) | MaybeExported::NestedUse(vis) => {
+                return vis.kind.is_pub();
+            }
         };
         def_id.map_or(true, |def_id| r.effective_visibilities.is_exported(def_id))
     }
@@ -2284,7 +2287,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
     fn resolve_item(&mut self, item: &'ast Item) {
         let mod_inner_docs =
             matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs);
-        if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..)) {
+        if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..) | ItemKind::Use(..)) {
             self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
         }
 
@@ -2428,6 +2431,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             }
 
             ItemKind::Use(ref use_tree) => {
+                let maybe_exported = match use_tree.kind {
+                    UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id),
+                    UseTreeKind::Nested(_) => MaybeExported::NestedUse(&item.vis),
+                };
+                self.resolve_doc_links(&item.attrs, maybe_exported);
+
                 self.future_proof_import(use_tree);
             }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index d14953f1bb7..440874df14c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2643,15 +2643,12 @@ fn clean_extern_crate<'tcx>(
         }
     }
 
-    // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
-    vec![Item {
-        name: Some(name),
-        attrs: Box::new(Attributes::from_ast(attrs)),
-        item_id: crate_def_id.into(),
-        kind: Box::new(ExternCrateItem { src: orig_name }),
-        cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
-        inline_stmt_id: Some(krate_owner_def_id),
-    }]
+    vec![Item::from_def_id_and_parts(
+        krate_owner_def_id,
+        Some(name),
+        ExternCrateItem { src: orig_name },
+        cx,
+    )]
 }
 
 fn clean_use_statement<'tcx>(
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index df9da9e7c7f..5c8db3b8774 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -38,11 +38,15 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
             for it in &module.items {
                 // `compiler_builtins` should be masked too, but we can't apply
                 // `#[doc(masked)]` to the injected `extern crate` because it's unstable.
-                if it.is_extern_crate()
-                    && (it.attrs.has_doc_flag(sym::masked)
-                        || cx.tcx.is_compiler_builtins(it.item_id.krate()))
-                {
+                if cx.tcx.is_compiler_builtins(it.item_id.krate()) {
                     cx.cache.masked_crates.insert(it.item_id.krate());
+                } else if it.is_extern_crate()
+                    && it.attrs.has_doc_flag(sym::masked)
+                    && let Some(def_id) = it.item_id.as_def_id()
+                    && let Some(local_def_id) = def_id.as_local()
+                    && let Some(cnum) = cx.tcx.extern_mod_stmt_cnum(local_def_id)
+                {
+                    cx.cache.masked_crates.insert(cnum);
                 }
             }
         }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 1099c68b004..f60f40267d6 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -18,7 +18,7 @@ use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_metadata::creader::{CStore, LoadedMacro};
 use rustc_middle::ty;
 use rustc_middle::ty::TyCtxt;
@@ -662,6 +662,14 @@ pub(crate) fn href_with_root_path(
             // documented on their parent's page
             tcx.parent(did)
         }
+        DefKind::ExternCrate => {
+            // Link to the crate itself, not the `extern crate` item.
+            if let Some(local_did) = did.as_local() {
+                tcx.extern_mod_stmt_cnum(local_did).unwrap_or(LOCAL_CRATE).as_def_id()
+            } else {
+                did
+            }
+        }
         _ => did,
     };
     let cache = cx.cache();
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 91f3729bfa2..4de30e4ed9d 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -14,7 +14,7 @@ use rustc_hir::def::{DefKind, Namespace, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
 use rustc_hir::Mutability;
 use rustc_middle::ty::{Ty, TyCtxt};
-use rustc_middle::{bug, ty};
+use rustc_middle::{bug, span_bug, ty};
 use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
 use rustc_resolve::rustdoc::{strip_generics_from_path, MalformedGenerics};
 use rustc_session::lint::Lint;
@@ -402,7 +402,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             // `doc_link_resolutions` is missing a `path_str`, that means that there are valid links
             // that are being missed. To fix the ICE, change
             // `rustc_resolve::rustdoc::attrs_to_preprocessed_links` to cache the link.
-            .unwrap_or_else(|| panic!("no resolution for {:?} {:?} {:?}", path_str, ns, module_id))
+            .unwrap_or_else(|| {
+                span_bug!(
+                    self.cx.tcx.def_span(item_id),
+                    "no resolution for {path_str:?} {ns:?} {module_id:?}",
+                )
+            })
             .and_then(|res| res.try_into().ok())
             .or_else(|| resolve_primitive(path_str, ns));
         debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
@@ -963,6 +968,7 @@ fn preprocessed_markdown_links(s: &str) -> Vec<PreprocessedMarkdownLink> {
 }
 
 impl LinkCollector<'_, '_> {
+    #[instrument(level = "debug", skip_all)]
     fn resolve_links(&mut self, item: &Item) {
         if !self.cx.render_options.document_private
             && let Some(def_id) = item.item_id.as_def_id()
diff --git a/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.rs b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.rs
new file mode 100644
index 00000000000..f3f044f6105
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.rs
@@ -0,0 +1,16 @@
+// Test that we don't ICE with broken links that don't show up in the docs.
+
+// check-pass
+// edition: 2021
+
+/// [1]
+//~^ WARN unresolved link to `1`
+//~| WARN unresolved link to `1`
+pub use {std, core};
+
+/// [2]
+pub use {};
+
+/// [3]
+//~^ WARN unresolved link to `3`
+pub extern crate alloc;
diff --git a/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr
new file mode 100644
index 00000000000..83e0d3962ca
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr
@@ -0,0 +1,27 @@
+warning: unresolved link to `3`
+  --> $DIR/broken-link-in-unused-doc-string.rs:14:6
+   |
+LL | /// [3]
+   |      ^ no item named `3` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+   = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+
+warning: unresolved link to `1`
+  --> $DIR/broken-link-in-unused-doc-string.rs:6:6
+   |
+LL | /// [1]
+   |      ^ no item named `1` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `1`
+  --> $DIR/broken-link-in-unused-doc-string.rs:6:6
+   |
+LL | /// [1]
+   |      ^ no item named `1` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: 3 warnings emitted
+
diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.rs b/tests/rustdoc-ui/lints/invalid-doc-attr.rs
index c231e43b35c..16b12cca5a0 100644
--- a/tests/rustdoc-ui/lints/invalid-doc-attr.rs
+++ b/tests/rustdoc-ui/lints/invalid-doc-attr.rs
@@ -1,5 +1,10 @@
 #![crate_type = "lib"]
 #![deny(warnings)]
+#![feature(doc_masked)]
+
+#![doc(masked)]
+//~^ ERROR this attribute can only be applied to an `extern crate` item
+//~| WARN is being phased out
 
 #[doc(test(no_crate_inject))]
 //~^ ERROR can only be applied at the crate level
@@ -30,3 +35,13 @@ pub mod bar {
 //~^^ ERROR conflicting doc inlining attributes
 //~|  HELP remove one of the conflicting attributes
 pub use bar::baz;
+
+#[doc(masked)]
+//~^ ERROR this attribute can only be applied to an `extern crate` item
+//~| WARN is being phased out
+pub struct Masked;
+
+#[doc(masked)]
+//~^ ERROR this attribute cannot be applied to an `extern crate self` item
+//~| WARN is being phased out
+pub extern crate self as reexport;
diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
index b23b8ded867..82ea33e1d89 100644
--- a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
+++ b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
@@ -1,5 +1,5 @@
 error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:4:7
+  --> $DIR/invalid-doc-attr.rs:9:7
    |
 LL | #[doc(test(no_crate_inject))]
    |       ^^^^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL | #![doc(test(no_crate_inject))]
    |  +
 
 error: this attribute can only be applied to a `use` item
-  --> $DIR/invalid-doc-attr.rs:9:7
+  --> $DIR/invalid-doc-attr.rs:14:7
    |
 LL | #[doc(inline)]
    |       ^^^^^^ only applicable on `use` items
@@ -32,7 +32,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:15:12
+  --> $DIR/invalid-doc-attr.rs:20:12
    |
 LL |     #![doc(test(no_crate_inject))]
    |            ^^^^^^^^^^^^^^^^^^^^^
@@ -42,7 +42,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:28:7
+  --> $DIR/invalid-doc-attr.rs:33:7
    |
 LL | #[doc(inline)]
    |       ^^^^^^ this attribute...
@@ -51,8 +51,43 @@ 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:39:7
+   |
+LL | #[doc(masked)]
+   |       ^^^^^^ only applicable on `extern crate` items
+...
+LL | pub struct Masked;
+   | ----------------- not an `extern crate` 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/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:44:7
+   |
+LL | #[doc(masked)]
+   |       ^^^^^^ not applicable on `extern crate self` items
+...
+LL | pub extern crate self as reexport;
+   | --------------------------------- `extern crate self` defined here
+   |
+   = 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: this attribute can only be applied to an `extern crate` item
+  --> $DIR/invalid-doc-attr.rs:5:8
+   |
+LL | #![doc(masked)]
+   |        ^^^^^^ only applicable on `extern crate` items
+   |
+   = 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/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:19:11
+  --> $DIR/invalid-doc-attr.rs:24:11
    |
 LL |     #[doc(test(no_crate_inject))]
    |           ^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +97,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:22:11
+  --> $DIR/invalid-doc-attr.rs:27:11
    |
 LL |     #[doc(inline)]
    |           ^^^^^^ only applicable on `use` items
@@ -74,5 +109,5 @@ LL |     pub fn baz() {}
    = 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#inline-and-no_inline> for more information
 
-error: aborting due to 6 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/tests/rustdoc/intra-doc/nested-use.rs b/tests/rustdoc/intra-doc/nested-use.rs
new file mode 100644
index 00000000000..19ebfff1bce
--- /dev/null
+++ b/tests/rustdoc/intra-doc/nested-use.rs
@@ -0,0 +1,16 @@
+// Regression test for issue #113896: Intra-doc links on nested use items.
+
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @has - '//a[@href="struct.Foo.html"]' 'Foo'
+// @has - '//a[@href="struct.Bar.html"]' 'Bar'
+
+/// [`Foo`]
+pub use m::{Foo, Bar};
+
+mod m {
+    /// [`Bar`]
+    pub struct Foo;
+    pub struct Bar;
+}
diff --git a/tests/rustdoc/issue-33178.rs b/tests/rustdoc/issue-33178.rs
index 1f45fe72391..ed643f5ae11 100644
--- a/tests/rustdoc/issue-33178.rs
+++ b/tests/rustdoc/issue-33178.rs
@@ -4,10 +4,11 @@
 // ignore-cross-compile
 
 // @has issue_33178/index.html
-// @has - //a/@title empty
-// @has - //a/@href ../empty/index.html
+// @has - '//a[@title="mod empty"][@href="../empty/index.html"]' empty
 pub extern crate empty;
 
-// @has - //a/@title variant_struct
-// @has - //a/@href ../variant_struct/index.html
+// @has - '//a[@title="mod variant_struct"][@href="../variant_struct/index.html"]' variant_struct
 pub extern crate variant_struct as foo;
+
+// @has - '//a[@title="mod issue_33178"][@href="index.html"]' self
+pub extern crate self as bar;
diff --git a/tests/ui/attributes/invalid-doc-attr.rs b/tests/ui/attributes/invalid-doc-attr.rs
deleted file mode 100644
index c231e43b35c..00000000000
--- a/tests/ui/attributes/invalid-doc-attr.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-#![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(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() {}
-}
-
-#[doc(inline)]
-#[doc(no_inline)]
-//~^^ ERROR conflicting doc inlining attributes
-//~|  HELP remove one of the conflicting attributes
-pub use bar::baz;
diff --git a/tests/ui/attributes/invalid-doc-attr.stderr b/tests/ui/attributes/invalid-doc-attr.stderr
deleted file mode 100644
index b23b8ded867..00000000000
--- a/tests/ui/attributes/invalid-doc-attr.stderr
+++ /dev/null
@@ -1,78 +0,0 @@
-error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:4:7
-   |
-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
-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)]`
-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#inline-and-no_inline> 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: conflicting doc inlining attributes
-  --> $DIR/invalid-doc-attr.rs:28:7
-   |
-LL | #[doc(inline)]
-   |       ^^^^^^ this attribute...
-LL | #[doc(no_inline)]
-   |       ^^^^^^^^^ ...conflicts with this attribute
-   |
-   = help: remove one of the conflicting attributes
-
-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#inline-and-no_inline> for more information
-
-error: aborting due to 6 previous errors
-