Skip to content

Commit 3c3ae3d

Browse files
authored
Rollup merge of rust-lang#68093 - GuillaumeGomez:fix-deref-impl-typedef, r=oli-obk
Fix deref impl typedef Fixes rust-lang#35295. r? @kinnison
2 parents a4014b6 + 482dc77 commit 3c3ae3d

File tree

6 files changed

+101
-25
lines changed

6 files changed

+101
-25
lines changed

src/librustdoc/clean/inline.rs

+16
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,22 @@ fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef {
273273
clean::Typedef {
274274
type_: cx.tcx.type_of(did).clean(cx),
275275
generics: (cx.tcx.generics_of(did), predicates).clean(cx),
276+
item_type: build_type_alias_type(cx, did),
277+
}
278+
}
279+
280+
fn build_type_alias_type(cx: &DocContext<'_>, did: DefId) -> Option<clean::Type> {
281+
let type_ = cx.tcx.type_of(did).clean(cx);
282+
type_.def_id().and_then(|did| build_ty(cx, did))
283+
}
284+
285+
pub fn build_ty(cx: &DocContext, did: DefId) -> Option<clean::Type> {
286+
match cx.tcx.def_kind(did)? {
287+
DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Const | DefKind::Static => {
288+
Some(cx.tcx.type_of(did).clean(cx))
289+
}
290+
DefKind::TyAlias => build_type_alias_type(cx, did),
291+
_ => None,
276292
}
277293
}
278294

src/librustdoc/clean/mod.rs

+24-11
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,9 @@ impl Clean<Item> for hir::ImplItem<'_> {
11221122
MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
11231123
}
11241124
hir::ImplItemKind::TyAlias(ref ty) => {
1125-
TypedefItem(Typedef { type_: ty.clean(cx), generics: Generics::default() }, true)
1125+
let type_ = ty.clean(cx);
1126+
let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
1127+
TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true)
11261128
}
11271129
hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem(
11281130
OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() },
@@ -1282,10 +1284,13 @@ impl Clean<Item> for ty::AssocItem {
12821284

12831285
AssocTypeItem(bounds, ty.clean(cx))
12841286
} else {
1287+
let type_ = cx.tcx.type_of(self.def_id).clean(cx);
1288+
let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
12851289
TypedefItem(
12861290
Typedef {
1287-
type_: cx.tcx.type_of(self.def_id).clean(cx),
1291+
type_,
12881292
generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
1293+
item_type,
12891294
},
12901295
true,
12911296
)
@@ -1989,6 +1994,8 @@ impl Clean<String> for ast::Name {
19891994

19901995
impl Clean<Item> for doctree::Typedef<'_> {
19911996
fn clean(&self, cx: &DocContext<'_>) -> Item {
1997+
let type_ = self.ty.clean(cx);
1998+
let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
19921999
Item {
19932000
name: Some(self.name.clean(cx)),
19942001
attrs: self.attrs.clean(cx),
@@ -1997,10 +2004,7 @@ impl Clean<Item> for doctree::Typedef<'_> {
19972004
visibility: self.vis.clean(cx),
19982005
stability: cx.stability(self.id).clean(cx),
19992006
deprecation: cx.deprecation(self.id).clean(cx),
2000-
inner: TypedefItem(
2001-
Typedef { type_: self.ty.clean(cx), generics: self.gen.clean(cx) },
2002-
false,
2003-
),
2007+
inner: TypedefItem(Typedef { type_, generics: self.gen.clean(cx), item_type }, false),
20042008
}
20052009
}
20062010
}
@@ -2101,7 +2105,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
21012105
build_deref_target_impls(cx, &items, &mut ret);
21022106
}
21032107

2104-
let provided = trait_
2108+
let provided: FxHashSet<String> = trait_
21052109
.def_id()
21062110
.map(|did| {
21072111
cx.tcx
@@ -2112,7 +2116,12 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
21122116
})
21132117
.unwrap_or_default();
21142118

2115-
ret.push(Item {
2119+
let for_ = self.for_.clean(cx);
2120+
let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) {
2121+
Some(DefKind::TyAlias) => Some(cx.tcx.type_of(did).clean(cx)),
2122+
_ => None,
2123+
});
2124+
let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| Item {
21162125
name: None,
21172126
attrs: self.attrs.clean(cx),
21182127
source: self.whence.clean(cx),
@@ -2123,15 +2132,19 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
21232132
inner: ImplItem(Impl {
21242133
unsafety: self.unsafety,
21252134
generics: self.generics.clean(cx),
2126-
provided_trait_methods: provided,
2135+
provided_trait_methods: provided.clone(),
21272136
trait_,
2128-
for_: self.for_.clean(cx),
2137+
for_,
21292138
items,
21302139
polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
21312140
synthetic: false,
21322141
blanket_impl: None,
21332142
}),
2134-
});
2143+
};
2144+
if let Some(type_alias) = type_alias {
2145+
ret.push(make_item(trait_.clone(), type_alias, items.clone()));
2146+
}
2147+
ret.push(make_item(trait_, for_, items));
21352148
ret
21362149
}
21372150
}

src/librustdoc/clean/types.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,14 @@ pub struct PathSegment {
14061406
pub struct Typedef {
14071407
pub type_: Type,
14081408
pub generics: Generics,
1409+
// Type of target item.
1410+
pub item_type: Option<Type>,
1411+
}
1412+
1413+
impl GetDefId for Typedef {
1414+
fn def_id(&self) -> Option<DefId> {
1415+
self.type_.def_id()
1416+
}
14091417
}
14101418

14111419
#[derive(Clone, Debug)]

src/librustdoc/html/render.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -3469,20 +3469,23 @@ fn render_deref_methods(
34693469
deref_mut: bool,
34703470
) {
34713471
let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
3472-
let target = impl_
3472+
let (target, real_target) = impl_
34733473
.inner_impl()
34743474
.items
34753475
.iter()
34763476
.filter_map(|item| match item.inner {
3477-
clean::TypedefItem(ref t, true) => Some(&t.type_),
3477+
clean::TypedefItem(ref t, true) => Some(match *t {
3478+
clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_),
3479+
_ => (&t.type_, &t.type_),
3480+
}),
34783481
_ => None,
34793482
})
34803483
.next()
34813484
.expect("Expected associated type binding");
34823485
let what =
3483-
AssocItemRender::DerefFor { trait_: deref_type, type_: target, deref_mut_: deref_mut };
3486+
AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
34843487
if let Some(did) = target.def_id() {
3485-
render_assoc_items(w, cx, container_item, did, what)
3488+
render_assoc_items(w, cx, container_item, did, what);
34863489
} else {
34873490
if let Some(prim) = target.primitive_type() {
34883491
if let Some(&did) = cx.cache.primitive_locations.get(&prim) {
@@ -4123,12 +4126,15 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
41234126
.filter(|i| i.inner_impl().trait_.is_some())
41244127
.find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did)
41254128
{
4126-
if let Some(target) = impl_
4129+
if let Some((target, real_target)) = impl_
41274130
.inner_impl()
41284131
.items
41294132
.iter()
41304133
.filter_map(|item| match item.inner {
4131-
clean::TypedefItem(ref t, true) => Some(&t.type_),
4134+
clean::TypedefItem(ref t, true) => Some(match *t {
4135+
clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_),
4136+
_ => (&t.type_, &t.type_),
4137+
}),
41324138
_ => None,
41334139
})
41344140
.next()
@@ -4147,7 +4153,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
41474153
"{:#}",
41484154
impl_.inner_impl().trait_.as_ref().unwrap().print()
41494155
)),
4150-
Escape(&format!("{:#}", target.print()))
4156+
Escape(&format!("{:#}", real_target.print()))
41514157
));
41524158
out.push_str("</a>");
41534159
let mut ret = impls

src/librustdoc/html/render/cache.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ impl DocFolder for Cache {
277277
| clean::StructFieldItem(..)
278278
| clean::VariantItem(..) => (
279279
(
280-
Some(*self.parent_stack.last().unwrap()),
280+
Some(*self.parent_stack.last().expect("parent_stack is empty")),
281281
Some(&self.stack[..self.stack.len() - 1]),
282282
),
283283
false,
@@ -286,7 +286,7 @@ impl DocFolder for Cache {
286286
if self.parent_stack.is_empty() {
287287
((None, None), false)
288288
} else {
289-
let last = self.parent_stack.last().unwrap();
289+
let last = self.parent_stack.last().expect("parent_stack is empty 2");
290290
let did = *last;
291291
let path = match self.paths.get(&did) {
292292
// The current stack not necessarily has correlation
@@ -468,7 +468,7 @@ impl DocFolder for Cache {
468468
self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
469469
}
470470
} else {
471-
let trait_did = impl_item.trait_did().unwrap();
471+
let trait_did = impl_item.trait_did().expect("no trait did");
472472
self.orphan_trait_impls.push((trait_did, dids, impl_item));
473473
}
474474
None
@@ -478,10 +478,10 @@ impl DocFolder for Cache {
478478
});
479479

480480
if pushed {
481-
self.stack.pop().unwrap();
481+
self.stack.pop().expect("stack already empty");
482482
}
483483
if parent_pushed {
484-
self.parent_stack.pop().unwrap();
484+
self.parent_stack.pop().expect("parent stack already empty");
485485
}
486486
self.stripped_mod = orig_stripped_mod;
487487
self.parent_is_trait_impl = orig_parent_is_trait_impl;
@@ -594,7 +594,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
594594
for item in search_index {
595595
item.parent_idx = item.parent.map(|nodeid| {
596596
if nodeid_to_pathid.contains_key(&nodeid) {
597-
*nodeid_to_pathid.get(&nodeid).unwrap()
597+
*nodeid_to_pathid.get(&nodeid).expect("no pathid")
598598
} else {
599599
let pathid = lastpathid;
600600
nodeid_to_pathid.insert(nodeid, pathid);
@@ -639,7 +639,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
639639
items: crate_items,
640640
paths: crate_paths,
641641
})
642-
.unwrap()
642+
.expect("failed serde conversion")
643643
)
644644
}
645645

src/test/rustdoc/deref-typedef.rs

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#![crate_name = "foo"]
2+
3+
// @has 'foo/struct.Bar.html'
4+
// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooC>'
5+
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)'
6+
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
7+
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
8+
// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref<Target=FooC>'
9+
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
10+
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
11+
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'
12+
13+
pub struct FooA;
14+
pub type FooB = FooA;
15+
pub type FooC = FooB;
16+
17+
impl FooA {
18+
pub fn foo_a(&self) {}
19+
}
20+
21+
impl FooB {
22+
pub fn foo_b(&self) {}
23+
}
24+
25+
impl FooC {
26+
pub fn foo_c(&self) {}
27+
}
28+
29+
pub struct Bar;
30+
impl std::ops::Deref for Bar {
31+
type Target = FooC;
32+
fn deref(&self) -> &Self::Target { unimplemented!() }
33+
}

0 commit comments

Comments
 (0)