Skip to content

Commit 4e25765

Browse files
committed
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.
1 parent c9b03c2 commit 4e25765

File tree

11 files changed

+130
-14
lines changed

11 files changed

+130
-14
lines changed

src/librustc/metadata/csearch.rs

+5
Original file line numberDiff line numberDiff line change
@@ -411,3 +411,8 @@ pub fn is_defaulted_trait(cstore: &cstore::CStore, trait_def_id: ast::DefId) ->
411411
let cdata = cstore.get_crate_data(trait_def_id.krate);
412412
decoder::is_defaulted_trait(&*cdata, trait_def_id.node)
413413
}
414+
415+
pub fn is_default_impl(cstore: &cstore::CStore, impl_did: ast::DefId) -> bool {
416+
let cdata = cstore.get_crate_data(impl_did.krate);
417+
decoder::is_default_impl(&*cdata, impl_did.node)
418+
}

src/librustc/metadata/decoder.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1537,13 +1537,18 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
15371537
}
15381538
}
15391539

1540-
pub fn is_defaulted_trait<'tcx>(cdata: Cmd, trait_id: ast::NodeId) -> bool {
1540+
pub fn is_defaulted_trait(cdata: Cmd, trait_id: ast::NodeId) -> bool {
15411541
let trait_doc = lookup_item(trait_id, cdata.data());
15421542
assert!(item_family(trait_doc) == Family::Trait);
15431543
let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait);
15441544
reader::doc_as_u8(defaulted_doc) != 0
15451545
}
15461546

1547+
pub fn is_default_impl(cdata: Cmd, impl_id: ast::NodeId) -> bool {
1548+
let impl_doc = lookup_item(impl_id, cdata.data());
1549+
item_family(impl_doc) == Family::DefaultImpl
1550+
}
1551+
15471552
pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
15481553
let crate_doc = rbml::Doc::new(metadata);
15491554
let cm_doc = reader::get_doc(crate_doc, tag_codemap);

src/librustdoc/clean/inline.rs

+30-11
Original file line numberDiff line numberDiff line change
@@ -259,26 +259,43 @@ fn build_impls(cx: &DocContext, tcx: &ty::ctxt,
259259
impls.into_iter().filter_map(|a| a).collect()
260260
}
261261

262-
fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
262+
fn build_impl(cx: &DocContext,
263+
tcx: &ty::ctxt,
263264
did: ast::DefId) -> Option<clean::Item> {
264265
if !cx.inlined.borrow_mut().as_mut().unwrap().insert(did) {
265266
return None
266267
}
267268

269+
let attrs = load_attrs(cx, tcx, did);
268270
let associated_trait = csearch::get_impl_trait(tcx, did);
269-
// If this is an impl for a #[doc(hidden)] trait, be sure to not inline it.
270-
match associated_trait {
271-
Some(ref t) => {
272-
let trait_attrs = load_attrs(cx, tcx, t.def_id);
273-
if trait_attrs.iter().any(|a| is_doc_hidden(a)) {
274-
return None
275-
}
271+
if let Some(ref t) = associated_trait {
272+
// If this is an impl for a #[doc(hidden)] trait, be sure to not inline
273+
let trait_attrs = load_attrs(cx, tcx, t.def_id);
274+
if trait_attrs.iter().any(|a| is_doc_hidden(a)) {
275+
return None
276276
}
277-
None => {}
278277
}
279278

280-
let attrs = load_attrs(cx, tcx, did);
281-
let ty = ty::lookup_item_type(tcx, did);
279+
// If this is a defaulted impl, then bail out early here
280+
if csearch::is_default_impl(&tcx.sess.cstore, did) {
281+
return Some(clean::Item {
282+
inner: clean::DefaultImplItem(clean::DefaultImpl {
283+
// FIXME: this should be decoded
284+
unsafety: ast::Unsafety::Normal,
285+
trait_: match associated_trait.as_ref().unwrap().clean(cx) {
286+
clean::TraitBound(polyt, _) => polyt.trait_,
287+
clean::RegionBound(..) => unreachable!(),
288+
},
289+
}),
290+
source: clean::Span::empty(),
291+
name: None,
292+
attrs: attrs,
293+
visibility: Some(ast::Inherited),
294+
stability: stability::lookup(tcx, did).clean(cx),
295+
def_id: did,
296+
});
297+
}
298+
282299
let predicates = ty::lookup_predicates(tcx, did);
283300
let trait_items = csearch::get_impl_items(&tcx.sess.cstore, did)
284301
.iter()
@@ -330,8 +347,10 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
330347
}
331348
}).collect();
332349
let polarity = csearch::get_impl_polarity(tcx, did);
350+
let ty = ty::lookup_item_type(tcx, did);
333351
return Some(clean::Item {
334352
inner: clean::ImplItem(clean::Impl {
353+
unsafety: ast::Unsafety::Normal, // FIXME: this should be decoded
335354
derived: clean::detect_derived(&attrs),
336355
trait_: associated_trait.clean(cx).map(|bound| {
337356
match bound {

src/librustdoc/clean/mod.rs

+27
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ pub enum ItemEnum {
337337
MacroItem(Macro),
338338
PrimitiveItem(PrimitiveType),
339339
AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
340+
DefaultImplItem(DefaultImpl),
340341
}
341342

342343
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -367,6 +368,7 @@ impl Clean<Item> for doctree::Module {
367368
items.extend(self.traits.iter().map(|x| x.clean(cx)));
368369
items.extend(self.impls.iter().map(|x| x.clean(cx)));
369370
items.extend(self.macros.iter().map(|x| x.clean(cx)));
371+
items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
370372

371373
// determine if we should display the inner contents or
372374
// the outer `mod` item for the source code.
@@ -2079,6 +2081,7 @@ impl Clean<ImplPolarity> for ast::ImplPolarity {
20792081

20802082
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
20812083
pub struct Impl {
2084+
pub unsafety: ast::Unsafety,
20822085
pub generics: Generics,
20832086
pub trait_: Option<Type>,
20842087
pub for_: Type,
@@ -2101,6 +2104,7 @@ impl Clean<Item> for doctree::Impl {
21012104
visibility: self.vis.clean(cx),
21022105
stability: self.stab.clean(cx),
21032106
inner: ImplItem(Impl {
2107+
unsafety: self.unsafety,
21042108
generics: self.generics.clean(cx),
21052109
trait_: self.trait_.clean(cx),
21062110
for_: self.for_.clean(cx),
@@ -2112,6 +2116,29 @@ impl Clean<Item> for doctree::Impl {
21122116
}
21132117
}
21142118

2119+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2120+
pub struct DefaultImpl {
2121+
pub unsafety: ast::Unsafety,
2122+
pub trait_: Type,
2123+
}
2124+
2125+
impl Clean<Item> for doctree::DefaultImpl {
2126+
fn clean(&self, cx: &DocContext) -> Item {
2127+
Item {
2128+
name: None,
2129+
attrs: self.attrs.clean(cx),
2130+
source: self.whence.clean(cx),
2131+
def_id: ast_util::local_def(self.id),
2132+
visibility: Some(ast::Public),
2133+
stability: None,
2134+
inner: DefaultImplItem(DefaultImpl {
2135+
unsafety: self.unsafety,
2136+
trait_: self.trait_.clean(cx),
2137+
}),
2138+
}
2139+
}
2140+
}
2141+
21152142
impl Clean<Item> for doctree::ExternCrate {
21162143
fn clean(&self, cx: &DocContext) -> Item {
21172144
Item {

src/librustdoc/doctree.rs

+2
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ pub struct DefaultImpl {
202202
pub unsafety: ast::Unsafety,
203203
pub trait_: ast::TraitRef,
204204
pub id: ast::NodeId,
205+
pub attrs: Vec<ast::Attribute>,
206+
pub whence: Span,
205207
}
206208

207209
pub struct Macro {

src/librustdoc/html/item_type.rs

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ impl ItemType {
6464
clean::MacroItem(..) => ItemType::Macro,
6565
clean::PrimitiveItem(..) => ItemType::Primitive,
6666
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
67+
clean::DefaultImplItem(..) => ItemType::Impl,
6768
}
6869
}
6970

src/librustdoc/passes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
176176
return None;
177177
}
178178
}
179-
clean::ImplItem(..) => {}
179+
clean::DefaultImplItem(..) | clean::ImplItem(..) => {}
180180

181181
// tymethods/macros have no control over privacy
182182
clean::MacroItem(..) | clean::TyMethodItem(..) => {}

src/librustdoc/visit_ast.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
362362
let i = DefaultImpl {
363363
unsafety: unsafety,
364364
trait_: trait_ref.clone(),
365-
id: item.id
365+
id: item.id,
366+
attrs: item.attrs.clone(),
367+
whence: item.span,
366368
};
367369
om.def_traits.push(i);
368370
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-include ../tools.mk
2+
3+
all: foo.rs bar.rs
4+
$(RUSTC) foo.rs --crate-type lib
5+
$(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc bar.rs -L $(TMPDIR)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern crate foo;
12+
13+
pub use foo::bar;
14+
15+
pub fn wut<T: bar::Bar>() {
16+
}
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub mod bar {
12+
use std::marker;
13+
14+
pub trait Bar: marker::MarkerTrait + 'static {}
15+
16+
impl Bar for .. {}
17+
18+
pub trait Foo {
19+
fn foo(&self) {}
20+
}
21+
22+
impl Foo {
23+
pub fn test<T: Bar>(&self) {}
24+
}
25+
26+
pub struct TypeId;
27+
28+
impl TypeId {
29+
pub fn of<T: Bar + ?Sized>() -> TypeId {
30+
panic!()
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)