Fix deref impl on type alias
This commit is contained in:
parent
bf84eb538f
commit
12f029b7ee
5 changed files with 90 additions and 27 deletions
|
@ -273,6 +273,24 @@ fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef {
|
||||||
clean::Typedef {
|
clean::Typedef {
|
||||||
type_: cx.tcx.type_of(did).clean(cx),
|
type_: cx.tcx.type_of(did).clean(cx),
|
||||||
generics: (cx.tcx.generics_of(did), predicates).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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1122,7 +1122,16 @@ impl Clean<Item> for hir::ImplItem<'_> {
|
||||||
MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
|
MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
|
||||||
}
|
}
|
||||||
hir::ImplItemKind::TyAlias(ref ty) => {
|
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(
|
hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem(
|
||||||
OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() },
|
OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() },
|
||||||
|
@ -1282,10 +1291,13 @@ impl Clean<Item> for ty::AssocItem {
|
||||||
|
|
||||||
AssocTypeItem(bounds, ty.clean(cx))
|
AssocTypeItem(bounds, ty.clean(cx))
|
||||||
} else {
|
} 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(
|
TypedefItem(
|
||||||
Typedef {
|
Typedef {
|
||||||
type_: cx.tcx.type_of(self.def_id).clean(cx),
|
type_,
|
||||||
generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
|
generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
|
||||||
|
item_type,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
@ -1989,6 +2001,8 @@ impl Clean<String> for ast::Name {
|
||||||
|
|
||||||
impl Clean<Item> for doctree::Typedef<'_> {
|
impl Clean<Item> for doctree::Typedef<'_> {
|
||||||
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
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 {
|
Item {
|
||||||
name: Some(self.name.clean(cx)),
|
name: Some(self.name.clean(cx)),
|
||||||
attrs: self.attrs.clean(cx),
|
attrs: self.attrs.clean(cx),
|
||||||
|
@ -1998,7 +2012,11 @@ impl Clean<Item> for doctree::Typedef<'_> {
|
||||||
stability: cx.stability(self.id).clean(cx),
|
stability: cx.stability(self.id).clean(cx),
|
||||||
deprecation: cx.deprecation(self.id).clean(cx),
|
deprecation: cx.deprecation(self.id).clean(cx),
|
||||||
inner: TypedefItem(
|
inner: TypedefItem(
|
||||||
Typedef { type_: self.ty.clean(cx), generics: self.gen.clean(cx) },
|
Typedef {
|
||||||
|
type_,
|
||||||
|
generics: self.gen.clean(cx),
|
||||||
|
item_type,
|
||||||
|
},
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1406,6 +1406,14 @@ pub struct PathSegment {
|
||||||
pub struct Typedef {
|
pub struct Typedef {
|
||||||
pub type_: Type,
|
pub type_: Type,
|
||||||
pub generics: Generics,
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
@ -3469,22 +3469,27 @@ fn render_deref_methods(
|
||||||
deref_mut: bool,
|
deref_mut: bool,
|
||||||
) {
|
) {
|
||||||
let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
|
let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
|
||||||
let target = impl_
|
let (target, real_target) = impl_
|
||||||
.inner_impl()
|
.inner_impl()
|
||||||
.items
|
.items
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|item| match item.inner {
|
.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,
|
_ => None,
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
.expect("Expected associated type binding");
|
.expect("Expected associated type binding");
|
||||||
let what =
|
let what =
|
||||||
AssocItemRender::DerefFor { trait_: deref_type, type_: target, deref_mut_: deref_mut };
|
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)
|
render_assoc_items(w, cx, container_item, did, what)
|
||||||
} else {
|
} 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) {
|
if let Some(&did) = cx.cache.primitive_locations.get(&prim) {
|
||||||
render_assoc_items(w, cx, container_item, did, what);
|
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())
|
.filter(|i| i.inner_impl().trait_.is_some())
|
||||||
.find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did)
|
.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()
|
.inner_impl()
|
||||||
.items
|
.items
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|item| match item.inner {
|
.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,
|
_ => None,
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
{
|
{
|
||||||
let inner_impl = target
|
let inner_impl = real_target
|
||||||
.def_id()
|
.def_id()
|
||||||
.or(target
|
.or(target
|
||||||
.primitive_type()
|
.primitive_type()
|
||||||
|
|
|
@ -277,7 +277,7 @@ impl DocFolder for Cache {
|
||||||
| clean::StructFieldItem(..)
|
| clean::StructFieldItem(..)
|
||||||
| clean::VariantItem(..) => (
|
| 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]),
|
Some(&self.stack[..self.stack.len() - 1]),
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
|
@ -286,7 +286,7 @@ impl DocFolder for Cache {
|
||||||
if self.parent_stack.is_empty() {
|
if self.parent_stack.is_empty() {
|
||||||
((None, None), false)
|
((None, None), false)
|
||||||
} else {
|
} else {
|
||||||
let last = self.parent_stack.last().unwrap();
|
let last = self.parent_stack.last().expect("parent_stack is empty 2");
|
||||||
let did = *last;
|
let did = *last;
|
||||||
let path = match self.paths.get(&did) {
|
let path = match self.paths.get(&did) {
|
||||||
// The current stack not necessarily has correlation
|
// 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());
|
self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
|
||||||
}
|
}
|
||||||
} else {
|
} 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));
|
self.orphan_trait_impls.push((trait_did, dids, impl_item));
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
@ -478,10 +478,10 @@ impl DocFolder for Cache {
|
||||||
});
|
});
|
||||||
|
|
||||||
if pushed {
|
if pushed {
|
||||||
self.stack.pop().unwrap();
|
self.stack.pop().expect("stack already empty");
|
||||||
}
|
}
|
||||||
if parent_pushed {
|
if parent_pushed {
|
||||||
self.parent_stack.pop().unwrap();
|
self.parent_stack.pop().expect("parent stack already empty");
|
||||||
}
|
}
|
||||||
self.stripped_mod = orig_stripped_mod;
|
self.stripped_mod = orig_stripped_mod;
|
||||||
self.parent_is_trait_impl = orig_parent_is_trait_impl;
|
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.
|
// has since been learned.
|
||||||
for &(did, ref item) in orphan_impl_items {
|
for &(did, ref item) in orphan_impl_items {
|
||||||
if let Some(&(ref fqp, _)) = paths.get(&did) {
|
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 {
|
search_index.push(IndexItem {
|
||||||
ty: item.type_(),
|
ty: item.type_(),
|
||||||
name: item.name.clone().unwrap(),
|
name: item.name.clone().unwrap(),
|
||||||
|
@ -592,19 +595,25 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
|
||||||
let mut lastpathid = 0usize;
|
let mut lastpathid = 0usize;
|
||||||
|
|
||||||
for item in search_index {
|
for item in search_index {
|
||||||
item.parent_idx = item.parent.map(|nodeid| {
|
item.parent_idx = match item.parent {
|
||||||
if nodeid_to_pathid.contains_key(&nodeid) {
|
Some(nodeid) => {
|
||||||
*nodeid_to_pathid.get(&nodeid).unwrap()
|
Some(if nodeid_to_pathid.contains_key(&nodeid) {
|
||||||
} else {
|
*nodeid_to_pathid.get(&nodeid).expect("no pathid")
|
||||||
let pathid = lastpathid;
|
} else {
|
||||||
nodeid_to_pathid.insert(nodeid, pathid);
|
let pathid = lastpathid;
|
||||||
lastpathid += 1;
|
nodeid_to_pathid.insert(nodeid, pathid);
|
||||||
|
lastpathid += 1;
|
||||||
|
|
||||||
let &(ref fqp, short) = paths.get(&nodeid).unwrap();
|
if let Some(&(ref fqp, short)) = paths.get(&nodeid) {
|
||||||
crate_paths.push((short, fqp.last().unwrap().clone()));
|
crate_paths.push((short, fqp.last().expect("no fqp").clone()));
|
||||||
pathid
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pathid
|
||||||
|
})
|
||||||
}
|
}
|
||||||
});
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
// Omit the parent path if it is same to that of the prior item.
|
// Omit the parent path if it is same to that of the prior item.
|
||||||
if lastpath == item.path {
|
if lastpath == item.path {
|
||||||
|
@ -639,7 +648,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
|
||||||
items: crate_items,
|
items: crate_items,
|
||||||
paths: crate_paths,
|
paths: crate_paths,
|
||||||
})
|
})
|
||||||
.unwrap()
|
.expect("failed serde conversion")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue