about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-01-04 10:32:28 +0000
committerbors <bors@rust-lang.org>2021-01-04 10:32:28 +0000
commit6163bfdcce6404c5d61d6ab441bf49a831082194 (patch)
treedf84df6a3ff736da63f3c06a84595b7e310cffc4
parent887398ff688e2e3cf8a95e588d0b51420e08fb6b (diff)
parent24ef94593c84084be03e6461b702178523767cf7 (diff)
downloadrust-6163bfdcce6404c5d61d6ab441bf49a831082194.tar.gz
rust-6163bfdcce6404c5d61d6ab441bf49a831082194.zip
Auto merge of #80661 - jyn514:duplicate-types, r=GuillaumeGomez
Cleanup rustdoc handling of associated types

This is best reviewed a commit at a time. No particular reason for these changes, they just stood out as I was reviewing https://github.com/rust-lang/rust/pull/80653 and thinking about https://github.com/rust-lang/rust/issues/80379. The new test case worked before, it just wasn't tested.

r? `@GuillaumeGomez`
-rw-r--r--src/librustdoc/clean/inline.rs20
-rw-r--r--src/librustdoc/clean/mod.rs31
-rw-r--r--src/librustdoc/clean/types.rs11
-rw-r--r--src/librustdoc/html/render/mod.rs3
-rw-r--r--src/test/rustdoc/deref-typedef.rs19
5 files changed, 53 insertions, 31 deletions
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index c168c56d30d..ed972cc16e9 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -261,26 +261,12 @@ fn build_union(cx: &DocContext<'_>, did: DefId) -> clean::Union {
 
 fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef {
     let predicates = cx.tcx.explicit_predicates_of(did);
+    let type_ = cx.tcx.type_of(did).clean(cx);
 
     clean::Typedef {
-        type_: cx.tcx.type_of(did).clean(cx),
+        type_,
         generics: (cx.tcx.generics_of(did), predicates).clean(cx),
-        item_type: build_type_alias_type(cx, did),
-    }
-}
-
-fn build_type_alias_type(cx: &DocContext<'_>, did: DefId) -> Option<clean::Type> {
-    let type_ = cx.tcx.type_of(did).clean(cx);
-    type_.def_id().and_then(|did| build_ty(cx, did))
-}
-
-crate fn build_ty(cx: &DocContext<'_>, did: DefId) -> Option<clean::Type> {
-    match cx.tcx.def_kind(did) {
-        DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Const | DefKind::Static => {
-            Some(cx.tcx.type_of(did).clean(cx))
-        }
-        DefKind::TyAlias => build_type_alias_type(cx, did),
-        _ => None,
+        item_type: None,
     }
 }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 14902c318c9..0b979120ff9 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1119,10 +1119,17 @@ impl Clean<Item> for hir::ImplItem<'_> {
                     }
                     MethodItem(m, Some(self.defaultness))
                 }
-                hir::ImplItemKind::TyAlias(ref ty) => {
-                    let type_ = ty.clean(cx);
-                    let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
-                    TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true)
+                hir::ImplItemKind::TyAlias(ref hir_ty) => {
+                    let type_ = hir_ty.clean(cx);
+                    let item_type = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
+                    TypedefItem(
+                        Typedef {
+                            type_,
+                            generics: Generics::default(),
+                            item_type: Some(item_type),
+                        },
+                        true,
+                    )
                 }
             };
             Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx)
@@ -1268,13 +1275,13 @@ impl Clean<Item> for ty::AssocItem {
 
                     AssocTypeItem(bounds, ty.clean(cx))
                 } else {
+                    // FIXME: when could this happen? ASsociated items in inherent impls?
                     let type_ = cx.tcx.type_of(self.def_id).clean(cx);
-                    let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
                     TypedefItem(
                         Typedef {
                             type_,
                             generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
-                            item_type,
+                            item_type: None,
                         },
                         true,
                     )
@@ -1987,11 +1994,15 @@ impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
                     bounds: ty.bounds.clean(cx),
                     generics: ty.generics.clean(cx),
                 }),
-                ItemKind::TyAlias(ty, ref generics) => {
-                    let rustdoc_ty = ty.clean(cx);
-                    let item_type = rustdoc_ty.def_id().and_then(|did| inline::build_ty(cx, did));
+                ItemKind::TyAlias(hir_ty, ref generics) => {
+                    let rustdoc_ty = hir_ty.clean(cx);
+                    let ty = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
                     TypedefItem(
-                        Typedef { type_: rustdoc_ty, generics: generics.clean(cx), item_type },
+                        Typedef {
+                            type_: rustdoc_ty,
+                            generics: generics.clean(cx),
+                            item_type: Some(ty),
+                        },
                         false,
                     )
                 }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 8d5ef1ed28c..cc31461646c 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -332,6 +332,10 @@ crate enum ItemKind {
     ProcMacroItem(ProcMacro),
     PrimitiveItem(PrimitiveType),
     AssocConstItem(Type, Option<String>),
+    /// An associated item in a trait or trait impl.
+    ///
+    /// The bounds may be non-empty if there is a `where` clause.
+    /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
     AssocTypeItem(Vec<GenericBound>, Option<Type>),
     /// An item that has been stripped by a rustdoc pass
     StrippedItem(Box<ItemKind>),
@@ -1804,7 +1808,12 @@ crate struct PathSegment {
 crate struct Typedef {
     crate type_: Type,
     crate generics: Generics,
-    // Type of target item.
+    /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
+    /// alias instead of the final type. This will always have the final type, regardless of whether
+    /// `type_` came from HIR or from metadata.
+    ///
+    /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
+    /// final type).
     crate item_type: Option<Type>,
 }
 
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 1c713df9276..f7eb136a754 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -4303,6 +4303,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
                 .filter(|i| i.inner_impl().trait_.is_some())
                 .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did)
             {
+                debug!("found Deref: {:?}", impl_);
                 if let Some((target, real_target)) =
                     impl_.inner_impl().items.iter().find_map(|item| match *item.kind {
                         clean::TypedefItem(ref t, true) => Some(match *t {
@@ -4312,6 +4313,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
                         _ => None,
                     })
                 {
+                    debug!("found target, real_target: {:?} {:?}", target, real_target);
                     let deref_mut = v
                         .iter()
                         .filter(|i| i.inner_impl().trait_.is_some())
@@ -4325,6 +4327,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
                         })
                         .and_then(|did| c.impls.get(&did));
                     if let Some(impls) = inner_impl {
+                        debug!("found inner_impl: {:?}", impls);
                         out.push_str("<a class=\"sidebar-title\" href=\"#deref-methods\">");
                         out.push_str(&format!(
                             "Methods from {}&lt;Target={}&gt;",
diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs
index 770f8d7289c..e2dac2cf417 100644
--- a/src/test/rustdoc/deref-typedef.rs
+++ b/src/test/rustdoc/deref-typedef.rs
@@ -1,18 +1,27 @@
 #![crate_name = "foo"]
 
 // @has 'foo/struct.Bar.html'
-// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooC>'
+// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooJ>'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
-// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref<Target=FooC>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
+// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref<Target=FooJ>'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_j"]' 'foo_j'
 
 pub struct FooA;
 pub type FooB = FooA;
 pub type FooC = FooB;
+pub type FooD = FooC;
+pub type FooE = FooD;
+pub type FooF = FooE;
+pub type FooG = FooF;
+pub type FooH = FooG;
+pub type FooI = FooH;
+pub type FooJ = FooI;
 
 impl FooA {
     pub fn foo_a(&self) {}
@@ -26,8 +35,12 @@ impl FooC {
     pub fn foo_c(&self) {}
 }
 
+impl FooJ {
+    pub fn foo_j(&self) {}
+}
+
 pub struct Bar;
 impl std::ops::Deref for Bar {
-    type Target = FooC;
+    type Target = FooJ;
     fn deref(&self) -> &Self::Target { unimplemented!() }
 }