rustdoc: Fix ICE with cross-crate default impls
This adds a special code path for impls which are listed as default impls to ensure that they're loaded correctly.
This commit is contained in:
parent
c9b03c24ec
commit
4e25765aa2
@ -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);
|
let cdata = cstore.get_crate_data(trait_def_id.krate);
|
||||||
decoder::is_defaulted_trait(&*cdata, trait_def_id.node)
|
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)
|
||||||
|
}
|
||||||
|
@ -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());
|
let trait_doc = lookup_item(trait_id, cdata.data());
|
||||||
assert!(item_family(trait_doc) == Family::Trait);
|
assert!(item_family(trait_doc) == Family::Trait);
|
||||||
let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait);
|
let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait);
|
||||||
reader::doc_as_u8(defaulted_doc) != 0
|
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<codemap::FileMap> {
|
pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
|
||||||
let crate_doc = rbml::Doc::new(metadata);
|
let crate_doc = rbml::Doc::new(metadata);
|
||||||
let cm_doc = reader::get_doc(crate_doc, tag_codemap);
|
let cm_doc = reader::get_doc(crate_doc, tag_codemap);
|
||||||
|
@ -259,26 +259,43 @@ fn build_impls(cx: &DocContext, tcx: &ty::ctxt,
|
|||||||
impls.into_iter().filter_map(|a| a).collect()
|
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<clean::Item> {
|
did: ast::DefId) -> Option<clean::Item> {
|
||||||
if !cx.inlined.borrow_mut().as_mut().unwrap().insert(did) {
|
if !cx.inlined.borrow_mut().as_mut().unwrap().insert(did) {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let attrs = load_attrs(cx, tcx, did);
|
||||||
let associated_trait = csearch::get_impl_trait(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.
|
if let Some(ref t) = associated_trait {
|
||||||
match associated_trait {
|
// If this is an impl for a #[doc(hidden)] trait, be sure to not inline
|
||||||
Some(ref t) => {
|
let trait_attrs = load_attrs(cx, tcx, t.def_id);
|
||||||
let trait_attrs = load_attrs(cx, tcx, t.def_id);
|
if trait_attrs.iter().any(|a| is_doc_hidden(a)) {
|
||||||
if trait_attrs.iter().any(|a| is_doc_hidden(a)) {
|
return None
|
||||||
return None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let attrs = load_attrs(cx, tcx, did);
|
// If this is a defaulted impl, then bail out early here
|
||||||
let ty = ty::lookup_item_type(tcx, did);
|
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 predicates = ty::lookup_predicates(tcx, did);
|
||||||
let trait_items = csearch::get_impl_items(&tcx.sess.cstore, did)
|
let trait_items = csearch::get_impl_items(&tcx.sess.cstore, did)
|
||||||
.iter()
|
.iter()
|
||||||
@ -330,8 +347,10 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
|
|||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
let polarity = csearch::get_impl_polarity(tcx, did);
|
let polarity = csearch::get_impl_polarity(tcx, did);
|
||||||
|
let ty = ty::lookup_item_type(tcx, did);
|
||||||
return Some(clean::Item {
|
return Some(clean::Item {
|
||||||
inner: clean::ImplItem(clean::Impl {
|
inner: clean::ImplItem(clean::Impl {
|
||||||
|
unsafety: ast::Unsafety::Normal, // FIXME: this should be decoded
|
||||||
derived: clean::detect_derived(&attrs),
|
derived: clean::detect_derived(&attrs),
|
||||||
trait_: associated_trait.clean(cx).map(|bound| {
|
trait_: associated_trait.clean(cx).map(|bound| {
|
||||||
match bound {
|
match bound {
|
||||||
|
@ -337,6 +337,7 @@ pub enum ItemEnum {
|
|||||||
MacroItem(Macro),
|
MacroItem(Macro),
|
||||||
PrimitiveItem(PrimitiveType),
|
PrimitiveItem(PrimitiveType),
|
||||||
AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
|
AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
|
||||||
|
DefaultImplItem(DefaultImpl),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
@ -367,6 +368,7 @@ impl Clean<Item> for doctree::Module {
|
|||||||
items.extend(self.traits.iter().map(|x| x.clean(cx)));
|
items.extend(self.traits.iter().map(|x| x.clean(cx)));
|
||||||
items.extend(self.impls.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.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
|
// determine if we should display the inner contents or
|
||||||
// the outer `mod` item for the source code.
|
// the outer `mod` item for the source code.
|
||||||
@ -2079,6 +2081,7 @@ impl Clean<ImplPolarity> for ast::ImplPolarity {
|
|||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct Impl {
|
pub struct Impl {
|
||||||
|
pub unsafety: ast::Unsafety,
|
||||||
pub generics: Generics,
|
pub generics: Generics,
|
||||||
pub trait_: Option<Type>,
|
pub trait_: Option<Type>,
|
||||||
pub for_: Type,
|
pub for_: Type,
|
||||||
@ -2101,6 +2104,7 @@ impl Clean<Item> for doctree::Impl {
|
|||||||
visibility: self.vis.clean(cx),
|
visibility: self.vis.clean(cx),
|
||||||
stability: self.stab.clean(cx),
|
stability: self.stab.clean(cx),
|
||||||
inner: ImplItem(Impl {
|
inner: ImplItem(Impl {
|
||||||
|
unsafety: self.unsafety,
|
||||||
generics: self.generics.clean(cx),
|
generics: self.generics.clean(cx),
|
||||||
trait_: self.trait_.clean(cx),
|
trait_: self.trait_.clean(cx),
|
||||||
for_: self.for_.clean(cx),
|
for_: self.for_.clean(cx),
|
||||||
@ -2112,6 +2116,29 @@ impl Clean<Item> for doctree::Impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
|
pub struct DefaultImpl {
|
||||||
|
pub unsafety: ast::Unsafety,
|
||||||
|
pub trait_: Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clean<Item> 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<Item> for doctree::ExternCrate {
|
impl Clean<Item> for doctree::ExternCrate {
|
||||||
fn clean(&self, cx: &DocContext) -> Item {
|
fn clean(&self, cx: &DocContext) -> Item {
|
||||||
Item {
|
Item {
|
||||||
|
@ -202,6 +202,8 @@ pub struct DefaultImpl {
|
|||||||
pub unsafety: ast::Unsafety,
|
pub unsafety: ast::Unsafety,
|
||||||
pub trait_: ast::TraitRef,
|
pub trait_: ast::TraitRef,
|
||||||
pub id: ast::NodeId,
|
pub id: ast::NodeId,
|
||||||
|
pub attrs: Vec<ast::Attribute>,
|
||||||
|
pub whence: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Macro {
|
pub struct Macro {
|
||||||
|
@ -64,6 +64,7 @@ impl ItemType {
|
|||||||
clean::MacroItem(..) => ItemType::Macro,
|
clean::MacroItem(..) => ItemType::Macro,
|
||||||
clean::PrimitiveItem(..) => ItemType::Primitive,
|
clean::PrimitiveItem(..) => ItemType::Primitive,
|
||||||
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
|
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
|
||||||
|
clean::DefaultImplItem(..) => ItemType::Impl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clean::ImplItem(..) => {}
|
clean::DefaultImplItem(..) | clean::ImplItem(..) => {}
|
||||||
|
|
||||||
// tymethods/macros have no control over privacy
|
// tymethods/macros have no control over privacy
|
||||||
clean::MacroItem(..) | clean::TyMethodItem(..) => {}
|
clean::MacroItem(..) | clean::TyMethodItem(..) => {}
|
||||||
|
@ -362,7 +362,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||||||
let i = DefaultImpl {
|
let i = DefaultImpl {
|
||||||
unsafety: unsafety,
|
unsafety: unsafety,
|
||||||
trait_: trait_ref.clone(),
|
trait_: trait_ref.clone(),
|
||||||
id: item.id
|
id: item.id,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
whence: item.span,
|
||||||
};
|
};
|
||||||
om.def_traits.push(i);
|
om.def_traits.push(i);
|
||||||
}
|
}
|
||||||
|
5
src/test/run-make/rustdoc-default-impl/Makefile
Normal file
5
src/test/run-make/rustdoc-default-impl/Makefile
Normal file
@ -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)
|
17
src/test/run-make/rustdoc-default-impl/bar.rs
Normal file
17
src/test/run-make/rustdoc-default-impl/bar.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: bar::Bar>() {
|
||||||
|
}
|
||||||
|
|
33
src/test/run-make/rustdoc-default-impl/foo.rs
Normal file
33
src/test/run-make/rustdoc-default-impl/foo.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Bar>(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TypeId;
|
||||||
|
|
||||||
|
impl TypeId {
|
||||||
|
pub fn of<T: Bar + ?Sized>() -> TypeId {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user