Auto merge of #81015 - jyn514:feature-gate-ptr, r=camelid

Feature-gate `pointer` and `reference` in intra-doc links

r? `@camelid`

Addresses (but does not close) https://github.com/rust-lang/rust/issues/80896.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 3b54ffb..b9d1597 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -629,6 +629,8 @@
     /// Allows references to types with interior mutability within constants
     (active, const_refs_to_cell, "1.51.0", Some(80384), None),
 
+    /// Allows using `pointer` and `reference` in intra-doc links
+    (active, intra_doc_pointers, "1.51.0", Some(80896), None),
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 63f95a3..7b90e5b 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -622,6 +622,7 @@
         intel,
         into_iter,
         into_result,
+        intra_doc_pointers,
         intrinsics,
         irrefutable_let_patterns,
         isa_attribute,
diff --git a/src/doc/unstable-book/src/language-features/intra-doc-pointers.md b/src/doc/unstable-book/src/language-features/intra-doc-pointers.md
new file mode 100644
index 0000000..fbc83f4
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/intra-doc-pointers.md
@@ -0,0 +1,15 @@
+# `intra-doc-pointers`
+
+The tracking issue for this feature is: [#80896]
+
+[#80896]: https://github.com/rust-lang/rust/issues/80896
+
+------------------------
+
+Rustdoc does not currently allow disambiguating between `*const` and `*mut`, and
+raw pointers in intra-doc links are unstable until it does.
+
+```rust
+#![feature(intra_doc_pointers)]
+//! [pointer::add]
+```
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 2809840..2694450 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -20,8 +20,7 @@
     Lint,
 };
 use rustc_span::hygiene::{MacroKind, SyntaxContext};
-use rustc_span::symbol::Ident;
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::DUMMY_SP;
 use smallvec::{smallvec, SmallVec};
 
@@ -1195,7 +1194,7 @@
         };
 
         match res {
-            Res::Primitive(_) => {
+            Res::Primitive(prim) => {
                 if let Some((kind, id)) = self.kind_side_channel.take() {
                     // We're actually resolving an associated item of a primitive, so we need to
                     // verify the disambiguator (if any) matches the type of the associated item.
@@ -1206,6 +1205,29 @@
                     // valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677
                     // for discussion on the matter.
                     verify(kind, id)?;
+
+                    if prim == PrimitiveType::RawPointer
+                        && !self.cx.tcx.features().intra_doc_pointers
+                    {
+                        let span = super::source_span_for_markdown_range(
+                            cx,
+                            dox,
+                            &ori_link.range,
+                            &item.attrs,
+                        )
+                        .unwrap_or_else(|| {
+                            span_of_attrs(&item.attrs).unwrap_or(item.source.span())
+                        });
+
+                        rustc_session::parse::feature_err(
+                            &self.cx.tcx.sess.parse_sess,
+                            sym::intra_doc_pointers,
+                            span,
+                            "linking to associated items of raw pointers is experimental",
+                        )
+                        .note("rustdoc does not allow disambiguating between `*const` and `*mut`, and pointers are unstable until it does")
+                        .emit();
+                    }
                 } else {
                     match disambiguator {
                         Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {}
@@ -1215,6 +1237,7 @@
                         }
                     }
                 }
+
                 Some(ItemLink { link: ori_link.link, link_text, did: None, fragment })
             }
             Res::Def(kind, id) => {
diff --git a/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.rs b/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.rs
new file mode 100644
index 0000000..3cfac94
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.rs
@@ -0,0 +1,6 @@
+//! [pointer::add]
+//~^ ERROR: experimental
+//! [pointer::wrapping_add]
+//~^ ERROR: experimental
+//! [pointer] // This is explicitly allowed
+//! [reference] // This is explicitly allowed
diff --git a/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.stderr b/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.stderr
new file mode 100644
index 0000000..2c946ed
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.stderr
@@ -0,0 +1,23 @@
+error[E0658]: linking to associated items of raw pointers is experimental
+  --> $DIR/feature-gate-intra-doc-pointers.rs:1:6
+   |
+LL | //! [pointer::add]
+   |      ^^^^^^^^^^^^
+   |
+   = note: see issue #80896 <https://github.com/rust-lang/rust/issues/80896> for more information
+   = help: add `#![feature(intra_doc_pointers)]` to the crate attributes to enable
+   = note: rustdoc does not allow disambiguating between `*const` and `*mut`, and pointers are unstable until it does
+
+error[E0658]: linking to associated items of raw pointers is experimental
+  --> $DIR/feature-gate-intra-doc-pointers.rs:3:6
+   |
+LL | //! [pointer::wrapping_add]
+   |      ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #80896 <https://github.com/rust-lang/rust/issues/80896> for more information
+   = help: add `#![feature(intra_doc_pointers)]` to the crate attributes to enable
+   = note: rustdoc does not allow disambiguating between `*const` and `*mut`, and pointers are unstable until it does
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs b/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs
index 114502b0..6785c4c 100644
--- a/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs
+++ b/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs
@@ -1,4 +1,5 @@
 #![deny(broken_intra_doc_links)]
+#![feature(intra_doc_pointers)]
 // These are links that could reasonably expected to work, but don't.
 
 // `[]` isn't supported because it had too many false positives.
diff --git a/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr b/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr
index ea831e6..1747585 100644
--- a/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr
+++ b/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr
@@ -1,5 +1,5 @@
 error: unresolved link to `T`
-  --> $DIR/non-path-primitives.rs:11:7
+  --> $DIR/non-path-primitives.rs:12:7
    |
 LL | //! [[T]::rotate_left]
    |       ^ no item named `T` in scope
@@ -12,7 +12,7 @@
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: unresolved link to `Z`
-  --> $DIR/non-path-primitives.rs:13:5
+  --> $DIR/non-path-primitives.rs:14:5
    |
 LL | //![Z]([T; N]::map)
    |     ^ no item named `Z` in scope
@@ -20,7 +20,7 @@
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: unresolved link to `Z`
-  --> $DIR/non-path-primitives.rs:16:6
+  --> $DIR/non-path-primitives.rs:17:6
    |
 LL | //! [Z][]
    |      ^ no item named `Z` in scope
@@ -28,7 +28,7 @@
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: unresolved link to `Z`
-  --> $DIR/non-path-primitives.rs:18:6
+  --> $DIR/non-path-primitives.rs:19:6
    |
 LL | //! [Z]: [T; N]::map
    |      ^ no item named `Z` in scope
@@ -36,31 +36,31 @@
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: unresolved link to `unit::eq`
-  --> $DIR/non-path-primitives.rs:27:6
+  --> $DIR/non-path-primitives.rs:28:6
    |
 LL | //! [unit::eq]
    |      ^^^^^^^^ the builtin type `unit` has no associated item named `eq`
 
 error: unresolved link to `tuple::eq`
-  --> $DIR/non-path-primitives.rs:28:6
+  --> $DIR/non-path-primitives.rs:29:6
    |
 LL | //! [tuple::eq]
    |      ^^^^^^^^^ the builtin type `tuple` has no associated item named `eq`
 
 error: unresolved link to `fn::eq`
-  --> $DIR/non-path-primitives.rs:29:6
+  --> $DIR/non-path-primitives.rs:30:6
    |
 LL | //! [fn::eq]
    |      ^^^^^^ the builtin type `fn` has no associated item named `eq`
 
 error: unresolved link to `never::eq`
-  --> $DIR/non-path-primitives.rs:30:6
+  --> $DIR/non-path-primitives.rs:31:6
    |
 LL | //! [never::eq]
    |      ^^^^^^^^^ the builtin type `never` has no associated item named `eq`
 
 error: unresolved link to `reference::deref`
-  --> $DIR/non-path-primitives.rs:34:6
+  --> $DIR/non-path-primitives.rs:35:6
    |
 LL | //! [reference::deref]
    |      ^^^^^^^^^^^^^^^^ the builtin type `reference` has no associated item named `deref`
diff --git a/src/test/rustdoc/intra-doc/non-path-primitives.rs b/src/test/rustdoc/intra-doc/non-path-primitives.rs
index 2c7e7b5..48c667e 100644
--- a/src/test/rustdoc/intra-doc/non-path-primitives.rs
+++ b/src/test/rustdoc/intra-doc/non-path-primitives.rs
@@ -1,5 +1,6 @@
 // ignore-tidy-linelength
 #![crate_name = "foo"]
+#![feature(intra_doc_pointers)]
 #![deny(broken_intra_doc_links)]
 
 // @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.rotate_left"]' 'slice::rotate_left'
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 384a291..d3a4454 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -85,7 +85,11 @@
     assert!(!lib_features.is_empty());
 
     super::walk_many(
-        &[&src_path.join("test/ui"), &src_path.join("test/ui-fulldeps")],
+        &[
+            &src_path.join("test/ui"),
+            &src_path.join("test/ui-fulldeps"),
+            &src_path.join("test/rustdoc-ui"),
+        ],
         &mut |path| super::filter_dirs(path),
         &mut |entry, contents| {
             let file = entry.path();