Skip to content

Fix some assorted rustdoc bugs. #15982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 26, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/libcore/fmt/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use iter::Iterator; // NOTE(stage0): Remove after snapshot.
use option::{Some, None}; // NOTE(stage0): Remove after snapshot.

/// A type that represents a specific radix
#[doc(hidden)]
trait GenericRadix {
/// The number of digits.
fn base(&self) -> u8;
Expand Down
95 changes: 69 additions & 26 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use rustc::metadata::csearch;
use rustc::metadata::decoder;
use rustc::middle::def;
use rustc::middle::ty;
use rustc::middle::subst;
use rustc::middle::stability;

use core;
Expand All @@ -38,7 +39,8 @@ use super::Clean;
///
/// The returned value is `None` if the `id` could not be inlined, and `Some`
/// of a vector of items if it was successfully expanded.
pub fn try_inline(id: ast::NodeId) -> Option<Vec<clean::Item>> {
pub fn try_inline(id: ast::NodeId, into: Option<ast::Ident>)
-> Option<Vec<clean::Item>> {
let cx = ::ctxtkey.get().unwrap();
let tcx = match cx.maybe_typed {
core::Typed(ref tycx) => tycx,
Expand All @@ -50,7 +52,17 @@ pub fn try_inline(id: ast::NodeId) -> Option<Vec<clean::Item>> {
};
let did = def.def_id();
if ast_util::is_local(did) { return None }
try_inline_def(&**cx, tcx, def)
try_inline_def(&**cx, tcx, def).map(|vec| {
vec.move_iter().map(|mut item| {
match into {
Some(into) if item.name.is_some() => {
item.name = Some(into.clean());
}
_ => {}
}
item
}).collect()
})
}

fn try_inline_def(cx: &core::DocContext,
Expand Down Expand Up @@ -163,7 +175,7 @@ pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait {
});

clean::Trait {
generics: def.generics.clean(),
generics: (&def.generics, subst::TypeSpace).clean(),
methods: methods.collect(),
parents: parents.collect()
}
Expand All @@ -178,7 +190,7 @@ fn build_external_function(tcx: &ty::ctxt,
ty::ty_bare_fn(ref f) => (did, &f.sig).clean(),
_ => fail!("bad function"),
},
generics: t.generics.clean(),
generics: (&t.generics, subst::FnSpace).clean(),
fn_style: style,
}
}
Expand All @@ -196,7 +208,7 @@ fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct {
[ref f, ..] if f.name == unnamed_field.name => doctree::Tuple,
_ => doctree::Plain,
},
generics: t.generics.clean(),
generics: (&t.generics, subst::TypeSpace).clean(),
fields: fields.iter().map(|f| f.clean()).collect(),
fields_stripped: false,
}
Expand All @@ -207,7 +219,7 @@ fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
match ty::get(t.ty).sty {
ty::ty_enum(edid, _) if !csearch::is_typedef(&tcx.sess.cstore, did) => {
return clean::EnumItem(clean::Enum {
generics: t.generics.clean(),
generics: (&t.generics, subst::TypeSpace).clean(),
variants_stripped: false,
variants: ty::enum_variants(tcx, edid).clean(),
})
Expand All @@ -217,7 +229,7 @@ fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {

clean::TypedefItem(clean::Typedef {
type_: t.ty.clean(),
generics: t.generics.clean(),
generics: (&t.generics, subst::TypeSpace).clean(),
})
}

Expand Down Expand Up @@ -278,6 +290,17 @@ fn build_impl(cx: &core::DocContext,
}

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(tcx, t.def_id);
if trait_attrs.iter().any(|a| is_doc_hidden(a)) {
return None
}
}
None => {}
}

let attrs = load_attrs(tcx, did);
let ty = ty::lookup_item_type(tcx, did);
let methods = csearch::get_impl_methods(&tcx.sess.cstore,
Expand All @@ -302,7 +325,7 @@ fn build_impl(cx: &core::DocContext,
};
Some(item)
}).collect();
Some(clean::Item {
return Some(clean::Item {
inner: clean::ImplItem(clean::Impl {
derived: clean::detect_derived(attrs.as_slice()),
trait_: associated_trait.clean().map(|bound| {
Expand All @@ -312,7 +335,7 @@ fn build_impl(cx: &core::DocContext,
}
}),
for_: ty.ty.clean(),
generics: ty.generics.clean(),
generics: (&ty.generics, subst::TypeSpace).clean(),
methods: methods,
}),
source: clean::Span::empty(),
Expand All @@ -321,33 +344,53 @@ fn build_impl(cx: &core::DocContext,
visibility: Some(ast::Inherited),
stability: stability::lookup(tcx, did).clean(),
def_id: did,
})
});

fn is_doc_hidden(a: &clean::Attribute) -> bool {
match *a {
clean::List(ref name, ref inner) if name.as_slice() == "doc" => {
inner.iter().any(|a| {
match *a {
clean::Word(ref s) => s.as_slice() == "hidden",
_ => false,
}
})
}
_ => false
}
}
}

fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
did: ast::DefId) -> clean::Module {
let mut items = Vec::new();
fill_in(cx, tcx, did, &mut items);
return clean::Module {
items: items,
is_crate: false,
};

// FIXME: this doesn't handle reexports inside the module itself.
// Should they be handled?
csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, vis| {
if vis != ast::Public { return }
match def {
decoder::DlDef(def) => {
match try_inline_def(cx, tcx, def) {
Some(i) => items.extend(i.move_iter()),
None => {}
fn fill_in(cx: &core::DocContext, tcx: &ty::ctxt, did: ast::DefId,
items: &mut Vec<clean::Item>) {
csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, vis| {
match def {
decoder::DlDef(def::DefForeignMod(did)) => {
fill_in(cx, tcx, did, items);
}
decoder::DlDef(def) if vis == ast::Public => {
match try_inline_def(cx, tcx, def) {
Some(i) => items.extend(i.move_iter()),
None => {}
}
}
decoder::DlDef(..) => {}
// All impls were inlined above
decoder::DlImpl(..) => {}
decoder::DlField => fail!("unimplemented field"),
}
// All impls were inlined above
decoder::DlImpl(..) => {}
decoder::DlField => fail!("unimplemented field"),
}
});

clean::Module {
items: items,
is_crate: false,
});
}
}

Expand Down
95 changes: 53 additions & 42 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,35 +653,12 @@ impl Clean<Generics> for ast::Generics {
}
}

impl Clean<Generics> for ty::Generics {
impl<'a> Clean<Generics> for (&'a ty::Generics, subst::ParamSpace) {
fn clean(&self) -> Generics {
// In the type space, generics can come in one of multiple
// namespaces. This means that e.g. for fn items the type
// parameters will live in FnSpace, but for types the
// parameters will live in TypeSpace (trait definitions also
// define a parameter in SelfSpace). *Method* definitions are
// the one exception: they combine the TypeSpace parameters
// from the enclosing impl/trait with their own FnSpace
// parameters.
//
// In general, when we clean, we are trying to produce the
// "user-facing" generics. Hence we select the most specific
// namespace that is occupied, ignoring SelfSpace because it
// is implicit.

let space = {
if !self.types.is_empty_in(subst::FnSpace) ||
!self.regions.is_empty_in(subst::FnSpace)
{
subst::FnSpace
} else {
subst::TypeSpace
}
};

let (me, space) = *self;
Generics {
type_params: Vec::from_slice(self.types.get_slice(space)).clean(),
lifetimes: Vec::from_slice(self.regions.get_slice(space)).clean(),
type_params: Vec::from_slice(me.types.get_slice(space)).clean(),
lifetimes: Vec::from_slice(me.regions.get_slice(space)).clean(),
}
}
}
Expand Down Expand Up @@ -770,7 +747,6 @@ pub enum SelfTy {
SelfStatic,
SelfValue,
SelfBorrowed(Option<Lifetime>, Mutability),
SelfOwned,
SelfExplicit(Type),
}

Expand Down Expand Up @@ -994,28 +970,27 @@ impl Clean<Item> for ty::Method {
fn clean(&self) -> Item {
let cx = get_cx();
let (self_, sig) = match self.explicit_self {
ty::StaticExplicitSelfCategory => (ast::SelfStatic.clean(), self.fty.sig.clone()),
ty::StaticExplicitSelfCategory => (ast::SelfStatic.clean(),
self.fty.sig.clone()),
s => {
let sig = ty::FnSig {
inputs: Vec::from_slice(self.fty.sig.inputs.slice_from(1)),
..self.fty.sig.clone()
};
let s = match s {
ty::ByValueExplicitSelfCategory => SelfValue,
ty::ByReferenceExplicitSelfCategory(..) => {
match ty::get(self.fty.sig.inputs[0]).sty {
ty::ty_rptr(r, mt) => {
SelfBorrowed(r.clean(), mt.mutbl.clean())
}
_ => {
// FIXME(pcwalton): This is wrong.
SelfStatic
}
_ => unreachable!(),
}
}
_ => {
// FIXME(pcwalton): This is wrong.
SelfStatic
ty::ByBoxExplicitSelfCategory => {
SelfExplicit(self.fty.sig.inputs[0].clean())
}
ty::StaticExplicitSelfCategory => unreachable!(),
};
(s, sig)
}
Expand All @@ -1030,7 +1005,7 @@ impl Clean<Item> for ty::Method {
source: Span::empty(),
inner: TyMethodItem(TyMethod {
fn_style: self.fty.fn_style,
generics: self.generics.clean(),
generics: (&self.generics, subst::FnSpace).clean(),
self_: self_,
decl: (self.def_id, &sig).clean(),
})
Expand Down Expand Up @@ -1236,8 +1211,18 @@ impl Clean<Type> for ty::t {
ty::ty_float(ast::TyF32) => Primitive(F32),
ty::ty_float(ast::TyF64) => Primitive(F64),
ty::ty_str => Primitive(Str),
ty::ty_box(t) => Managed(box t.clean()),
ty::ty_uniq(t) => Unique(box t.clean()),
ty::ty_box(t) => {
let gc_did = get_cx().tcx_opt().and_then(|tcx| {
tcx.lang_items.gc()
});
lang_struct(gc_did, t, "Gc", Managed)
}
ty::ty_uniq(t) => {
let box_did = get_cx().tcx_opt().and_then(|tcx| {
tcx.lang_items.owned_box()
});
lang_struct(box_did, t, "Box", Unique)
}
ty::ty_vec(mt, None) => Vector(box mt.ty.clean()),
ty::ty_vec(mt, Some(i)) => FixedVector(box mt.ty.clean(),
format!("{}", i)),
Expand Down Expand Up @@ -1778,7 +1763,7 @@ impl Clean<Vec<Item>> for ast::ViewItem {
// to keep any non-inlineable reexports so they can be
// listed in the documentation.
let remaining = list.iter().filter(|path| {
match inline::try_inline(path.node.id()) {
match inline::try_inline(path.node.id(), None) {
Some(items) => {
ret.extend(items.move_iter()); false
}
Expand All @@ -1793,8 +1778,8 @@ impl Clean<Vec<Item>> for ast::ViewItem {
ret.push(convert(&ast::ViewItemUse(box(GC) path)));
}
}
ast::ViewPathSimple(_, _, id) => {
match inline::try_inline(id) {
ast::ViewPathSimple(ident, _, id) => {
match inline::try_inline(id, Some(ident)) {
Some(items) => ret.extend(items.move_iter()),
None => ret.push(convert(&self.node)),
}
Expand Down Expand Up @@ -2117,3 +2102,29 @@ impl Clean<Stability> for attr::Stability {
}
}
}

fn lang_struct(did: Option<ast::DefId>, t: ty::t, name: &str,
fallback: fn(Box<Type>) -> Type) -> Type {
let did = match did {
Some(did) => did,
None => return fallback(box t.clean()),
};
let fqn = csearch::get_item_path(get_cx().tcx(), did);
let fqn: Vec<String> = fqn.move_iter().map(|i| {
i.to_string()
}).collect();
get_cx().external_paths.borrow_mut().get_mut_ref()
.insert(did, (fqn, TypeStruct));
ResolvedPath {
typarams: None,
did: did,
path: Path {
global: false,
segments: vec![PathSegment {
name: name.to_string(),
lifetimes: vec![],
types: vec![t.clean()],
}],
},
}
}
9 changes: 6 additions & 3 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ pub struct CrateAnalysis {
pub type Externs = HashMap<String, Vec<String>>;

/// Parses, resolves, and typechecks the given crate
fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>, externs: Externs)
fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>,
externs: Externs, triple: Option<String>)
-> (DocContext, CrateAnalysis) {
use syntax::codemap::dummy_spanned;
use rustc::driver::driver::{FileInput,
Expand All @@ -99,6 +100,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>, ext
crate_types: vec!(driver::config::CrateTypeRlib),
lint_opts: vec!((warning_lint, lint::Allow)),
externs: externs,
target_triple: triple.unwrap_or(driver::driver::host_triple().to_string()),
..rustc::driver::config::basic_options().clone()
};

Expand Down Expand Up @@ -151,9 +153,10 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>, ext
})
}

pub fn run_core(libs: HashSet<Path>, cfgs: Vec<String>, externs: Externs, path: &Path)
pub fn run_core(libs: HashSet<Path>, cfgs: Vec<String>, externs: Externs,
path: &Path, triple: Option<String>)
-> (clean::Crate, CrateAnalysis) {
let (ctxt, analysis) = get_ast_and_resolve(path, libs, cfgs, externs);
let (ctxt, analysis) = get_ast_and_resolve(path, libs, cfgs, externs, triple);
let ctxt = box(GC) ctxt;
super::ctxtkey.replace(Some(ctxt));

Expand Down
Loading