diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index a4fd5bb92e697db2d576ffff55c8bda5e8a11bb4..2ed32b3388f17b2932283c4f1c181ff405664df9 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -26,6 +26,7 @@ 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; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index b3891432e2146e280317216cdedcb4f2aa877c16..2f7d766c28fa87c1e086f91fe52d02e278cdb83d 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -18,6 +18,7 @@ use rustc::metadata::decoder; use rustc::middle::def; use rustc::middle::ty; +use rustc::middle::subst; use rustc::middle::stability; use core; @@ -38,7 +39,8 @@ /// /// 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> { +pub fn try_inline(id: ast::NodeId, into: Option) + -> Option> { let cx = ::ctxtkey.get().unwrap(); let tcx = match cx.maybe_typed { core::Typed(ref tycx) => tycx, @@ -50,7 +52,17 @@ pub fn try_inline(id: ast::NodeId) -> Option> { }; 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, @@ -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() } @@ -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, } } @@ -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, } @@ -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(), }) @@ -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(), }) } @@ -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, @@ -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| { @@ -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(), @@ -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) { + 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, + }); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 57cda6c48178a3d42ab98c2b0b079b16b5780323..953b736f38b435375febc999fd4775ec1a5dadb8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -653,35 +653,12 @@ fn clean(&self) -> Generics { } } -impl Clean for ty::Generics { +impl<'a> Clean 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(), } } } @@ -770,7 +747,6 @@ pub enum SelfTy { SelfStatic, SelfValue, SelfBorrowed(Option, Mutability), - SelfOwned, SelfExplicit(Type), } @@ -994,28 +970,27 @@ impl Clean 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) } @@ -1030,7 +1005,7 @@ fn clean(&self) -> Item { 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(), }) @@ -1236,8 +1211,18 @@ fn clean(&self) -> Type { 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)), @@ -1778,7 +1763,7 @@ fn clean(&self) -> Vec { // 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 } @@ -1793,8 +1778,8 @@ fn clean(&self) -> Vec { 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)), } @@ -2117,3 +2102,29 @@ fn clean(&self) -> Stability { } } } + +fn lang_struct(did: Option, t: ty::t, name: &str, + fallback: fn(Box) -> 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 = 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()], + }], + }, + } +} diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 7f021510f4a0ed85838d81f036856df189155a29..032189dca4877323f6c6a9d6c79982192e3a1eec 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -80,7 +80,8 @@ pub struct CrateAnalysis { pub type Externs = HashMap>; /// Parses, resolves, and typechecks the given crate -fn get_ast_and_resolve(cpath: &Path, libs: HashSet, cfgs: Vec, externs: Externs) +fn get_ast_and_resolve(cpath: &Path, libs: HashSet, cfgs: Vec, + externs: Externs, triple: Option) -> (DocContext, CrateAnalysis) { use syntax::codemap::dummy_spanned; use rustc::driver::driver::{FileInput, @@ -99,6 +100,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet, cfgs: Vec, 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() }; @@ -151,9 +153,10 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet, cfgs: Vec, ext }) } -pub fn run_core(libs: HashSet, cfgs: Vec, externs: Externs, path: &Path) +pub fn run_core(libs: HashSet, cfgs: Vec, externs: Externs, + path: &Path, triple: Option) -> (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)); diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index e7f9370339922d3ae5abf583e0f84eee999c7879..c6d6843db5fb32d029f1a82b359831a32f06de62 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -444,8 +444,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { format!("[{}, ..{}]", **t, *s).as_slice()) } clean::Bottom => f.write("!".as_bytes()), - clean::Unique(ref t) => write!(f, "Box<{}>", **t), - clean::Managed(ref t) => write!(f, "Gc<{}>", **t), clean::RawPointer(m, ref t) => { write!(f, "*{}{}", RawMutableSpace(m), **t) } @@ -456,6 +454,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { }; write!(f, "&{}{}{}", lt, MutableSpace(mutability), **ty) } + clean::Unique(..) | clean::Managed(..) => { + fail!("should have been cleaned") + } } } } @@ -491,7 +492,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *selfty { clean::SelfStatic => {}, clean::SelfValue => args.push_str("self"), - clean::SelfOwned => args.push_str("self: Box"), clean::SelfBorrowed(Some(ref lt), mtbl) => { args.push_str(format!("&{} {}self", *lt, MutableSpace(mtbl)).as_slice()); diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index fc1e480f6afcf0731bad841f2a9e459e65a6d564..1869031dab3c2eca35df3e355089634ee1d3ef4b 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -357,8 +357,8 @@ }, 20); }); - $(document).off('keypress.searchnav'); - $(document).on('keypress.searchnav', function(e) { + $(document).off('keydown.searchnav'); + $(document).on('keydown.searchnav', function(e) { var $active = $results.filter('.highlighted'); if (e.which === 38) { // up diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 39b2511fde4f3e49ea6756224d8a8fbcb1f5564a..a89b76572875efba87edec77401683653a17b175 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -117,6 +117,7 @@ pub fn opts() -> Vec { optflag("", "test", "run code examples as tests"), optmulti("", "test-args", "arguments to pass to the test runner", "ARGS"), + optopt("", "target", "target triple to document", "TRIPLE"), optmulti("", "markdown-css", "CSS files to include via in a rendered Markdown file", "FILES"), optmulti("", "html-in-header", @@ -321,6 +322,7 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche .map(|s| Path::new(s.as_slice())) .collect(); let cfgs = matches.opt_strs("cfg"); + let triple = matches.opt_str("target"); let cr = Path::new(cratefile); info!("starting to run rustc"); @@ -329,7 +331,8 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche core::run_core(libs.move_iter().collect(), cfgs, externs, - &cr) + &cr, + triple) }).map_err(|boxed_any|format!("{:?}", boxed_any)).unwrap(); info!("finished with rustc"); analysiskey.replace(Some(analysis)); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 594a235339669694357c7693e11a061dfa1cf6c7..d28069da6ba06e5acaf86e4f1a9e7d6e38d096f1 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -192,13 +192,16 @@ fn visit_view_path(&mut self, path: Gc, om: &mut Module, please_inline: bool) -> Option> { match path.node { - ast::ViewPathSimple(_, _, id) => { - if self.resolve_id(id, false, om, please_inline) { return None } + ast::ViewPathSimple(dst, _, id) => { + if self.resolve_id(id, Some(dst), false, om, please_inline) { + return None + } } ast::ViewPathList(ref p, ref paths, ref b) => { let mut mine = Vec::new(); for path in paths.iter() { - if !self.resolve_id(path.node.id(), false, om, please_inline) { + if !self.resolve_id(path.node.id(), None, false, om, + please_inline) { mine.push(path.clone()); } } @@ -212,14 +215,16 @@ fn visit_view_path(&mut self, path: Gc, // these are feature gated anyway ast::ViewPathGlob(_, id) => { - if self.resolve_id(id, true, om, please_inline) { return None } + if self.resolve_id(id, None, true, om, please_inline) { + return None + } } } return Some(path); } - fn resolve_id(&mut self, id: ast::NodeId, glob: bool, - om: &mut Module, please_inline: bool) -> bool { + fn resolve_id(&mut self, id: ast::NodeId, renamed: Option, + glob: bool, om: &mut Module, please_inline: bool) -> bool { let tcx = match self.cx.maybe_typed { core::Typed(ref tcx) => tcx, core::NotTyped(_) => return false @@ -235,6 +240,15 @@ fn resolve_id(&mut self, id: ast::NodeId, glob: bool, match tcx.map.get(def.node) { ast_map::NodeItem(it) => { + let it = match renamed { + Some(ident) => { + box(GC) ast::Item { + ident: ident, + ..(*it).clone() + } + } + None => it, + }; if glob { match it.node { ast::ItemMod(ref m) => {