Rollup merge of #68093 - GuillaumeGomez:fix-deref-impl-typedef, r=oli-obk
Fix deref impl typedef Fixes #35295. r? @kinnison
This commit is contained in:
commit
bafe089d1f
@ -273,6 +273,22 @@ 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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1122,7 +1122,9 @@ impl Clean<Item> 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 +1284,13 @@ impl Clean<Item> 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 +1994,8 @@ impl Clean<String> for ast::Name {
|
||||
|
||||
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),
|
||||
@ -1997,10 +2004,7 @@ impl Clean<Item> for doctree::Typedef<'_> {
|
||||
visibility: self.vis.clean(cx),
|
||||
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) },
|
||||
false,
|
||||
),
|
||||
inner: TypedefItem(Typedef { type_, generics: self.gen.clean(cx), item_type }, false),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2101,7 +2105,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
|
||||
build_deref_target_impls(cx, &items, &mut ret);
|
||||
}
|
||||
|
||||
let provided = trait_
|
||||
let provided: FxHashSet<String> = trait_
|
||||
.def_id()
|
||||
.map(|did| {
|
||||
cx.tcx
|
||||
@ -2112,7 +2116,12 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
ret.push(Item {
|
||||
let for_ = self.for_.clean(cx);
|
||||
let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) {
|
||||
Some(DefKind::TyAlias) => Some(cx.tcx.type_of(did).clean(cx)),
|
||||
_ => None,
|
||||
});
|
||||
let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| Item {
|
||||
name: None,
|
||||
attrs: self.attrs.clean(cx),
|
||||
source: self.whence.clean(cx),
|
||||
@ -2123,15 +2132,19 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
|
||||
inner: ImplItem(Impl {
|
||||
unsafety: self.unsafety,
|
||||
generics: self.generics.clean(cx),
|
||||
provided_trait_methods: provided,
|
||||
provided_trait_methods: provided.clone(),
|
||||
trait_,
|
||||
for_: self.for_.clean(cx),
|
||||
for_,
|
||||
items,
|
||||
polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
|
||||
synthetic: false,
|
||||
blanket_impl: None,
|
||||
}),
|
||||
});
|
||||
};
|
||||
if let Some(type_alias) = type_alias {
|
||||
ret.push(make_item(trait_.clone(), type_alias, items.clone()));
|
||||
}
|
||||
ret.push(make_item(trait_, for_, items));
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -3469,20 +3469,23 @@ 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_), .. } => (type_, &t.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 };
|
||||
AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
|
||||
if let Some(did) = target.def_id() {
|
||||
render_assoc_items(w, cx, container_item, did, what)
|
||||
render_assoc_items(w, cx, container_item, did, what);
|
||||
} else {
|
||||
if let Some(prim) = target.primitive_type() {
|
||||
if let Some(&did) = cx.cache.primitive_locations.get(&prim) {
|
||||
@ -4123,12 +4126,15 @@ 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_), .. } => (type_, &t.type_),
|
||||
_ => (&t.type_, &t.type_),
|
||||
}),
|
||||
_ => None,
|
||||
})
|
||||
.next()
|
||||
@ -4147,7 +4153,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
|
||||
"{:#}",
|
||||
impl_.inner_impl().trait_.as_ref().unwrap().print()
|
||||
)),
|
||||
Escape(&format!("{:#}", target.print()))
|
||||
Escape(&format!("{:#}", real_target.print()))
|
||||
));
|
||||
out.push_str("</a>");
|
||||
let mut ret = impls
|
||||
|
@ -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;
|
||||
@ -594,7 +594,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
|
||||
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()
|
||||
*nodeid_to_pathid.get(&nodeid).expect("no pathid")
|
||||
} else {
|
||||
let pathid = lastpathid;
|
||||
nodeid_to_pathid.insert(nodeid, pathid);
|
||||
@ -639,7 +639,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
|
||||
items: crate_items,
|
||||
paths: crate_paths,
|
||||
})
|
||||
.unwrap()
|
||||
.expect("failed serde conversion")
|
||||
)
|
||||
}
|
||||
|
||||
|
33
src/test/rustdoc/deref-typedef.rs
Normal file
33
src/test/rustdoc/deref-typedef.rs
Normal file
@ -0,0 +1,33 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has 'foo/struct.Bar.html'
|
||||
// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooC>'
|
||||
// @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="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'
|
||||
|
||||
pub struct FooA;
|
||||
pub type FooB = FooA;
|
||||
pub type FooC = FooB;
|
||||
|
||||
impl FooA {
|
||||
pub fn foo_a(&self) {}
|
||||
}
|
||||
|
||||
impl FooB {
|
||||
pub fn foo_b(&self) {}
|
||||
}
|
||||
|
||||
impl FooC {
|
||||
pub fn foo_c(&self) {}
|
||||
}
|
||||
|
||||
pub struct Bar;
|
||||
impl std::ops::Deref for Bar {
|
||||
type Target = FooC;
|
||||
fn deref(&self) -> &Self::Target { unimplemented!() }
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user