Skip to content

Commit

Permalink
collect auto-/blanket-impls during collect-trait-impls
Browse files Browse the repository at this point in the history
  • Loading branch information
QuietMisdreavus committed Sep 20, 2018
1 parent e854d39 commit 87760e5
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 63 deletions.
28 changes: 7 additions & 21 deletions src/librustdoc/clean/inline.rs
Expand Up @@ -29,8 +29,6 @@ use clean::{
self,
GetDefId,
ToSource,
get_auto_traits_with_def_id,
get_blanket_impls_with_def_id,
};

use super::Clean;
Expand All @@ -56,7 +54,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
let inner = match def {
Def::Trait(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Trait);
ret.extend(build_impls(cx, did, false));
ret.extend(build_impls(cx, did));
clean::TraitItem(build_external_trait(cx, did))
}
Def::Fn(did) => {
Expand All @@ -65,27 +63,27 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
}
Def::Struct(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Struct);
ret.extend(build_impls(cx, did, true));
ret.extend(build_impls(cx, did));
clean::StructItem(build_struct(cx, did))
}
Def::Union(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Union);
ret.extend(build_impls(cx, did, true));
ret.extend(build_impls(cx, did));
clean::UnionItem(build_union(cx, did))
}
Def::TyAlias(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Typedef);
ret.extend(build_impls(cx, did, false));
ret.extend(build_impls(cx, did));
clean::TypedefItem(build_type_alias(cx, did), false)
}
Def::Enum(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Enum);
ret.extend(build_impls(cx, did, true));
ret.extend(build_impls(cx, did));
clean::EnumItem(build_enum(cx, did))
}
Def::ForeignTy(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Foreign);
ret.extend(build_impls(cx, did, false));
ret.extend(build_impls(cx, did));
clean::ForeignTypeItem
}
// Never inline enum variants but leave them shown as re-exports.
Expand Down Expand Up @@ -275,26 +273,14 @@ fn build_type_alias(cx: &DocContext, did: DefId) -> clean::Typedef {
}
}

pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean::Item> {
pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
let tcx = cx.tcx;
let mut impls = Vec::new();

for &did in tcx.inherent_impls(did).iter() {
build_impl(cx, did, &mut impls);
}

if auto_traits {
let auto_impls = get_auto_traits_with_def_id(cx, did);
{
let mut renderinfo = cx.renderinfo.borrow_mut();
let new_impls: Vec<clean::Item> = auto_impls.into_iter()
.filter(|i| renderinfo.inlined.insert(i.def_id)).collect();

impls.extend(new_impls);
}
impls.extend(get_blanket_impls_with_def_id(cx, did));
}

impls
}

Expand Down
60 changes: 19 additions & 41 deletions src/librustdoc/clean/mod.rs
Expand Up @@ -576,9 +576,9 @@ impl Clean<Item> for doctree::Module {
let mut items: Vec<Item> = vec![];
items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
items.extend(self.structs.iter().flat_map(|x| x.clean(cx)));
items.extend(self.unions.iter().flat_map(|x| x.clean(cx)));
items.extend(self.enums.iter().flat_map(|x| x.clean(cx)));
items.extend(self.structs.iter().map(|x| x.clean(cx)));
items.extend(self.unions.iter().map(|x| x.clean(cx)));
items.extend(self.enums.iter().map(|x| x.clean(cx)));
items.extend(self.fns.iter().map(|x| x.clean(cx)));
items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
items.extend(self.mods.iter().map(|x| x.clean(cx)));
Expand Down Expand Up @@ -2813,14 +2813,10 @@ pub struct Union {
pub fields_stripped: bool,
}

impl Clean<Vec<Item>> for doctree::Struct {
fn clean(&self, cx: &DocContext) -> Vec<Item> {
let name = self.name.clean(cx);
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));

ret.push(Item {
name: Some(name),
impl Clean<Item> for doctree::Struct {
fn clean(&self, cx: &DocContext) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: cx.tcx.hir.local_def_id(self.id),
Expand All @@ -2833,20 +2829,14 @@ impl Clean<Vec<Item>> for doctree::Struct {
fields: self.fields.clean(cx),
fields_stripped: false,
}),
});

ret
}
}
}

impl Clean<Vec<Item>> for doctree::Union {
fn clean(&self, cx: &DocContext) -> Vec<Item> {
let name = self.name.clean(cx);
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));

ret.push(Item {
name: Some(name),
impl Clean<Item> for doctree::Union {
fn clean(&self, cx: &DocContext) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: cx.tcx.hir.local_def_id(self.id),
Expand All @@ -2859,9 +2849,7 @@ impl Clean<Vec<Item>> for doctree::Union {
fields: self.fields.clean(cx),
fields_stripped: false,
}),
});

ret
}
}
}

Expand Down Expand Up @@ -2892,14 +2880,10 @@ pub struct Enum {
pub variants_stripped: bool,
}

impl Clean<Vec<Item>> for doctree::Enum {
fn clean(&self, cx: &DocContext) -> Vec<Item> {
let name = self.name.clean(cx);
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));

ret.push(Item {
name: Some(name),
impl Clean<Item> for doctree::Enum {
fn clean(&self, cx: &DocContext) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: cx.tcx.hir.local_def_id(self.id),
Expand All @@ -2911,9 +2895,7 @@ impl Clean<Vec<Item>> for doctree::Enum {
generics: self.generics.clean(cx),
variants_stripped: false,
}),
});

ret
}
}
}

Expand Down Expand Up @@ -3442,11 +3424,7 @@ fn build_deref_target_impls(cx: &DocContext,
let primitive = match *target {
ResolvedPath { did, .. } if did.is_local() => continue,
ResolvedPath { did, .. } => {
// We set the last parameter to false to avoid looking for auto-impls for traits
// and therefore avoid an ICE.
// The reason behind this is that auto-traits don't propagate through Deref so
// we're not supposed to synthesise impls for them.
ret.extend(inline::build_impls(cx, did, false));
ret.extend(inline::build_impls(cx, did));
continue
}
_ => match target.primitive_type() {
Expand Down
40 changes: 39 additions & 1 deletion src/librustdoc/passes/collect_trait_impls.rs
Expand Up @@ -12,14 +12,20 @@ use clean::*;

use super::Pass;
use core::DocContext;
use fold::DocFolder;

pub const COLLECT_TRAIT_IMPLS: Pass =
Pass::early("collect-trait-impls", collect_trait_impls,
"retrieves trait impls for items in the crate");

pub fn collect_trait_impls(mut krate: Crate, cx: &DocContext) -> Crate {
pub fn collect_trait_impls(krate: Crate, cx: &DocContext) -> Crate {
let mut synth = SyntheticImplCollector::new(cx);
let mut krate = synth.fold_crate(krate);

if let Some(ref mut it) = krate.module {
if let ModuleItem(Module { ref mut items, .. }) = it.inner {
items.extend(synth.impls);

for &cnum in cx.tcx.crates().iter() {
for &did in cx.tcx.all_trait_implementations(cnum).iter() {
inline::build_impl(cx, did, items);
Expand Down Expand Up @@ -90,3 +96,35 @@ pub fn collect_trait_impls(mut krate: Crate, cx: &DocContext) -> Crate {

krate
}

struct SyntheticImplCollector<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>,
impls: Vec<Item>,
}

impl<'a, 'tcx, 'rcx, 'cstore> SyntheticImplCollector<'a, 'tcx, 'rcx, 'cstore> {
fn new(cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self {
SyntheticImplCollector {
cx,
impls: Vec::new(),
}
}
}

impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for SyntheticImplCollector<'a, 'tcx, 'rcx, 'cstore> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
if i.is_struct() || i.is_enum() || i.is_union() {
if let (Some(node_id), Some(name)) =
(self.cx.tcx.hir.as_local_node_id(i.def_id), i.name.clone())
{
self.impls.extend(get_auto_traits_with_node_id(self.cx, node_id, name.clone()));
self.impls.extend(get_blanket_impls_with_node_id(self.cx, node_id, name));
} else {
self.impls.extend(get_auto_traits_with_def_id(self.cx, i.def_id));
self.impls.extend(get_blanket_impls_with_def_id(self.cx, i.def_id));
}
}

self.fold_item_recur(i)
}
}

0 comments on commit 87760e5

Please sign in to comment.