]> git.lizzy.rs Git - rust.git/commitdiff
Fix deref impl on type alias
authorGuillaume Gomez <guillaume1.gomez@gmail.com>
Fri, 10 Jan 2020 01:07:13 +0000 (02:07 +0100)
committerGuillaume Gomez <guillaume1.gomez@gmail.com>
Wed, 15 Jan 2020 12:43:09 +0000 (13:43 +0100)
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/html/render.rs
src/librustdoc/html/render/cache.rs

index c7e0f1e9e704ba0683a838307205f56a39ac8341..fc75bf35b250d0e3e9c518f96fa105a390026c98 100644 (file)
@@ -273,6 +273,24 @@ fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef {
     clean::Typedef {
         type_: cx.tcx.type_of(did).clean(cx),
         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))
+}
+
+pub 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,
     }
 }
 
index be9654612f504e91163a02adc414d459735c08bd..0cc4c55f49be82b335a5ff945298e61945415455 100644 (file)
@@ -1122,7 +1122,16 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
                 MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
             }
             hir::ImplItemKind::TyAlias(ref ty) => {
-                TypedefItem(Typedef { type_: ty.clean(cx), generics: Generics::default() }, true)
+                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::OpaqueTy(ref bounds) => OpaqueTyItem(
                 OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() },
@@ -1282,10 +1291,13 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
 
                     AssocTypeItem(bounds, ty.clean(cx))
                 } else {
+                    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_: cx.tcx.type_of(self.def_id).clean(cx),
+                            type_,
                             generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
+                            item_type,
                         },
                         true,
                     )
@@ -1989,6 +2001,8 @@ fn clean(&self, _: &DocContext<'_>) -> String {
 
 impl Clean<Item> for doctree::Typedef<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
+        let type_ = self.ty.clean(cx);
+        let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -1998,7 +2012,11 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
             stability: cx.stability(self.id).clean(cx),
             deprecation: cx.deprecation(self.id).clean(cx),
             inner: TypedefItem(
-                Typedef { type_: self.ty.clean(cx), generics: self.gen.clean(cx) },
+                Typedef {
+                    type_,
+                    generics: self.gen.clean(cx),
+                    item_type,
+                },
                 false,
             ),
         }
index 5d8e27ecadb828dbe8edbd7db05671ddf777c39c..79a078ca7a991abdaf58ccdf8728d6e22b466fbf 100644 (file)
@@ -1406,6 +1406,14 @@ pub struct PathSegment {
 pub struct Typedef {
     pub type_: Type,
     pub generics: Generics,
+    // Type of target item.
+    pub item_type: Option<Type>,
+}
+
+impl GetDefId for Typedef {
+    fn def_id(&self) -> Option<DefId> {
+        self.type_.def_id()
+    }
 }
 
 #[derive(Clone, Debug)]
index 2d932eb7668c41041ee767be827f74d3c91834a0..69e268f3f80c1688f9e64cef00b06d327b2eecd9 100644 (file)
@@ -3469,22 +3469,27 @@ fn render_deref_methods(
     deref_mut: bool,
 ) {
     let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
-    let target = impl_
+    let (target, real_target) = impl_
         .inner_impl()
         .items
         .iter()
         .filter_map(|item| match item.inner {
-            clean::TypedefItem(ref t, true) => Some(&t.type_),
+            clean::TypedefItem(ref t, true) => {
+                Some(match *t {
+                    clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, type_),
+                    _ => (&t.type_, &t.type_),
+                })
+            }
             _ => None,
         })
         .next()
         .expect("Expected associated type binding");
     let what =
         AssocItemRender::DerefFor { trait_: deref_type, type_: target, deref_mut_: deref_mut };
-    if let Some(did) = target.def_id() {
+    if let Some(did) = real_target.def_id() {
         render_assoc_items(w, cx, container_item, did, what)
     } else {
-        if let Some(prim) = target.primitive_type() {
+        if let Some(prim) = real_target.primitive_type() {
             if let Some(&did) = cx.cache.primitive_locations.get(&prim) {
                 render_assoc_items(w, cx, container_item, did, what);
             }
@@ -4123,17 +4128,22 @@ 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)
             {
-                if let Some(target) = impl_
+                if let Some((target, real_target)) = impl_
                     .inner_impl()
                     .items
                     .iter()
                     .filter_map(|item| match item.inner {
-                        clean::TypedefItem(ref t, true) => Some(&t.type_),
+                        clean::TypedefItem(ref t, true) => {
+                            Some(match *t {
+                                clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, type_),
+                                _ => (&t.type_, &t.type_),
+                            })
+                        }
                         _ => None,
                     })
                     .next()
                 {
-                    let inner_impl = target
+                    let inner_impl = real_target
                         .def_id()
                         .or(target
                             .primitive_type()
index 22507443b0842fa2d56842cf4fb8890ba7e7a0d9..cdfd6b3073adfc9e230a5449e4a02055186fbf31 100644 (file)
@@ -277,7 +277,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 | clean::StructFieldItem(..)
                 | clean::VariantItem(..) => (
                     (
-                        Some(*self.parent_stack.last().unwrap()),
+                        Some(*self.parent_stack.last().expect("parent_stack is empty")),
                         Some(&self.stack[..self.stack.len() - 1]),
                     ),
                     false,
@@ -286,7 +286,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                     if self.parent_stack.is_empty() {
                         ((None, None), false)
                     } else {
-                        let last = self.parent_stack.last().unwrap();
+                        let last = self.parent_stack.last().expect("parent_stack is empty 2");
                         let did = *last;
                         let path = match self.paths.get(&did) {
                             // The current stack not necessarily has correlation
@@ -468,7 +468,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                         self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
                     }
                 } else {
-                    let trait_did = impl_item.trait_did().unwrap();
+                    let trait_did = impl_item.trait_did().expect("no trait did");
                     self.orphan_trait_impls.push((trait_did, dids, impl_item));
                 }
                 None
@@ -478,10 +478,10 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         });
 
         if pushed {
-            self.stack.pop().unwrap();
+            self.stack.pop().expect("stack already empty");
         }
         if parent_pushed {
-            self.parent_stack.pop().unwrap();
+            self.parent_stack.pop().expect("parent stack already empty");
         }
         self.stripped_mod = orig_stripped_mod;
         self.parent_is_trait_impl = orig_parent_is_trait_impl;
@@ -574,6 +574,9 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     // has since been learned.
     for &(did, ref item) in orphan_impl_items {
         if let Some(&(ref fqp, _)) = paths.get(&did) {
+            if item.name.is_none() { // this is most likely from a typedef
+                continue;
+            }
             search_index.push(IndexItem {
                 ty: item.type_(),
                 name: item.name.clone().unwrap(),
@@ -592,19 +595,25 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     let mut lastpathid = 0usize;
 
     for item in search_index {
-        item.parent_idx = item.parent.map(|nodeid| {
-            if nodeid_to_pathid.contains_key(&nodeid) {
-                *nodeid_to_pathid.get(&nodeid).unwrap()
-            } else {
-                let pathid = lastpathid;
-                nodeid_to_pathid.insert(nodeid, pathid);
-                lastpathid += 1;
+        item.parent_idx = match item.parent {
+            Some(nodeid) => {
+                Some(if nodeid_to_pathid.contains_key(&nodeid) {
+                    *nodeid_to_pathid.get(&nodeid).expect("no pathid")
+                } else {
+                    let pathid = lastpathid;
+                    nodeid_to_pathid.insert(nodeid, pathid);
+                    lastpathid += 1;
 
-                let &(ref fqp, short) = paths.get(&nodeid).unwrap();
-                crate_paths.push((short, fqp.last().unwrap().clone()));
-                pathid
+                    if let Some(&(ref fqp, short)) = paths.get(&nodeid) {
+                        crate_paths.push((short, fqp.last().expect("no fqp").clone()));
+                    } else {
+                        continue
+                    }
+                    pathid
+                })
             }
-        });
+            None => None,
+        };
 
         // Omit the parent path if it is same to that of the prior item.
         if lastpath == item.path {
@@ -639,7 +648,7 @@ struct CrateData<'a> {
             items: crate_items,
             paths: crate_paths,
         })
-        .unwrap()
+        .expect("failed serde conversion")
     )
 }