diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index ed5783c8dba66..ca8ae83ab80a8 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -411,3 +411,8 @@ pub fn is_defaulted_trait(cstore: &cstore::CStore, trait_def_id: ast::DefId) -> let cdata = cstore.get_crate_data(trait_def_id.krate); decoder::is_defaulted_trait(&*cdata, trait_def_id.node) } + +pub fn is_default_impl(cstore: &cstore::CStore, impl_did: ast::DefId) -> bool { + let cdata = cstore.get_crate_data(impl_did.krate); + decoder::is_default_impl(&*cdata, impl_did.node) +} diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index dbbc17c018a2f..c0bad80ab594a 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1537,13 +1537,18 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool { } } -pub fn is_defaulted_trait<'tcx>(cdata: Cmd, trait_id: ast::NodeId) -> bool { +pub fn is_defaulted_trait(cdata: Cmd, trait_id: ast::NodeId) -> bool { let trait_doc = lookup_item(trait_id, cdata.data()); assert!(item_family(trait_doc) == Family::Trait); let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait); reader::doc_as_u8(defaulted_doc) != 0 } +pub fn is_default_impl(cdata: Cmd, impl_id: ast::NodeId) -> bool { + let impl_doc = lookup_item(impl_id, cdata.data()); + item_family(impl_doc) == Family::DefaultImpl +} + pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { let crate_doc = rbml::Doc::new(metadata); let cm_doc = reader::get_doc(crate_doc, tag_codemap); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 9f7b68f38fa6e..aa17bf20d74bb 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -259,26 +259,43 @@ fn build_impls(cx: &DocContext, tcx: &ty::ctxt, impls.into_iter().filter_map(|a| a).collect() } -fn build_impl(cx: &DocContext, tcx: &ty::ctxt, +fn build_impl(cx: &DocContext, + tcx: &ty::ctxt, did: ast::DefId) -> Option { if !cx.inlined.borrow_mut().as_mut().unwrap().insert(did) { return None } + let attrs = load_attrs(cx, tcx, did); let associated_trait = csearch::get_impl_trait(tcx, did); - // If this is an impl for a #[doc(hidden)] trait, be sure to not inline it. - match associated_trait { - Some(ref t) => { - let trait_attrs = load_attrs(cx, tcx, t.def_id); - if trait_attrs.iter().any(|a| is_doc_hidden(a)) { - return None - } + if let Some(ref t) = associated_trait { + // If this is an impl for a #[doc(hidden)] trait, be sure to not inline + let trait_attrs = load_attrs(cx, tcx, t.def_id); + if trait_attrs.iter().any(|a| is_doc_hidden(a)) { + return None } - None => {} } - let attrs = load_attrs(cx, tcx, did); - let ty = ty::lookup_item_type(tcx, did); + // If this is a defaulted impl, then bail out early here + if csearch::is_default_impl(&tcx.sess.cstore, did) { + return Some(clean::Item { + inner: clean::DefaultImplItem(clean::DefaultImpl { + // FIXME: this should be decoded + unsafety: ast::Unsafety::Normal, + trait_: match associated_trait.as_ref().unwrap().clean(cx) { + clean::TraitBound(polyt, _) => polyt.trait_, + clean::RegionBound(..) => unreachable!(), + }, + }), + source: clean::Span::empty(), + name: None, + attrs: attrs, + visibility: Some(ast::Inherited), + stability: stability::lookup(tcx, did).clean(cx), + def_id: did, + }); + } + let predicates = ty::lookup_predicates(tcx, did); let trait_items = csearch::get_impl_items(&tcx.sess.cstore, did) .iter() @@ -330,8 +347,10 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt, } }).collect(); let polarity = csearch::get_impl_polarity(tcx, did); + let ty = ty::lookup_item_type(tcx, did); return Some(clean::Item { inner: clean::ImplItem(clean::Impl { + unsafety: ast::Unsafety::Normal, // FIXME: this should be decoded derived: clean::detect_derived(&attrs), trait_: associated_trait.clean(cx).map(|bound| { match bound { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e91e95961c521..421549f8b7ecb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -337,6 +337,7 @@ pub enum ItemEnum { MacroItem(Macro), PrimitiveItem(PrimitiveType), AssociatedTypeItem(Vec, Option), + DefaultImplItem(DefaultImpl), } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -367,6 +368,7 @@ impl Clean for doctree::Module { items.extend(self.traits.iter().map(|x| x.clean(cx))); items.extend(self.impls.iter().map(|x| x.clean(cx))); items.extend(self.macros.iter().map(|x| x.clean(cx))); + items.extend(self.def_traits.iter().map(|x| x.clean(cx))); // determine if we should display the inner contents or // the outer `mod` item for the source code. @@ -2079,6 +2081,7 @@ impl Clean for ast::ImplPolarity { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Impl { + pub unsafety: ast::Unsafety, pub generics: Generics, pub trait_: Option, pub for_: Type, @@ -2101,6 +2104,7 @@ impl Clean for doctree::Impl { visibility: self.vis.clean(cx), stability: self.stab.clean(cx), inner: ImplItem(Impl { + unsafety: self.unsafety, generics: self.generics.clean(cx), trait_: self.trait_.clean(cx), for_: self.for_.clean(cx), @@ -2112,6 +2116,29 @@ impl Clean for doctree::Impl { } } +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub struct DefaultImpl { + pub unsafety: ast::Unsafety, + pub trait_: Type, +} + +impl Clean for doctree::DefaultImpl { + fn clean(&self, cx: &DocContext) -> Item { + Item { + name: None, + attrs: self.attrs.clean(cx), + source: self.whence.clean(cx), + def_id: ast_util::local_def(self.id), + visibility: Some(ast::Public), + stability: None, + inner: DefaultImplItem(DefaultImpl { + unsafety: self.unsafety, + trait_: self.trait_.clean(cx), + }), + } + } +} + impl Clean for doctree::ExternCrate { fn clean(&self, cx: &DocContext) -> Item { Item { diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 5a4deaa2e7266..c6d8b9428c575 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -202,6 +202,8 @@ pub struct DefaultImpl { pub unsafety: ast::Unsafety, pub trait_: ast::TraitRef, pub id: ast::NodeId, + pub attrs: Vec, + pub whence: Span, } pub struct Macro { diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index 356be2ffeb04c..1d63f01be524a 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -64,6 +64,7 @@ impl ItemType { clean::MacroItem(..) => ItemType::Macro, clean::PrimitiveItem(..) => ItemType::Primitive, clean::AssociatedTypeItem(..) => ItemType::AssociatedType, + clean::DefaultImplItem(..) => ItemType::Impl, } } diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index 722f14fa6d4c7..953b442bb3ceb 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -176,7 +176,7 @@ impl<'a> fold::DocFolder for Stripper<'a> { return None; } } - clean::ImplItem(..) => {} + clean::DefaultImplItem(..) | clean::ImplItem(..) => {} // tymethods/macros have no control over privacy clean::MacroItem(..) | clean::TyMethodItem(..) => {} diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 3e998166397bc..d53954b29b585 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -362,7 +362,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let i = DefaultImpl { unsafety: unsafety, trait_: trait_ref.clone(), - id: item.id + id: item.id, + attrs: item.attrs.clone(), + whence: item.span, }; om.def_traits.push(i); } diff --git a/src/test/run-make/rustdoc-default-impl/Makefile b/src/test/run-make/rustdoc-default-impl/Makefile new file mode 100644 index 0000000000000..338cf9d205318 --- /dev/null +++ b/src/test/run-make/rustdoc-default-impl/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: foo.rs bar.rs + $(RUSTC) foo.rs --crate-type lib + $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc bar.rs -L $(TMPDIR) diff --git a/src/test/run-make/rustdoc-default-impl/bar.rs b/src/test/run-make/rustdoc-default-impl/bar.rs new file mode 100644 index 0000000000000..c9fae80d85829 --- /dev/null +++ b/src/test/run-make/rustdoc-default-impl/bar.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate foo; + +pub use foo::bar; + +pub fn wut() { +} + diff --git a/src/test/run-make/rustdoc-default-impl/foo.rs b/src/test/run-make/rustdoc-default-impl/foo.rs new file mode 100644 index 0000000000000..08f3bd10e74a7 --- /dev/null +++ b/src/test/run-make/rustdoc-default-impl/foo.rs @@ -0,0 +1,33 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub mod bar { + use std::marker; + + pub trait Bar: marker::MarkerTrait + 'static {} + + impl Bar for .. {} + + pub trait Foo { + fn foo(&self) {} + } + + impl Foo { + pub fn test(&self) {} + } + + pub struct TypeId; + + impl TypeId { + pub fn of() -> TypeId { + panic!() + } + } +}