From fe540ae1bb13d3838d1d5c78b546d96b4d44797e Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Sat, 1 May 2021 21:39:59 -0700
Subject: [PATCH 1/2] RustDoc: Fix bounds linking trait.Foo instead of
 traitalias.Foo

---
 src/librustdoc/clean/inline.rs          |  2 +-
 src/librustdoc/clean/mod.rs             |  7 +++-
 src/librustdoc/formats/cache.rs         | 46 +++++++++++++++++--------
 src/test/rustdoc/trait-alias-mention.rs |  9 +++++
 src/test/rustdoc/trait_alias.rs         |  2 ++
 5 files changed, 50 insertions(+), 16 deletions(-)
 create mode 100644 src/test/rustdoc/trait-alias-mention.rs

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 3e89c1ac4c514..4660ac17b279f 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -188,7 +188,7 @@ crate fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemType)
     if did.is_local() {
         cx.cache.exact_paths.insert(did, fqn);
     } else {
-        cx.cache.external_paths.insert(did, (fqn, ItemType::from(kind)));
+        cx.cache.external_paths.insert(did, (fqn, kind));
     }
 }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 6563f398edb6f..2c6bade11fb95 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -157,7 +157,12 @@ impl Clean<GenericBound> for hir::GenericBound<'_> {
 impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
         let (trait_ref, bounds) = *self;
-        inline::record_extern_fqn(cx, trait_ref.def_id, ItemType::Trait);
+        let kind = match cx.tcx.def_kind(trait_ref.def_id) {
+            DefKind::Trait => ItemType::Trait,
+            DefKind::TraitAlias => ItemType::TraitAlias,
+            other => bug!("`TraitRef` had unexpected kind {:?}", other),
+        };
+        inline::record_extern_fqn(cx, trait_ref.def_id, kind);
         let path = external_path(
             cx,
             cx.tcx.item_name(trait_ref.def_id),
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 8f8bca64e1497..a023400a436fd 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -340,6 +340,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
             | clean::EnumItem(..)
             | clean::TypedefItem(..)
             | clean::TraitItem(..)
+            | clean::TraitAliasItem(..)
             | clean::FunctionItem(..)
             | clean::ModuleItem(..)
             | clean::ForeignFunctionItem(..)
@@ -350,26 +351,43 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
             | clean::ForeignTypeItem
             | clean::MacroItem(..)
             | clean::ProcMacroItem(..)
-            | clean::VariantItem(..)
-                if !self.cache.stripped_mod =>
-            {
-                // Re-exported items mean that the same id can show up twice
-                // in the rustdoc ast that we're looking at. We know,
-                // however, that a re-exported item doesn't show up in the
-                // `public_items` map, so we can skip inserting into the
-                // paths map if there was already an entry present and we're
-                // not a public item.
-                if !self.cache.paths.contains_key(&item.def_id)
-                    || self.cache.access_levels.is_public(item.def_id)
-                {
-                    self.cache.paths.insert(item.def_id, (self.cache.stack.clone(), item.type_()));
+            | clean::VariantItem(..) => {
+                if !self.cache.stripped_mod {
+                    // Re-exported items mean that the same id can show up twice
+                    // in the rustdoc ast that we're looking at. We know,
+                    // however, that a re-exported item doesn't show up in the
+                    // `public_items` map, so we can skip inserting into the
+                    // paths map if there was already an entry present and we're
+                    // not a public item.
+                    if !self.cache.paths.contains_key(&item.def_id)
+                        || self.cache.access_levels.is_public(item.def_id)
+                    {
+                        self.cache
+                            .paths
+                            .insert(item.def_id, (self.cache.stack.clone(), item.type_()));
+                    }
                 }
             }
             clean::PrimitiveItem(..) => {
                 self.cache.paths.insert(item.def_id, (self.cache.stack.clone(), item.type_()));
             }
 
-            _ => {}
+            clean::ExternCrateItem { .. }
+            | clean::ImportItem(..)
+            | clean::OpaqueTyItem(..)
+            | clean::ImplItem(..)
+            | clean::TyMethodItem(..)
+            | clean::MethodItem(..)
+            | clean::StructFieldItem(..)
+            | clean::AssocConstItem(..)
+            | clean::AssocTypeItem(..)
+            | clean::StrippedItem(..)
+            | clean::KeywordItem(..) => {
+                // FIXME: Do these need handling?
+                // The person writing this comment doesn't know.
+                // So would rather leave them to an expert,
+                // as at least the list is better than `_ => {}`.
+            }
         }
 
         // Maintain the parent stack
diff --git a/src/test/rustdoc/trait-alias-mention.rs b/src/test/rustdoc/trait-alias-mention.rs
new file mode 100644
index 0000000000000..dea72cdb5fbbd
--- /dev/null
+++ b/src/test/rustdoc/trait-alias-mention.rs
@@ -0,0 +1,9 @@
+#![feature(trait_alias)]
+#![feature(ptr_metadata)]
+
+#![crate_name = "foo"]
+
+// @has foo/fn.this_never_panics.html '//a[@title="traitalias core::ptr::metadata::Thin"]' 'Thin'
+pub fn this_never_panics<T: std::ptr::Thin>() {
+    assert_eq!(std::mem::size_of::<&T>(), std::mem::size_of::<usize>())
+}
diff --git a/src/test/rustdoc/trait_alias.rs b/src/test/rustdoc/trait_alias.rs
index 98b8d879ac078..6cd4a1a0afa08 100644
--- a/src/test/rustdoc/trait_alias.rs
+++ b/src/test/rustdoc/trait_alias.rs
@@ -19,3 +19,5 @@ pub trait CopyAlias = Copy;
 pub trait Alias2 = Copy + Debug;
 // @has foo/traitalias.Foo.html '//section[@id="main"]/pre' 'trait Foo<T> = Into<T> + Debug;'
 pub trait Foo<T> = Into<T> + Debug;
+// @has foo/fn.bar.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
+pub fn bar<T>() where T: Alias2 {}

From 40ffa942444b84336b0d03f3004d7eb9ca36f8ad Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Sun, 2 May 2021 12:11:13 -0700
Subject: [PATCH 2/2] PR feedback

---
 src/librustdoc/clean/mod.rs                       | 15 +++++++++------
 src/test/rustdoc/auxiliary/trait-alias-mention.rs |  3 +++
 src/test/rustdoc/trait-alias-mention.rs           | 11 ++++++-----
 3 files changed, 18 insertions(+), 11 deletions(-)
 create mode 100644 src/test/rustdoc/auxiliary/trait-alias-mention.rs

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2c6bade11fb95..f71489f32311f 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -17,11 +17,11 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
-use rustc_middle::bug;
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
 use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_mir::const_eval::{is_const_fn, is_unstable_const_fn};
 use rustc_span::hygiene::{AstPass, MacroKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -157,11 +157,14 @@ impl Clean<GenericBound> for hir::GenericBound<'_> {
 impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
         let (trait_ref, bounds) = *self;
-        let kind = match cx.tcx.def_kind(trait_ref.def_id) {
-            DefKind::Trait => ItemType::Trait,
-            DefKind::TraitAlias => ItemType::TraitAlias,
-            other => bug!("`TraitRef` had unexpected kind {:?}", other),
-        };
+        let kind = cx.tcx.def_kind(trait_ref.def_id).into();
+        if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
+            span_bug!(
+                cx.tcx.def_span(trait_ref.def_id),
+                "`TraitRef` had unexpected kind {:?}",
+                kind
+            );
+        }
         inline::record_extern_fqn(cx, trait_ref.def_id, kind);
         let path = external_path(
             cx,
diff --git a/src/test/rustdoc/auxiliary/trait-alias-mention.rs b/src/test/rustdoc/auxiliary/trait-alias-mention.rs
new file mode 100644
index 0000000000000..6df06c87a09d5
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/trait-alias-mention.rs
@@ -0,0 +1,3 @@
+#![feature(trait_alias)]
+
+pub trait SomeAlias = std::fmt::Debug + std::marker::Copy;
diff --git a/src/test/rustdoc/trait-alias-mention.rs b/src/test/rustdoc/trait-alias-mention.rs
index dea72cdb5fbbd..6da0dc68785c5 100644
--- a/src/test/rustdoc/trait-alias-mention.rs
+++ b/src/test/rustdoc/trait-alias-mention.rs
@@ -1,9 +1,10 @@
-#![feature(trait_alias)]
-#![feature(ptr_metadata)]
+// aux-build:trait-alias-mention.rs
+// build-aux-docs
 
 #![crate_name = "foo"]
 
-// @has foo/fn.this_never_panics.html '//a[@title="traitalias core::ptr::metadata::Thin"]' 'Thin'
-pub fn this_never_panics<T: std::ptr::Thin>() {
-    assert_eq!(std::mem::size_of::<&T>(), std::mem::size_of::<usize>())
+extern crate trait_alias_mention;
+
+// @has foo/fn.mention_alias_in_bounds.html '//a[@href="../trait_alias_mention/traitalias.SomeAlias.html"]' 'SomeAlias'
+pub fn mention_alias_in_bounds<T: trait_alias_mention::SomeAlias>() {
 }