提交 4e0b9369 编写于 作者: B bors

auto merge of #14513 : alexcrichton/rust/rustdoc-primitives, r=huonw

This is currently rebased on top of #14478, but that's just to preemptively avoid rebase conflicts and to provide a better preview. This can land independently of that PR.

This change crates a dedicated page in rustdoc for primitive types to outline everything you can do with them (at least in a basic way).

* Preview - http://people.mozilla.org/~acrichton/doc/
* Exhibit A - http://people.mozilla.org/~acrichton/doc/std/#primitives
* Exhibit B - http://people.mozilla.org/~acrichton/doc/std/primitive.str.html
* Exhibit C - http://people.mozilla.org/~acrichton/doc/std/primitive.slice.html

Please don't hesitate to be nitpickity, it's easy to overlook a thing here or there!
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
**Int to string** **Int to string**
Use [`ToStr`](../std/to_str/trait.ToStr.html). Use [`ToStr`](std/to_str/trait.ToStr.html).
~~~ ~~~
let x: int = 42; let x: int = 42;
...@@ -13,8 +13,8 @@ let y: String = x.to_str().to_string(); ...@@ -13,8 +13,8 @@ let y: String = x.to_str().to_string();
**String to int** **String to int**
Use [`FromStr`](../std/from_str/trait.FromStr.html), and its helper function, Use [`FromStr`](std/from_str/trait.FromStr.html), and its helper function,
[`from_str`](../std/from_str/fn.from_str.html). [`from_str`](std/from_str/fn.from_str.html).
~~~ ~~~
let x: Option<int> = from_str("42"); let x: Option<int> = from_str("42");
...@@ -35,8 +35,8 @@ let y: String = format!("{:X}", x); // uppercase hexadecimal ...@@ -35,8 +35,8 @@ let y: String = format!("{:X}", x); // uppercase hexadecimal
**String to int, in non-base-10** **String to int, in non-base-10**
Use [`FromStrRadix`](../std/num/trait.FromStrRadix.html), and its helper Use [`FromStrRadix`](std/num/trait.FromStrRadix.html), and its helper
function, [`from_str_radix`](../std/num/fn.from_str_radix.html). function, [`from_str_radix`](std/num/fn.from_str_radix.html).
~~~ ~~~
use std::num; use std::num;
...@@ -48,7 +48,7 @@ let y: i64 = x.unwrap(); ...@@ -48,7 +48,7 @@ let y: i64 = x.unwrap();
**Vector of Bytes to String** **Vector of Bytes to String**
To return a Borrowed String Slice (&str) use the str helper function To return a Borrowed String Slice (&str) use the str helper function
[`from_utf8`](../std/str/fn.from_utf8.html). [`from_utf8`](std/str/fn.from_utf8.html).
~~~ ~~~
use std::str; use std::str;
...@@ -58,7 +58,7 @@ let x: &str = str::from_utf8(bytes).unwrap(); ...@@ -58,7 +58,7 @@ let x: &str = str::from_utf8(bytes).unwrap();
~~~ ~~~
To return an Owned String use the str helper function To return an Owned String use the str helper function
[`from_utf8_owned`](../std/str/fn.from_utf8_owned.html). [`from_utf8_owned`](std/str/fn.from_utf8_owned.html).
~~~ ~~~
use std::str; use std::str;
...@@ -68,8 +68,8 @@ let x: Option<String> = ...@@ -68,8 +68,8 @@ let x: Option<String> =
let y: String = x.unwrap(); let y: String = x.unwrap();
~~~ ~~~
To return a [`MaybeOwned`](../std/str/enum.MaybeOwned.html) use the str helper To return a [`MaybeOwned`](std/str/type.MaybeOwned.html) use the str helper
function [`from_utf8_lossy`](../std/str/fn.from_utf8_owned.html). function [`from_utf8_lossy`](std/str/fn.from_utf8_owned.html).
This function also replaces non-valid utf-8 sequences with U+FFFD replacement This function also replaces non-valid utf-8 sequences with U+FFFD replacement
character. character.
...@@ -85,11 +85,11 @@ let y = str::from_utf8_lossy(x); ...@@ -85,11 +85,11 @@ let y = str::from_utf8_lossy(x);
## How do I read from a file? ## How do I read from a file?
Use Use
[`File::open`](../std/io/fs/struct.File.html#method.open) [`File::open`](std/io/fs/struct.File.html#method.open)
to create a to create a
[`File`](../std/io/fs/struct.File.html) [`File`](std/io/fs/struct.File.html)
struct, which implements the struct, which implements the
[`Reader`](../std/io/trait.Reader.html) [`Reader`](std/io/trait.Reader.html)
trait. trait.
~~~ {.ignore} ~~~ {.ignore}
...@@ -103,7 +103,8 @@ let reader : File = File::open(&path).unwrap_or_else(on_error); ...@@ -103,7 +103,8 @@ let reader : File = File::open(&path).unwrap_or_else(on_error);
## How do I iterate over the lines in a file? ## How do I iterate over the lines in a file?
Use the [`lines`](../std/io/trait.Buffer.html#method.lines) method on a [`BufferedReader`](../std/io/buffered/struct.BufferedReader.html). Use the [`lines`](std/io/trait.Buffer.html#method.lines) method on a
[`BufferedReader`](std/io/struct.BufferedReader.html).
~~~ ~~~
use std::io::BufferedReader; use std::io::BufferedReader;
...@@ -121,7 +122,7 @@ for line in reader.lines() { ...@@ -121,7 +122,7 @@ for line in reader.lines() {
## How do I search for a substring? ## How do I search for a substring?
Use the [`find_str`](../std/str/trait.StrSlice.html#tymethod.find_str) method. Use the [`find_str`](std/str/trait.StrSlice.html#tymethod.find_str) method.
~~~ ~~~
let str = "Hello, this is some random string"; let str = "Hello, this is some random string";
...@@ -132,7 +133,7 @@ let index: Option<uint> = str.find_str("rand"); ...@@ -132,7 +133,7 @@ let index: Option<uint> = str.find_str("rand");
## How do I get the length of a vector? ## How do I get the length of a vector?
The [`Container`](../std/container/trait.Container.html) trait provides the `len` method. The [`Container`](std/container/trait.Container.html) trait provides the `len` method.
~~~ ~~~
let u: Vec<u32> = vec![0, 1, 2]; let u: Vec<u32> = vec![0, 1, 2];
...@@ -144,7 +145,7 @@ println!("u: {}, v: {}, w: {}", u.len(), v.len(), w.len()); // 3, 4, 5 ...@@ -144,7 +145,7 @@ println!("u: {}, v: {}, w: {}", u.len(), v.len(), w.len()); // 3, 4, 5
## How do I iterate over a vector? ## How do I iterate over a vector?
Use the [`iter`](../std/vec/trait.ImmutableVector.html#tymethod.iter) method. Use the [`iter`](std/slice/trait.ImmutableVector.html#tymethod.iter) method.
~~~ ~~~
let values: Vec<int> = vec![1, 2, 3, 4, 5]; let values: Vec<int> = vec![1, 2, 3, 4, 5];
...@@ -153,9 +154,9 @@ for value in values.iter() { // value: &int ...@@ -153,9 +154,9 @@ for value in values.iter() { // value: &int
} }
~~~ ~~~
(See also [`mut_iter`](../std/vec/trait.MutableVector.html#tymethod.mut_iter) (See also [`mut_iter`](std/slice/trait.MutableVector.html#tymethod.mut_iter)
which yields `&mut int` and which yields `&mut int` and
[`move_iter`](../std/vec/trait.OwnedVector.html#tymethod.move_iter) which yields [`move_iter`](std/slice/trait.OwnedVector.html#tymethod.move_iter) which yields
`int` while consuming the `values` vector.) `int` while consuming the `values` vector.)
# Type system # Type system
......
...@@ -21,7 +21,7 @@ Some examples that demonstrate different aspects of the language: ...@@ -21,7 +21,7 @@ Some examples that demonstrate different aspects of the language:
* The extra library's [json] module. Enums and pattern matching * The extra library's [json] module. Enums and pattern matching
[sprocketnes]: https://github.com/pcwalton/sprocketnes [sprocketnes]: https://github.com/pcwalton/sprocketnes
[hash]: https://github.com/mozilla/rust/blob/master/src/libstd/hash.rs [hash]: https://github.com/mozilla/rust/blob/master/src/libstd/hash/mod.rs
[HashMap]: https://github.com/mozilla/rust/blob/master/src/libcollections/hashmap.rs [HashMap]: https://github.com/mozilla/rust/blob/master/src/libcollections/hashmap.rs
[json]: https://github.com/mozilla/rust/blob/master/src/libserialize/json.rs [json]: https://github.com/mozilla/rust/blob/master/src/libserialize/json.rs
...@@ -149,6 +149,6 @@ example we were setting RUST_LOG to the name of the hello crate. Multiple paths ...@@ -149,6 +149,6 @@ example we were setting RUST_LOG to the name of the hello crate. Multiple paths
can be combined to control the exact logging you want to see. For example, when can be combined to control the exact logging you want to see. For example, when
debugging linking in the compiler you might set debugging linking in the compiler you might set
`RUST_LOG=rustc::metadata::creader,rustc::util::filesearch,rustc::back::rpath` `RUST_LOG=rustc::metadata::creader,rustc::util::filesearch,rustc::back::rpath`
For a full description see [the language reference][1]. For a full description see [the logging crate][1].
[1]:http://doc.rust-lang.org/doc/master/rust.html#logging-system [1]:log/index.html
...@@ -499,9 +499,9 @@ shouldn't get triggered. ...@@ -499,9 +499,9 @@ shouldn't get triggered.
The second of these two functions, `eh_personality`, is used by the failure The second of these two functions, `eh_personality`, is used by the failure
mechanisms of the compiler. This is often mapped to GCC's personality function mechanisms of the compiler. This is often mapped to GCC's personality function
(see the [libstd implementation](../std/rt/unwind/) for more information), but (see the [libstd implementation](std/rt/unwind/index.html) for more
crates which do not trigger failure can be assured that this function is never information), but crates which do not trigger failure can be assured that this
called. function is never called.
## Using libcore ## Using libcore
...@@ -511,7 +511,8 @@ called. ...@@ -511,7 +511,8 @@ called.
With the above techniques, we've got a bare-metal executable running some Rust With the above techniques, we've got a bare-metal executable running some Rust
code. There is a good deal of functionality provided by the standard library, code. There is a good deal of functionality provided by the standard library,
however, that is necessary to be productive in Rust. If the standard library is however, that is necessary to be productive in Rust. If the standard library is
not sufficient, then [libcore](../core/) is designed to be used instead. not sufficient, then [libcore](core/index.html) is designed to be used
instead.
The core library has very few dependencies and is much more portable than the The core library has very few dependencies and is much more portable than the
standard library itself. Additionally, the core library has most of the standard library itself. Additionally, the core library has most of the
......
...@@ -97,6 +97,7 @@ ...@@ -97,6 +97,7 @@
pub mod rc; pub mod rc;
#[cfg(not(test))] #[cfg(not(test))]
#[doc(hidden)]
mod std { mod std {
pub use core::fmt; pub use core::fmt;
pub use core::option; pub use core::option;
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
//! //!
//! A `to_bit` conversion function. //! A `to_bit` conversion function.
#![doc(primitive = "bool")]
use num::{Int, one, zero}; use num::{Int, one, zero};
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
//! and, as such, should be performed via the `from_u32` function.. //! and, as such, should be performed via the `from_u32` function..
#![allow(non_snake_case_functions)] #![allow(non_snake_case_functions)]
#![doc(primitive = "char")]
use mem::transmute; use mem::transmute;
use option::{None, Option, Some}; use option::{None, Option, Some};
......
...@@ -134,10 +134,12 @@ ...@@ -134,10 +134,12 @@
// crate. // crate.
mod should_not_exist; mod should_not_exist;
#[doc(hidden)]
mod core { mod core {
pub use failure; pub use failure;
} }
#[doc(hidden)]
mod std { mod std {
pub use clone; pub use clone;
pub use cmp; pub use cmp;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for 32-bits floats (`f32` type) //! Operations and constants for 32-bits floats (`f32` type)
#![doc(primitive = "f32")]
use intrinsics; use intrinsics;
use mem; use mem;
use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for 64-bits floats (`f64` type) //! Operations and constants for 64-bits floats (`f64` type)
#![doc(primitive = "f64")]
use intrinsics; use intrinsics;
use mem; use mem;
use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
......
...@@ -10,5 +10,7 @@ ...@@ -10,5 +10,7 @@
//! Operations and constants for signed 16-bits integers (`i16` type) //! Operations and constants for signed 16-bits integers (`i16` type)
#![doc(primitive = "i16")]
int_module!(i16, 16) int_module!(i16, 16)
...@@ -10,5 +10,7 @@ ...@@ -10,5 +10,7 @@
//! Operations and constants for signed 32-bits integers (`i32` type) //! Operations and constants for signed 32-bits integers (`i32` type)
#![doc(primitive = "i32")]
int_module!(i32, 32) int_module!(i32, 32)
...@@ -10,5 +10,7 @@ ...@@ -10,5 +10,7 @@
//! Operations and constants for signed 64-bits integers (`i64` type) //! Operations and constants for signed 64-bits integers (`i64` type)
#![doc(primitive = "i64")]
int_module!(i64, 64) int_module!(i64, 64)
...@@ -10,5 +10,7 @@ ...@@ -10,5 +10,7 @@
//! Operations and constants for signed 8-bits integers (`i8` type) //! Operations and constants for signed 8-bits integers (`i8` type)
#![doc(primitive = "i8")]
int_module!(i8, 8) int_module!(i8, 8)
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for architecture-sized signed integers (`int` type) //! Operations and constants for architecture-sized signed integers (`int` type)
#![doc(primitive = "int")]
#[cfg(target_word_size = "32")] int_module!(int, 32) #[cfg(target_word_size = "32")] int_module!(int, 32)
#[cfg(target_word_size = "64")] int_module!(int, 64) #[cfg(target_word_size = "64")] int_module!(int, 64)
...@@ -10,4 +10,6 @@ ...@@ -10,4 +10,6 @@
//! Operations and constants for unsigned 16-bits integers (`u16` type) //! Operations and constants for unsigned 16-bits integers (`u16` type)
#![doc(primitive = "u16")]
uint_module!(u16, i16, 16) uint_module!(u16, i16, 16)
...@@ -10,5 +10,7 @@ ...@@ -10,5 +10,7 @@
//! Operations and constants for unsigned 32-bits integers (`u32` type) //! Operations and constants for unsigned 32-bits integers (`u32` type)
#![doc(primitive = "u32")]
uint_module!(u32, i32, 32) uint_module!(u32, i32, 32)
...@@ -10,5 +10,7 @@ ...@@ -10,5 +10,7 @@
//! Operations and constants for unsigned 64-bits integer (`u64` type) //! Operations and constants for unsigned 64-bits integer (`u64` type)
#![doc(primitive = "u64")]
uint_module!(u64, i64, 64) uint_module!(u64, i64, 64)
...@@ -10,5 +10,7 @@ ...@@ -10,5 +10,7 @@
//! Operations and constants for unsigned 8-bits integers (`u8` type) //! Operations and constants for unsigned 8-bits integers (`u8` type)
#![doc(primitive = "u8")]
uint_module!(u8, i8, 8) uint_module!(u8, i8, 8)
...@@ -10,5 +10,7 @@ ...@@ -10,5 +10,7 @@
//! Operations and constants for architecture-sized unsigned integers (`uint` type) //! Operations and constants for architecture-sized unsigned integers (`uint` type)
#![doc(primitive = "uint")]
uint_module!(uint, int, ::int::BITS) uint_module!(uint, int, ::int::BITS)
...@@ -234,8 +234,8 @@ ...@@ -234,8 +234,8 @@
//! similar and complementary: they are often employed to indicate a //! similar and complementary: they are often employed to indicate a
//! lack of a return value; and they are trivially converted between //! lack of a return value; and they are trivially converted between
//! each other, so `Result`s are often handled by first converting to //! each other, so `Result`s are often handled by first converting to
//! `Option` with the [`ok`](enum.Result.html#method.ok) and //! `Option` with the [`ok`](type.Result.html#method.ok) and
//! [`err`](enum.Result.html#method.ok) methods. //! [`err`](type.Result.html#method.ok) methods.
//! //!
//! Whereas `Option` only indicates the lack of a value, `Result` is //! Whereas `Option` only indicates the lack of a value, `Result` is
//! specifically for error reporting, and carries with it an error //! specifically for error reporting, and carries with it an error
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
//! //!
//! For more details `std::slice`. //! For more details `std::slice`.
#![doc(primitive = "slice")]
use mem::transmute; use mem::transmute;
use clone::Clone; use clone::Clone;
use container::Container; use container::Container;
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
//! //!
//! For more details, see std::str //! For more details, see std::str
#![doc(primitive = "str")]
use mem; use mem;
use char; use char;
use clone::Clone; use clone::Clone;
......
...@@ -59,6 +59,8 @@ ...@@ -59,6 +59,8 @@
//! assert_eq!(d, (0u32, 0.0f32)); //! assert_eq!(d, (0u32, 0.0f32));
//! ``` //! ```
#![doc(primitive = "tuple")]
use clone::Clone; use clone::Clone;
#[cfg(not(test))] use cmp::*; #[cfg(not(test))] use cmp::*;
#[cfg(not(test))] use default::Default; #[cfg(not(test))] use default::Default;
......
...@@ -62,17 +62,22 @@ fn try_inline_def(cx: &core::DocContext, ...@@ -62,17 +62,22 @@ fn try_inline_def(cx: &core::DocContext,
clean::TraitItem(build_external_trait(tcx, did)) clean::TraitItem(build_external_trait(tcx, did))
} }
ast::DefFn(did, style) => { ast::DefFn(did, style) => {
// If this function is a tuple struct constructor, we just skip it
if csearch::get_tuple_struct_definition_if_ctor(&tcx.sess.cstore,
did).is_some() {
return None
}
record_extern_fqn(cx, did, clean::TypeFunction); record_extern_fqn(cx, did, clean::TypeFunction);
clean::FunctionItem(build_external_function(tcx, did, style)) clean::FunctionItem(build_external_function(tcx, did, style))
} }
ast::DefStruct(did) => { ast::DefStruct(did) => {
record_extern_fqn(cx, did, clean::TypeStruct); record_extern_fqn(cx, did, clean::TypeStruct);
ret.extend(build_impls(tcx, did).move_iter()); ret.extend(build_impls(cx, tcx, did).move_iter());
clean::StructItem(build_struct(tcx, did)) clean::StructItem(build_struct(tcx, did))
} }
ast::DefTy(did) => { ast::DefTy(did) => {
record_extern_fqn(cx, did, clean::TypeEnum); record_extern_fqn(cx, did, clean::TypeEnum);
ret.extend(build_impls(tcx, did).move_iter()); ret.extend(build_impls(cx, tcx, did).move_iter());
build_type(tcx, did) build_type(tcx, did)
} }
// Assume that the enum type is reexported next to the variant, and // Assume that the enum type is reexported next to the variant, and
...@@ -193,7 +198,8 @@ fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum { ...@@ -193,7 +198,8 @@ fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
}) })
} }
fn build_impls(tcx: &ty::ctxt, fn build_impls(cx: &core::DocContext,
tcx: &ty::ctxt,
did: ast::DefId) -> Vec<clean::Item> { did: ast::DefId) -> Vec<clean::Item> {
ty::populate_implementations_for_type_if_necessary(tcx, did); ty::populate_implementations_for_type_if_necessary(tcx, did);
let mut impls = Vec::new(); let mut impls = Vec::new();
...@@ -205,6 +211,38 @@ fn build_impls(tcx: &ty::ctxt, ...@@ -205,6 +211,38 @@ fn build_impls(tcx: &ty::ctxt,
} }
} }
// If this is the first time we've inlined something from this crate, then
// we inline *all* impls from the crate into this crate. Note that there's
// currently no way for us to filter this based on type, and we likely need
// many impls for a variety of reasons.
//
// Primarily, the impls will be used to populate the documentation for this
// type being inlined, but impls can also be used when generating
// documentation for primitives (no way to find those specifically).
if cx.populated_crate_impls.borrow_mut().insert(did.krate) {
csearch::each_top_level_item_of_crate(&tcx.sess.cstore,
did.krate,
|def, _, _| {
populate_impls(tcx, def, &mut impls)
});
fn populate_impls(tcx: &ty::ctxt,
def: decoder::DefLike,
impls: &mut Vec<clean::Item>) {
match def {
decoder::DlImpl(did) => impls.push(build_impl(tcx, did)),
decoder::DlDef(ast::DefMod(did)) => {
csearch::each_child_of_item(&tcx.sess.cstore,
did,
|def, _, _| {
populate_impls(tcx, def, impls)
})
}
_ => {}
}
}
}
impls impls
} }
...@@ -259,7 +297,8 @@ fn build_module(cx: &core::DocContext, tcx: &ty::ctxt, ...@@ -259,7 +297,8 @@ fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
// FIXME: this doesn't handle reexports inside the module itself. // FIXME: this doesn't handle reexports inside the module itself.
// Should they be handled? // Should they be handled?
csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, _| { csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, vis| {
if vis != ast::Public { return }
match def { match def {
decoder::DlDef(def) => { decoder::DlDef(def) => {
match try_inline_def(cx, tcx, def) { match try_inline_def(cx, tcx, def) {
...@@ -267,7 +306,8 @@ fn build_module(cx: &core::DocContext, tcx: &ty::ctxt, ...@@ -267,7 +306,8 @@ fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
None => {} None => {}
} }
} }
decoder::DlImpl(did) => items.push(build_impl(tcx, did)), // All impls were inlined above
decoder::DlImpl(..) => {}
decoder::DlField => fail!("unimplemented field"), decoder::DlField => fail!("unimplemented field"),
} }
}); });
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
use rustc::middle::ty; use rustc::middle::ty;
use std::rc::Rc; use std::rc::Rc;
use std::u32;
use core; use core;
use doctree; use doctree;
...@@ -81,6 +82,7 @@ pub struct Crate { ...@@ -81,6 +82,7 @@ pub struct Crate {
pub name: String, pub name: String,
pub module: Option<Item>, pub module: Option<Item>,
pub externs: Vec<(ast::CrateNum, ExternalCrate)>, pub externs: Vec<(ast::CrateNum, ExternalCrate)>,
pub primitives: Vec<Primitive>,
} }
impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> { impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
...@@ -92,6 +94,7 @@ fn clean(&self) -> Crate { ...@@ -92,6 +94,7 @@ fn clean(&self) -> Crate {
externs.push((n, meta.clean())); externs.push((n, meta.clean()));
}); });
// Figure out the name of this crate
let input = driver::FileInput(cx.src.clone()); let input = driver::FileInput(cx.src.clone());
let t_outputs = driver::build_output_filenames(&input, let t_outputs = driver::build_output_filenames(&input,
&None, &None,
...@@ -100,10 +103,62 @@ fn clean(&self) -> Crate { ...@@ -100,10 +103,62 @@ fn clean(&self) -> Crate {
cx.sess()); cx.sess());
let id = link::find_crate_id(self.attrs.as_slice(), let id = link::find_crate_id(self.attrs.as_slice(),
t_outputs.out_filestem.as_slice()); t_outputs.out_filestem.as_slice());
// Clean the crate, translating the entire libsyntax AST to one that is
// understood by rustdoc.
let mut module = self.module.clean();
// Collect all inner modules which are tagged as implementations of
// primitives.
//
// Note that this loop only searches the top-level items of the crate,
// and this is intentional. If we were to search the entire crate for an
// item tagged with `#[doc(primitive)]` then we we would also have to
// search the entirety of external modules for items tagged
// `#[doc(primitive)]`, which is a pretty inefficient process (decoding
// all that metadata unconditionally).
//
// In order to keep the metadata load under control, the
// `#[doc(primitive)]` feature is explicitly designed to only allow the
// primitive tags to show up as the top level items in a crate.
//
// Also note that this does not attempt to deal with modules tagged
// duplicately for the same primitive. This is handled later on when
// rendering by delegating everything to a hash map.
let mut primitives = Vec::new();
{
let m = match module.inner {
ModuleItem(ref mut m) => m,
_ => unreachable!(),
};
let mut tmp = Vec::new();
for child in m.items.iter() {
match child.inner {
ModuleItem(..) => {},
_ => continue,
}
let prim = match Primitive::find(child.attrs.as_slice()) {
Some(prim) => prim,
None => continue,
};
primitives.push(prim);
tmp.push(Item {
source: Span::empty(),
name: Some(prim.to_url_str().to_string()),
attrs: child.attrs.clone(),
visibility: Some(ast::Public),
def_id: ast_util::local_def(prim.to_node_id()),
inner: PrimitiveItem(prim),
});
}
m.items.extend(tmp.move_iter());
}
Crate { Crate {
name: id.name.to_string(), name: id.name.to_string(),
module: Some(self.module.clean()), module: Some(module),
externs: externs, externs: externs,
primitives: primitives,
} }
} }
} }
...@@ -112,15 +167,35 @@ fn clean(&self) -> Crate { ...@@ -112,15 +167,35 @@ fn clean(&self) -> Crate {
pub struct ExternalCrate { pub struct ExternalCrate {
pub name: String, pub name: String,
pub attrs: Vec<Attribute>, pub attrs: Vec<Attribute>,
pub primitives: Vec<Primitive>,
} }
impl Clean<ExternalCrate> for cstore::crate_metadata { impl Clean<ExternalCrate> for cstore::crate_metadata {
fn clean(&self) -> ExternalCrate { fn clean(&self) -> ExternalCrate {
let mut primitives = Vec::new();
let cx = super::ctxtkey.get().unwrap();
match cx.maybe_typed {
core::Typed(ref tcx) => {
csearch::each_top_level_item_of_crate(&tcx.sess.cstore,
self.cnum,
|def, _, _| {
let did = match def {
decoder::DlDef(ast::DefMod(did)) => did,
_ => return
};
let attrs = inline::load_attrs(tcx, did);
match Primitive::find(attrs.as_slice()) {
Some(prim) => primitives.push(prim),
None => {}
}
});
}
core::NotTyped(..) => {}
}
ExternalCrate { ExternalCrate {
name: self.name.to_string(), name: self.name.to_string(),
attrs: decoder::get_crate_attributes(self.data()).clean() attrs: decoder::get_crate_attributes(self.data()).clean(),
.move_iter() primitives: primitives,
.collect(),
} }
} }
} }
...@@ -227,6 +302,7 @@ pub enum ItemEnum { ...@@ -227,6 +302,7 @@ pub enum ItemEnum {
/// `static`s from an extern block /// `static`s from an extern block
ForeignStaticItem(Static), ForeignStaticItem(Static),
MacroItem(Macro), MacroItem(Macro),
PrimitiveItem(Primitive),
} }
#[deriving(Clone, Encodable, Decodable)] #[deriving(Clone, Encodable, Decodable)]
...@@ -400,14 +476,19 @@ fn clean(&self) -> TyParamBound { ...@@ -400,14 +476,19 @@ fn clean(&self) -> TyParamBound {
} }
} }
fn external_path(name: &str) -> Path { fn external_path(name: &str, substs: &ty::substs) -> Path {
Path { Path {
global: false, global: false,
segments: vec![PathSegment { segments: vec![PathSegment {
name: name.to_string(), name: name.to_string(),
lifetimes: Vec::new(), lifetimes: match substs.regions {
types: Vec::new(), ty::ErasedRegions => Vec::new(),
}] ty::NonerasedRegions(ref v) => {
v.iter().filter_map(|v| v.clean()).collect()
}
},
types: substs.tps.clean(),
}],
} }
} }
...@@ -418,16 +499,21 @@ fn clean(&self) -> TyParamBound { ...@@ -418,16 +499,21 @@ fn clean(&self) -> TyParamBound {
core::Typed(ref tcx) => tcx, core::Typed(ref tcx) => tcx,
core::NotTyped(_) => return RegionBound, core::NotTyped(_) => return RegionBound,
}; };
let empty = ty::substs::empty();
let (did, path) = match *self { let (did, path) = match *self {
ty::BoundStatic => return RegionBound, ty::BoundStatic => return RegionBound,
ty::BoundSend => ty::BoundSend =>
(tcx.lang_items.send_trait().unwrap(), external_path("Send")), (tcx.lang_items.send_trait().unwrap(),
external_path("Send", &empty)),
ty::BoundSized => ty::BoundSized =>
(tcx.lang_items.sized_trait().unwrap(), external_path("Sized")), (tcx.lang_items.sized_trait().unwrap(),
external_path("Sized", &empty)),
ty::BoundCopy => ty::BoundCopy =>
(tcx.lang_items.copy_trait().unwrap(), external_path("Copy")), (tcx.lang_items.copy_trait().unwrap(),
external_path("Copy", &empty)),
ty::BoundShare => ty::BoundShare =>
(tcx.lang_items.share_trait().unwrap(), external_path("Share")), (tcx.lang_items.share_trait().unwrap(),
external_path("Share", &empty)),
}; };
let fqn = csearch::get_item_path(tcx, did); let fqn = csearch::get_item_path(tcx, did);
let fqn = fqn.move_iter().map(|i| i.to_str().to_string()).collect(); let fqn = fqn.move_iter().map(|i| i.to_str().to_string()).collect();
...@@ -451,7 +537,8 @@ fn clean(&self) -> TyParamBound { ...@@ -451,7 +537,8 @@ fn clean(&self) -> TyParamBound {
let fqn = csearch::get_item_path(tcx, self.def_id); let fqn = csearch::get_item_path(tcx, self.def_id);
let fqn = fqn.move_iter().map(|i| i.to_str().to_string()) let fqn = fqn.move_iter().map(|i| i.to_str().to_string())
.collect::<Vec<String>>(); .collect::<Vec<String>>();
let path = external_path(fqn.last().unwrap().as_slice()); let path = external_path(fqn.last().unwrap().as_slice(),
&self.substs);
cx.external_paths.borrow_mut().get_mut_ref().insert(self.def_id, cx.external_paths.borrow_mut().get_mut_ref().insert(self.def_id,
(fqn, TypeTrait)); (fqn, TypeTrait));
TraitBound(ResolvedPath { TraitBound(ResolvedPath {
...@@ -519,9 +606,9 @@ fn clean(&self) -> Option<Lifetime> { ...@@ -519,9 +606,9 @@ fn clean(&self) -> Option<Lifetime> {
ty::ReStatic => Some(Lifetime("static".to_string())), ty::ReStatic => Some(Lifetime("static".to_string())),
ty::ReLateBound(_, ty::BrNamed(_, name)) => ty::ReLateBound(_, ty::BrNamed(_, name)) =>
Some(Lifetime(token::get_name(name).get().to_string())), Some(Lifetime(token::get_name(name).get().to_string())),
ty::ReEarlyBound(_, _, name) => Some(Lifetime(name.clean())),
ty::ReLateBound(..) | ty::ReLateBound(..) |
ty::ReEarlyBound(..) |
ty::ReFree(..) | ty::ReFree(..) |
ty::ReScope(..) | ty::ReScope(..) |
ty::ReInfer(..) | ty::ReInfer(..) |
...@@ -920,7 +1007,7 @@ pub enum Type { ...@@ -920,7 +1007,7 @@ pub enum Type {
/// For references to self /// For references to self
Self(ast::DefId), Self(ast::DefId),
/// Primitives are just the fixed-size numeric types (plus int/uint/float), and char. /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
Primitive(ast::PrimTy), Primitive(Primitive),
Closure(Box<ClosureDecl>, Option<Lifetime>), Closure(Box<ClosureDecl>, Option<Lifetime>),
Proc(Box<ClosureDecl>), Proc(Box<ClosureDecl>),
/// extern "ABI" fn /// extern "ABI" fn
...@@ -928,10 +1015,6 @@ pub enum Type { ...@@ -928,10 +1015,6 @@ pub enum Type {
Tuple(Vec<Type>), Tuple(Vec<Type>),
Vector(Box<Type>), Vector(Box<Type>),
FixedVector(Box<Type>, String), FixedVector(Box<Type>, String),
String,
Bool,
/// aka TyNil
Unit,
/// aka TyBot /// aka TyBot
Bottom, Bottom,
Unique(Box<Type>), Unique(Box<Type>),
...@@ -945,6 +1028,19 @@ pub enum Type { ...@@ -945,6 +1028,19 @@ pub enum Type {
// region, raw, other boxes, mutable // region, raw, other boxes, mutable
} }
#[deriving(Clone, Encodable, Decodable, PartialEq, TotalEq, Hash)]
pub enum Primitive {
Int, I8, I16, I32, I64,
Uint, U8, U16, U32, U64,
F32, F64, F128,
Char,
Bool,
Nil,
Str,
Slice,
PrimitiveTuple,
}
#[deriving(Clone, Encodable, Decodable)] #[deriving(Clone, Encodable, Decodable)]
pub enum TypeKind { pub enum TypeKind {
TypeEnum, TypeEnum,
...@@ -956,11 +1052,97 @@ pub enum TypeKind { ...@@ -956,11 +1052,97 @@ pub enum TypeKind {
TypeVariant, TypeVariant,
} }
impl Primitive {
fn from_str(s: &str) -> Option<Primitive> {
match s.as_slice() {
"int" => Some(Int),
"i8" => Some(I8),
"i16" => Some(I16),
"i32" => Some(I32),
"i64" => Some(I64),
"uint" => Some(Uint),
"u8" => Some(U8),
"u16" => Some(U16),
"u32" => Some(U32),
"u64" => Some(U64),
"bool" => Some(Bool),
"nil" => Some(Nil),
"char" => Some(Char),
"str" => Some(Str),
"f32" => Some(F32),
"f64" => Some(F64),
"f128" => Some(F128),
"slice" => Some(Slice),
"tuple" => Some(PrimitiveTuple),
_ => None,
}
}
fn find(attrs: &[Attribute]) -> Option<Primitive> {
for attr in attrs.iter() {
let list = match *attr {
List(ref k, ref l) if k.as_slice() == "doc" => l,
_ => continue,
};
for sub_attr in list.iter() {
let value = match *sub_attr {
NameValue(ref k, ref v)
if k.as_slice() == "primitive" => v.as_slice(),
_ => continue,
};
match Primitive::from_str(value) {
Some(p) => return Some(p),
None => {}
}
}
}
return None
}
pub fn to_str(&self) -> &'static str {
match *self {
Int => "int",
I8 => "i8",
I16 => "i16",
I32 => "i32",
I64 => "i64",
Uint => "uint",
U8 => "u8",
U16 => "u16",
U32 => "u32",
U64 => "u64",
F32 => "f32",
F64 => "f64",
F128 => "f128",
Str => "str",
Bool => "bool",
Char => "char",
Nil => "()",
Slice => "slice",
PrimitiveTuple => "tuple",
}
}
pub fn to_url_str(&self) -> &'static str {
match *self {
Nil => "nil",
other => other.to_str(),
}
}
/// Creates a rustdoc-specific node id for primitive types.
///
/// These node ids are generally never used by the AST itself.
pub fn to_node_id(&self) -> ast::NodeId {
u32::MAX - 1 - (*self as u32)
}
}
impl Clean<Type> for ast::Ty { impl Clean<Type> for ast::Ty {
fn clean(&self) -> Type { fn clean(&self) -> Type {
use syntax::ast::*; use syntax::ast::*;
match self.node { match self.node {
TyNil => Unit, TyNil => Primitive(Nil),
TyPtr(ref m) => RawPointer(m.mutbl.clean(), box m.ty.clean()), TyPtr(ref m) => RawPointer(m.mutbl.clean(), box m.ty.clean()),
TyRptr(ref l, ref m) => TyRptr(ref l, ref m) =>
BorrowedRef {lifetime: l.clean(), mutability: m.mutbl.clean(), BorrowedRef {lifetime: l.clean(), mutability: m.mutbl.clean(),
...@@ -988,16 +1170,26 @@ fn clean(&self) -> Type { ...@@ -988,16 +1170,26 @@ fn clean(&self) -> Type {
impl Clean<Type> for ty::t { impl Clean<Type> for ty::t {
fn clean(&self) -> Type { fn clean(&self) -> Type {
match ty::get(*self).sty { match ty::get(*self).sty {
ty::ty_nil => Unit,
ty::ty_bot => Bottom, ty::ty_bot => Bottom,
ty::ty_bool => Bool, ty::ty_nil => Primitive(Nil),
ty::ty_char => Primitive(ast::TyChar), ty::ty_bool => Primitive(Bool),
ty::ty_int(t) => Primitive(ast::TyInt(t)), ty::ty_char => Primitive(Char),
ty::ty_uint(u) => Primitive(ast::TyUint(u)), ty::ty_int(ast::TyI) => Primitive(Int),
ty::ty_float(f) => Primitive(ast::TyFloat(f)), ty::ty_int(ast::TyI8) => Primitive(I8),
ty::ty_int(ast::TyI16) => Primitive(I16),
ty::ty_int(ast::TyI32) => Primitive(I32),
ty::ty_int(ast::TyI64) => Primitive(I64),
ty::ty_uint(ast::TyU) => Primitive(Uint),
ty::ty_uint(ast::TyU8) => Primitive(U8),
ty::ty_uint(ast::TyU16) => Primitive(U16),
ty::ty_uint(ast::TyU32) => Primitive(U32),
ty::ty_uint(ast::TyU64) => Primitive(U64),
ty::ty_float(ast::TyF32) => Primitive(F32),
ty::ty_float(ast::TyF64) => Primitive(F64),
ty::ty_float(ast::TyF128) => Primitive(F128),
ty::ty_str => Primitive(Str),
ty::ty_box(t) => Managed(box t.clean()), ty::ty_box(t) => Managed(box t.clean()),
ty::ty_uniq(t) => Unique(box t.clean()), ty::ty_uniq(t) => Unique(box t.clean()),
ty::ty_str => String,
ty::ty_vec(mt, None) => Vector(box mt.ty.clean()), ty::ty_vec(mt, None) => Vector(box mt.ty.clean()),
ty::ty_vec(mt, Some(i)) => FixedVector(box mt.ty.clean(), ty::ty_vec(mt, Some(i)) => FixedVector(box mt.ty.clean(),
format!("{}", i)), format!("{}", i)),
...@@ -1040,22 +1232,13 @@ fn clean(&self) -> Type { ...@@ -1040,22 +1232,13 @@ fn clean(&self) -> Type {
let fqn: Vec<String> = fqn.move_iter().map(|i| { let fqn: Vec<String> = fqn.move_iter().map(|i| {
i.to_str().to_string() i.to_str().to_string()
}).collect(); }).collect();
let mut path = external_path(fqn.last()
.unwrap()
.to_str()
.as_slice());
let kind = match ty::get(*self).sty { let kind = match ty::get(*self).sty {
ty::ty_struct(..) => TypeStruct, ty::ty_struct(..) => TypeStruct,
ty::ty_trait(..) => TypeTrait, ty::ty_trait(..) => TypeTrait,
_ => TypeEnum, _ => TypeEnum,
}; };
path.segments.get_mut(0).lifetimes = match substs.regions { let path = external_path(fqn.last().unwrap().to_str().as_slice(),
ty::ErasedRegions => Vec::new(), substs);
ty::NonerasedRegions(ref v) => {
v.iter().filter_map(|v| v.clean()).collect()
}
};
path.segments.get_mut(0).types = substs.tps.clean();
cx.external_paths.borrow_mut().get_mut_ref().insert(did, cx.external_paths.borrow_mut().get_mut_ref().insert(did,
(fqn, kind)); (fqn, kind));
ResolvedPath { ResolvedPath {
...@@ -1747,7 +1930,7 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>, ...@@ -1747,7 +1930,7 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>,
let tycx = match cx.maybe_typed { let tycx = match cx.maybe_typed {
core::Typed(ref tycx) => tycx, core::Typed(ref tycx) => tycx,
// If we're extracting tests, this return value doesn't matter. // If we're extracting tests, this return value doesn't matter.
core::NotTyped(_) => return Bool core::NotTyped(_) => return Primitive(Bool),
}; };
debug!("searching for {:?} in defmap", id); debug!("searching for {:?} in defmap", id);
let def = match tycx.def_map.borrow().find(&id) { let def = match tycx.def_map.borrow().find(&id) {
...@@ -1758,9 +1941,22 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>, ...@@ -1758,9 +1941,22 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>,
match def { match def {
ast::DefSelfTy(i) => return Self(ast_util::local_def(i)), ast::DefSelfTy(i) => return Self(ast_util::local_def(i)),
ast::DefPrimTy(p) => match p { ast::DefPrimTy(p) => match p {
ast::TyStr => return String, ast::TyStr => return Primitive(Str),
ast::TyBool => return Bool, ast::TyBool => return Primitive(Bool),
_ => return Primitive(p) ast::TyChar => return Primitive(Char),
ast::TyInt(ast::TyI) => return Primitive(Int),
ast::TyInt(ast::TyI8) => return Primitive(I8),
ast::TyInt(ast::TyI16) => return Primitive(I16),
ast::TyInt(ast::TyI32) => return Primitive(I32),
ast::TyInt(ast::TyI64) => return Primitive(I64),
ast::TyUint(ast::TyU) => return Primitive(Uint),
ast::TyUint(ast::TyU8) => return Primitive(U8),
ast::TyUint(ast::TyU16) => return Primitive(U16),
ast::TyUint(ast::TyU32) => return Primitive(U32),
ast::TyUint(ast::TyU64) => return Primitive(U64),
ast::TyFloat(ast::TyF32) => return Primitive(F32),
ast::TyFloat(ast::TyF64) => return Primitive(F64),
ast::TyFloat(ast::TyF128) => return Primitive(F128),
}, },
ast::DefTyParam(i, _) => return Generic(i), ast::DefTyParam(i, _) => return Generic(i),
ast::DefTyParamBinder(i) => return TyParamBinder(i), ast::DefTyParamBinder(i) => return TyParamBinder(i),
......
...@@ -42,6 +42,7 @@ pub struct DocContext { ...@@ -42,6 +42,7 @@ pub struct DocContext {
pub external_traits: RefCell<Option<HashMap<ast::DefId, clean::Trait>>>, pub external_traits: RefCell<Option<HashMap<ast::DefId, clean::Trait>>>,
pub external_typarams: RefCell<Option<HashMap<ast::DefId, String>>>, pub external_typarams: RefCell<Option<HashMap<ast::DefId, String>>>,
pub inlined: RefCell<Option<HashSet<ast::DefId>>>, pub inlined: RefCell<Option<HashSet<ast::DefId>>>,
pub populated_crate_impls: RefCell<HashSet<ast::CrateNum>>,
} }
impl DocContext { impl DocContext {
...@@ -114,6 +115,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>) ...@@ -114,6 +115,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>)
external_typarams: RefCell::new(Some(HashMap::new())), external_typarams: RefCell::new(Some(HashMap::new())),
external_paths: RefCell::new(Some(HashMap::new())), external_paths: RefCell::new(Some(HashMap::new())),
inlined: RefCell::new(Some(HashSet::new())), inlined: RefCell::new(Some(HashSet::new())),
populated_crate_impls: RefCell::new(HashSet::new()),
}, CrateAnalysis { }, CrateAnalysis {
exported_items: exported_items, exported_items: exported_items,
public_items: public_items, public_items: public_items,
......
...@@ -263,6 +263,53 @@ fn path(w: &mut fmt::Formatter, path: &clean::Path, print_all: bool, ...@@ -263,6 +263,53 @@ fn path(w: &mut fmt::Formatter, path: &clean::Path, print_all: bool,
Ok(()) Ok(())
} }
fn primitive_link(f: &mut fmt::Formatter,
prim: clean::Primitive,
name: &str) -> fmt::Result {
let m = cache_key.get().unwrap();
let mut needs_termination = false;
match m.primitive_locations.find(&prim) {
Some(&ast::LOCAL_CRATE) => {
let loc = current_location_key.get().unwrap();
let len = if loc.len() == 0 {0} else {loc.len() - 1};
try!(write!(f, "<a href='{}primitive.{}.html'>",
"../".repeat(len),
prim.to_url_str()));
needs_termination = true;
}
Some(&cnum) => {
let path = m.paths.get(&ast::DefId {
krate: cnum,
node: ast::CRATE_NODE_ID,
});
let loc = match *m.extern_locations.get(&cnum) {
render::Remote(ref s) => Some(s.to_string()),
render::Local => {
let loc = current_location_key.get().unwrap();
Some("../".repeat(loc.len()))
}
render::Unknown => None,
};
match loc {
Some(root) => {
try!(write!(f, "<a href='{}{}/primitive.{}.html'>",
root,
path.ref0().as_slice().head().unwrap(),
prim.to_url_str()));
needs_termination = true;
}
None => {}
}
}
None => {}
}
try!(write!(f, "{}", name));
if needs_termination {
try!(write!(f, "</a>"));
}
Ok(())
}
/// Helper to render type parameters /// Helper to render type parameters
fn tybounds(w: &mut fmt::Formatter, fn tybounds(w: &mut fmt::Formatter,
typarams: &Option<Vec<clean::TyParamBound> >) -> fmt::Result { typarams: &Option<Vec<clean::TyParamBound> >) -> fmt::Result {
...@@ -297,27 +344,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ...@@ -297,27 +344,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
tybounds(f, typarams) tybounds(f, typarams)
} }
clean::Self(..) => f.write("Self".as_bytes()), clean::Self(..) => f.write("Self".as_bytes()),
clean::Primitive(prim) => { clean::Primitive(prim) => primitive_link(f, prim, prim.to_str()),
let s = match prim {
ast::TyInt(ast::TyI) => "int",
ast::TyInt(ast::TyI8) => "i8",
ast::TyInt(ast::TyI16) => "i16",
ast::TyInt(ast::TyI32) => "i32",
ast::TyInt(ast::TyI64) => "i64",
ast::TyUint(ast::TyU) => "uint",
ast::TyUint(ast::TyU8) => "u8",
ast::TyUint(ast::TyU16) => "u16",
ast::TyUint(ast::TyU32) => "u32",
ast::TyUint(ast::TyU64) => "u64",
ast::TyFloat(ast::TyF32) => "f32",
ast::TyFloat(ast::TyF64) => "f64",
ast::TyFloat(ast::TyF128) => "f128",
ast::TyStr => "str",
ast::TyBool => "bool",
ast::TyChar => "char",
};
f.write(s.as_bytes())
}
clean::Closure(ref decl, ref region) => { clean::Closure(ref decl, ref region) => {
write!(f, "{style}{lifetimes}|{args}|{bounds}\ write!(f, "{style}{lifetimes}|{args}|{bounds}\
{arrow, select, yes{ -&gt; {ret}} other{}}", {arrow, select, yes{ -&gt; {ret}} other{}}",
...@@ -329,7 +356,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ...@@ -329,7 +356,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}, },
args = decl.decl.inputs, args = decl.decl.inputs,
arrow = match decl.decl.output { arrow = match decl.decl.output {
clean::Unit => "no", clean::Primitive(clean::Nil) => "no",
_ => "yes", _ => "yes",
}, },
ret = decl.decl.output, ret = decl.decl.output,
...@@ -379,7 +406,10 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ...@@ -379,7 +406,10 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
": {}", ": {}",
m.collect::<Vec<String>>().connect(" + ")) m.collect::<Vec<String>>().connect(" + "))
}, },
arrow = match decl.decl.output { clean::Unit => "no", _ => "yes" }, arrow = match decl.decl.output {
clean::Primitive(clean::Nil) => "no",
_ => "yes",
},
ret = decl.decl.output) ret = decl.decl.output)
} }
clean::BareFunction(ref decl) => { clean::BareFunction(ref decl) => {
...@@ -394,22 +424,16 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ...@@ -394,22 +424,16 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
decl.decl) decl.decl)
} }
clean::Tuple(ref typs) => { clean::Tuple(ref typs) => {
try!(f.write("(".as_bytes())); primitive_link(f, clean::PrimitiveTuple,
for (i, typ) in typs.iter().enumerate() { format!("({:#})", typs).as_slice())
if i > 0 { }
try!(f.write(", ".as_bytes())) clean::Vector(ref t) => {
} primitive_link(f, clean::Slice, format!("[{}]", **t).as_slice())
try!(write!(f, "{}", *typ));
}
f.write(")".as_bytes())
} }
clean::Vector(ref t) => write!(f, "[{}]", **t),
clean::FixedVector(ref t, ref s) => { clean::FixedVector(ref t, ref s) => {
write!(f, "[{}, ..{}]", **t, *s) primitive_link(f, clean::Slice,
format!("[{}, ..{}]", **t, *s).as_slice())
} }
clean::String => f.write("str".as_bytes()),
clean::Bool => f.write("bool".as_bytes()),
clean::Unit => f.write("()".as_bytes()),
clean::Bottom => f.write("!".as_bytes()), clean::Bottom => f.write("!".as_bytes()),
clean::Unique(ref t) => write!(f, "~{}", **t), clean::Unique(ref t) => write!(f, "~{}", **t),
clean::Managed(ref t) => write!(f, "@{}", **t), clean::Managed(ref t) => write!(f, "@{}", **t),
...@@ -454,7 +478,10 @@ impl fmt::Show for clean::FnDecl { ...@@ -454,7 +478,10 @@ impl fmt::Show for clean::FnDecl {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({args}){arrow, select, yes{ -&gt; {ret}} other{}}", write!(f, "({args}){arrow, select, yes{ -&gt; {ret}} other{}}",
args = self.inputs, args = self.inputs,
arrow = match self.output { clean::Unit => "no", _ => "yes" }, arrow = match self.output {
clean::Primitive(clean::Nil) => "no",
_ => "yes"
},
ret = self.output) ret = self.output)
} }
} }
...@@ -490,7 +517,10 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ...@@ -490,7 +517,10 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, write!(f,
"({args}){arrow, select, yes{ -&gt; {ret}} other{}}", "({args}){arrow, select, yes{ -&gt; {ret}} other{}}",
args = args, args = args,
arrow = match d.output { clean::Unit => "no", _ => "yes" }, arrow = match d.output {
clean::Primitive(clean::Nil) => "no",
_ => "yes"
},
ret = d.output) ret = d.output)
} }
} }
......
...@@ -37,6 +37,7 @@ pub enum ItemType { ...@@ -37,6 +37,7 @@ pub enum ItemType {
ForeignFunction = 13, ForeignFunction = 13,
ForeignStatic = 14, ForeignStatic = 14,
Macro = 15, Macro = 15,
Primitive = 16,
} }
impl ItemType { impl ItemType {
...@@ -58,6 +59,7 @@ pub fn to_static_str(&self) -> &'static str { ...@@ -58,6 +59,7 @@ pub fn to_static_str(&self) -> &'static str {
ForeignFunction => "ffi", ForeignFunction => "ffi",
ForeignStatic => "ffs", ForeignStatic => "ffs",
Macro => "macro", Macro => "macro",
Primitive => "primitive",
} }
} }
} }
...@@ -92,6 +94,7 @@ pub fn shortty(item: &clean::Item) -> ItemType { ...@@ -92,6 +94,7 @@ pub fn shortty(item: &clean::Item) -> ItemType {
clean::ForeignFunctionItem(..) => ForeignFunction, clean::ForeignFunctionItem(..) => ForeignFunction,
clean::ForeignStaticItem(..) => ForeignStatic, clean::ForeignStaticItem(..) => ForeignStatic,
clean::MacroItem(..) => Macro, clean::MacroItem(..) => Macro,
clean::PrimitiveItem(..) => Primitive,
} }
} }
...@@ -130,3 +130,17 @@ pub fn render<T: fmt::Show, S: fmt::Show>( ...@@ -130,3 +130,17 @@ pub fn render<T: fmt::Show, S: fmt::Show>(
fn nonestr<'a>(s: &'a str) -> &'a str { fn nonestr<'a>(s: &'a str) -> &'a str {
if s == "" { "none" } else { s } if s == "" { "none" } else { s }
} }
pub fn redirect(dst: &mut io::Writer, url: &str) -> io::IoResult<()> {
write!(dst,
r##"<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="refresh" content="0;URL={url}">
</head>
<body>
</body>
</html>"##,
url = url,
)
}
此差异已折叠。
...@@ -527,7 +527,8 @@ ...@@ -527,7 +527,8 @@
"variant", "variant",
"ffi", "ffi",
"ffs", "ffs",
"macro"]; "macro",
"primitive"];
function itemTypeFromName(typename) { function itemTypeFromName(typename) {
for (var i = 0; i < itemTypes.length; ++i) { for (var i = 0; i < itemTypes.length; ++i) {
...@@ -658,15 +659,13 @@ ...@@ -658,15 +659,13 @@
var list = $('#implementors-list'); var list = $('#implementors-list');
var libs = Object.getOwnPropertyNames(imp); var libs = Object.getOwnPropertyNames(imp);
for (var i = 0; i < libs.length; i++) { for (var i = 0; i < libs.length; i++) {
var structs = Object.getOwnPropertyNames(imp[libs[i]]); if (libs[i] == currentCrate) continue;
var structs = imp[libs[i]];
for (var j = 0; j < structs.length; j++) { for (var j = 0; j < structs.length; j++) {
console.log(i, structs[j]); var code = $('<code>').append(structs[j]);
var path = rootPath + imp[libs[i]][structs[j]]; $.each(code.find('a'), function(idx, a) {
var klass = path.contains("type.") ? "type" : "struct"; $(a).attr('href', rootPath + $(a).attr('href'));
var link = $('<a>').text(structs[j]) });
.attr('href', path)
.attr('class', klass);
var code = $('<code>').append(link);
var li = $('<li>').append(code); var li = $('<li>').append(code);
list.append(li); list.append(li);
} }
......
...@@ -67,11 +67,22 @@ impl<'a> fold::DocFolder for ImplStripper<'a> { ...@@ -67,11 +67,22 @@ impl<'a> fold::DocFolder for ImplStripper<'a> {
fn fold_item(&mut self, i: Item) -> Option<Item> { fn fold_item(&mut self, i: Item) -> Option<Item> {
match i.inner { match i.inner {
clean::ImplItem(clean::Impl{ clean::ImplItem(clean::Impl{
for_: clean::ResolvedPath{ did, .. }, .. for_: clean::ResolvedPath{ did, .. },
ref trait_, ..
}) => { }) => {
// Impls for stripped types don't need to exist
if self.stripped.contains(&did.node) { if self.stripped.contains(&did.node) {
return None; return None;
} }
// Impls of stripped traits also don't need to exist
match *trait_ {
Some(clean::ResolvedPath { did, .. }) => {
if self.stripped.contains(&did.node) {
return None
}
}
_ => {}
}
} }
_ => {} _ => {}
} }
...@@ -161,6 +172,9 @@ fn fold_item(&mut self, i: Item) -> Option<Item> { ...@@ -161,6 +172,9 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
// tymethods/macros have no control over privacy // tymethods/macros have no control over privacy
clean::MacroItem(..) | clean::TyMethodItem(..) => {} clean::MacroItem(..) | clean::TyMethodItem(..) => {}
// Primitives are never stripped
clean::PrimitiveItem(..) => {}
} }
let fastreturn = match i.inner { let fastreturn = match i.inner {
......
...@@ -79,6 +79,7 @@ pub fn run(input: &str, ...@@ -79,6 +79,7 @@ pub fn run(input: &str,
external_traits: RefCell::new(None), external_traits: RefCell::new(None),
external_typarams: RefCell::new(None), external_typarams: RefCell::new(None),
inlined: RefCell::new(None), inlined: RefCell::new(None),
populated_crate_impls: RefCell::new(HashSet::new()),
}; };
super::ctxtkey.replace(Some(ctx)); super::ctxtkey.replace(Some(ctx));
......
...@@ -82,6 +82,7 @@ pub fn local_id() -> uint { ...@@ -82,6 +82,7 @@ pub fn local_id() -> uint {
} }
} }
#[doc(hidden)]
pub trait HomingIO { pub trait HomingIO {
fn home<'r>(&'r mut self) -> &'r mut HomeHandle; fn home<'r>(&'r mut self) -> &'r mut HomeHandle;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#![allow(missing_doc)] #![allow(missing_doc)]
#![allow(unsigned_negate)] #![allow(unsigned_negate)]
#![doc(primitive = "f32")]
use prelude::*; use prelude::*;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
//! Operations and constants for 64-bits floats (`f64` type) //! Operations and constants for 64-bits floats (`f64` type)
#![allow(missing_doc)] #![allow(missing_doc)]
#![doc(primitive = "f64")]
use prelude::*; use prelude::*;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for signed 16-bits integers (`i16` type) //! Operations and constants for signed 16-bits integers (`i16` type)
#![doc(primitive = "i16")]
use from_str::FromStr; use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix}; use num::{ToStrRadix, FromStrRadix};
use num::strconv; use num::strconv;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for signed 32-bits integers (`i32` type) //! Operations and constants for signed 32-bits integers (`i32` type)
#![doc(primitive = "i32")]
use from_str::FromStr; use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix}; use num::{ToStrRadix, FromStrRadix};
use num::strconv; use num::strconv;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for signed 64-bits integers (`i64` type) //! Operations and constants for signed 64-bits integers (`i64` type)
#![doc(primitive = "i64")]
use from_str::FromStr; use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix}; use num::{ToStrRadix, FromStrRadix};
use num::strconv; use num::strconv;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for signed 8-bits integers (`i8` type) //! Operations and constants for signed 8-bits integers (`i8` type)
#![doc(primitive = "i8")]
use from_str::FromStr; use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix}; use num::{ToStrRadix, FromStrRadix};
use num::strconv; use num::strconv;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for architecture-sized signed integers (`int` type) //! Operations and constants for architecture-sized signed integers (`int` type)
#![doc(primitive = "int")]
use from_str::FromStr; use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix}; use num::{ToStrRadix, FromStrRadix};
use num::strconv; use num::strconv;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for unsigned 16-bits integers (`u16` type) //! Operations and constants for unsigned 16-bits integers (`u16` type)
#![doc(primitive = "u16")]
use from_str::FromStr; use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix}; use num::{ToStrRadix, FromStrRadix};
use num::strconv; use num::strconv;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for unsigned 32-bits integers (`u32` type) //! Operations and constants for unsigned 32-bits integers (`u32` type)
#![doc(primitive = "u32")]
use from_str::FromStr; use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix}; use num::{ToStrRadix, FromStrRadix};
use num::strconv; use num::strconv;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for unsigned 64-bits integer (`u64` type) //! Operations and constants for unsigned 64-bits integer (`u64` type)
#![doc(primitive = "u64")]
use from_str::FromStr; use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix}; use num::{ToStrRadix, FromStrRadix};
use num::strconv; use num::strconv;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for unsigned 8-bits integers (`u8` type) //! Operations and constants for unsigned 8-bits integers (`u8` type)
#![doc(primitive = "u8")]
use from_str::FromStr; use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix}; use num::{ToStrRadix, FromStrRadix};
use num::strconv; use num::strconv;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
//! Operations and constants for architecture-sized unsigned integers (`uint` type) //! Operations and constants for architecture-sized unsigned integers (`uint` type)
#![doc(primitive = "uint")]
use from_str::FromStr; use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix}; use num::{ToStrRadix, FromStrRadix};
use num::strconv; use num::strconv;
......
...@@ -97,6 +97,8 @@ ...@@ -97,6 +97,8 @@
*/ */
#![doc(primitive = "slice")]
use mem::transmute; use mem::transmute;
use clone::Clone; use clone::Clone;
use cmp::{TotalOrd, Ordering, Less, Greater}; use cmp::{TotalOrd, Ordering, Less, Greater};
......
...@@ -65,6 +65,8 @@ fn main() { ...@@ -65,6 +65,8 @@ fn main() {
*/ */
#![doc(primitive = "str")]
use char::Char; use char::Char;
use char; use char;
use clone::Clone; use clone::Clone;
......
...@@ -288,7 +288,7 @@ pub enum SubstructureFields<'a> { ...@@ -288,7 +288,7 @@ pub enum SubstructureFields<'a> {
/** /**
non-matching variants of the enum, [(variant index, ast::Variant, non-matching variants of the enum, [(variant index, ast::Variant,
[field span, field ident, fields])] (i.e. all fields for self are in the [field span, field ident, fields])] \(i.e. all fields for self are in the
first tuple, for other1 are in the second tuple, etc.) first tuple, for other1 are in the second tuple, etc.)
*/ */
EnumNonMatching(&'a [(uint, P<ast::Variant>, Vec<(Span, Option<Ident>, @Expr)> )]), EnumNonMatching(&'a [(uint, P<ast::Variant>, Vec<(Span, Option<Ident>, @Expr)> )]),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册