Skip to content

Commit

Permalink
Auto merge of rust-lang#80661 - jyn514:duplicate-types, r=GuillaumeGomez
Browse files Browse the repository at this point in the history
Cleanup rustdoc handling of associated types

This is best reviewed a commit at a time. No particular reason for these changes, they just stood out as I was reviewing rust-lang#80653 and thinking about rust-lang#80379. The new test case worked before, it just wasn't tested.

r? `@GuillaumeGomez`
  • Loading branch information
bors committed Jan 4, 2021
2 parents 887398f + 24ef945 commit 6163bfd
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 31 deletions.
20 changes: 3 additions & 17 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,26 +261,12 @@ fn build_union(cx: &DocContext<'_>, did: DefId) -> clean::Union {

fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef {
let predicates = cx.tcx.explicit_predicates_of(did);
let type_ = cx.tcx.type_of(did).clean(cx);

clean::Typedef {
type_: cx.tcx.type_of(did).clean(cx),
type_,
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))
}

crate 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,
item_type: None,
}
}

Expand Down
31 changes: 21 additions & 10 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1119,10 +1119,17 @@ impl Clean<Item> for hir::ImplItem<'_> {
}
MethodItem(m, Some(self.defaultness))
}
hir::ImplItemKind::TyAlias(ref ty) => {
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::TyAlias(ref hir_ty) => {
let type_ = hir_ty.clean(cx);
let item_type = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
TypedefItem(
Typedef {
type_,
generics: Generics::default(),
item_type: Some(item_type),
},
true,
)
}
};
Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx)
Expand Down Expand Up @@ -1268,13 +1275,13 @@ impl Clean<Item> for ty::AssocItem {

AssocTypeItem(bounds, ty.clean(cx))
} else {
// FIXME: when could this happen? ASsociated items in inherent impls?
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_,
generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
item_type,
item_type: None,
},
true,
)
Expand Down Expand Up @@ -1987,11 +1994,15 @@ impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
bounds: ty.bounds.clean(cx),
generics: ty.generics.clean(cx),
}),
ItemKind::TyAlias(ty, ref generics) => {
let rustdoc_ty = ty.clean(cx);
let item_type = rustdoc_ty.def_id().and_then(|did| inline::build_ty(cx, did));
ItemKind::TyAlias(hir_ty, ref generics) => {
let rustdoc_ty = hir_ty.clean(cx);
let ty = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
TypedefItem(
Typedef { type_: rustdoc_ty, generics: generics.clean(cx), item_type },
Typedef {
type_: rustdoc_ty,
generics: generics.clean(cx),
item_type: Some(ty),
},
false,
)
}
Expand Down
11 changes: 10 additions & 1 deletion src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,10 @@ crate enum ItemKind {
ProcMacroItem(ProcMacro),
PrimitiveItem(PrimitiveType),
AssocConstItem(Type, Option<String>),
/// An associated item in a trait or trait impl.
///
/// The bounds may be non-empty if there is a `where` clause.
/// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
AssocTypeItem(Vec<GenericBound>, Option<Type>),
/// An item that has been stripped by a rustdoc pass
StrippedItem(Box<ItemKind>),
Expand Down Expand Up @@ -1804,7 +1808,12 @@ crate struct PathSegment {
crate struct Typedef {
crate type_: Type,
crate generics: Generics,
// Type of target item.
/// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
/// alias instead of the final type. This will always have the final type, regardless of whether
/// `type_` came from HIR or from metadata.
///
/// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
/// final type).
crate item_type: Option<Type>,
}

Expand Down
3 changes: 3 additions & 0 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4303,6 +4303,7 @@ 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)
{
debug!("found Deref: {:?}", impl_);
if let Some((target, real_target)) =
impl_.inner_impl().items.iter().find_map(|item| match *item.kind {
clean::TypedefItem(ref t, true) => Some(match *t {
Expand All @@ -4312,6 +4313,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
_ => None,
})
{
debug!("found target, real_target: {:?} {:?}", target, real_target);
let deref_mut = v
.iter()
.filter(|i| i.inner_impl().trait_.is_some())
Expand All @@ -4325,6 +4327,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
})
.and_then(|did| c.impls.get(&did));
if let Some(impls) = inner_impl {
debug!("found inner_impl: {:?}", impls);
out.push_str("<a class=\"sidebar-title\" href=\"#deref-methods\">");
out.push_str(&format!(
"Methods from {}&lt;Target={}&gt;",
Expand Down
19 changes: 16 additions & 3 deletions src/test/rustdoc/deref-typedef.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
#![crate_name = "foo"]

// @has 'foo/struct.Bar.html'
// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooC>'
// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooJ>'
// @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="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref<Target=FooJ>'
// @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'
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_j"]' 'foo_j'

pub struct FooA;
pub type FooB = FooA;
pub type FooC = FooB;
pub type FooD = FooC;
pub type FooE = FooD;
pub type FooF = FooE;
pub type FooG = FooF;
pub type FooH = FooG;
pub type FooI = FooH;
pub type FooJ = FooI;

impl FooA {
pub fn foo_a(&self) {}
Expand All @@ -26,8 +35,12 @@ impl FooC {
pub fn foo_c(&self) {}
}

impl FooJ {
pub fn foo_j(&self) {}
}

pub struct Bar;
impl std::ops::Deref for Bar {
type Target = FooC;
type Target = FooJ;
fn deref(&self) -> &Self::Target { unimplemented!() }
}

0 comments on commit 6163bfd

Please sign in to comment.