diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c7e0f1e9e704..fc75bf35b250 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -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 { + 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 { + 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, } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index be9654612f50..0cc4c55f49be 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1122,7 +1122,16 @@ impl Clean for hir::ImplItem<'_> { 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 @@ impl Clean for ty::AssocItem { 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 @@ impl Clean for ast::Name { impl Clean 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 @@ impl Clean for doctree::Typedef<'_> { 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, ), } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5d8e27ecadb8..79a078ca7a99 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1406,6 +1406,14 @@ pub struct PathSegment { pub struct Typedef { pub type_: Type, pub generics: Generics, + // Type of target item. + pub item_type: Option, +} + +impl GetDefId for Typedef { + fn def_id(&self) -> Option { + self.type_.def_id() + } } #[derive(Clone, Debug)] diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 2d932eb7668c..69e268f3f80c 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -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() diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 22507443b084..cdfd6b3073ad 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -277,7 +277,7 @@ impl DocFolder for Cache { | 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 @@ impl DocFolder for Cache { 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 @@ impl DocFolder for Cache { 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 @@ impl DocFolder for Cache { }); 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 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { items: crate_items, paths: crate_paths, }) - .unwrap() + .expect("failed serde conversion") ) }