]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #15295 : TeXitoi/rust/relicense-shootout-mandelbrot, r=brson
authorbors <bors@rust-lang.org>
Wed, 2 Jul 2014 00:21:36 +0000 (00:21 +0000)
committerbors <bors@rust-lang.org>
Wed, 2 Jul 2014 00:21:36 +0000 (00:21 +0000)
Part of #14248

Main authors:
- @Ryman: OK
- @TeXitoi: OK
- @pcwalton: OK

Minor authors:
- @brson: OK
- @alexcrichton: OK
- @kballard: OK

Remark: @tedhorst was a main contributor, but its contribution
disapear with @pcwalton rewrite at af4ea11

@brson OK?

43 files changed:
src/doc/intro.md
src/etc/vim/syntax/rust.vim
src/liballoc/rc.rs
src/libcollections/str.rs
src/libcore/slice.rs
src/librustc/lint/builtin.rs
src/librustc/metadata/encoder.rs
src/librustc/middle/stability.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/doctree.rs
src/librustdoc/fold.rs
src/librustdoc/html/format.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.css
src/librustdoc/visit_ast.rs
src/libstd/ascii.rs
src/libstd/bitflags.rs
src/libstd/c_vec.rs
src/libstd/collections/mod.rs
src/libstd/failure.rs
src/libstd/fmt.rs
src/libstd/from_str.rs
src/libstd/gc.rs
src/libstd/io/mod.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/num/f32.rs
src/libstd/num/f64.rs
src/libstd/num/float_macros.rs
src/libstd/num/int_macros.rs
src/libstd/num/mod.rs
src/libstd/num/uint_macros.rs
src/libstd/os.rs
src/libstd/path/mod.rs
src/libstd/prelude.rs
src/libstd/rand/mod.rs
src/libstd/rt/mod.rs
src/libstd/rtdeps.rs
src/libstd/sync/mod.rs
src/libstd/task.rs
src/libstd/to_str.rs

index 10fd39c841bd658e12062378e33883945b1637ac..e8928cb55056c519d65faa4d65d8c220eba5fd46 100644 (file)
@@ -252,7 +252,7 @@ fn main() {
 }
 ```
 
-This will result an error indicating that the value is no longer in scope:
+The compiler will produce an error indicating that the value is no longer in scope:
 
 ```text
 concurrency.rs:12:20: 12:27 error: use of moved value: 'numbers'
index d8f00ac6b30facb057958d4dcbcefdef9e474912..a15bd3ca60ff1c7e484b10e1997a1fb525a8bd09 100644 (file)
@@ -77,34 +77,39 @@ syn keyword   rustEnumVariant Ok Err
 "syn keyword rustFunction drop
 
 " Types and traits {{{3
-syn keyword rustTrait Ascii AsciiCast OwnedAsciiCast AsciiStr IntoBytes
+syn keyword rustTrait Ascii AsciiCast OwnedAsciiCast AsciiStr
+syn keyword rustTrait IntoBytes
 syn keyword rustTrait ToCStr
 syn keyword rustTrait Char
 syn keyword rustTrait Clone
-syn keyword rustTrait Eq Ord PartialEq PartialOrd Ordering Equiv
+syn keyword rustTrait PartialEq PartialOrd Eq Ord Equiv
+syn keyword rustEnum Ordering
 syn keyword rustEnumVariant Less Equal Greater
-syn keyword rustTrait Container Mutable Map MutableMap Set MutableSet
-syn keyword rustTrait FromIterator Extendable
-syn keyword rustTrait Iterator DoubleEndedIterator RandomAccessIterator CloneableIterator
-syn keyword rustTrait OrdIterator MutableDoubleEndedIterator ExactSize
-syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul
-syn keyword rustTrait Signed Unsigned
-syn keyword rustTrait Primitive Int Float FloatMath ToPrimitive FromPrimitive
-"syn keyword rustTrait Expect
+syn keyword rustTrait Collection Mutable Map MutableMap
+syn keyword rustTrait Set MutableSet
+syn keyword rustTrait FromIterator Extendable ExactSize
+syn keyword rustTrait Iterator DoubleEndedIterator
+syn keyword rustTrait RandomAccessIterator CloneableIterator
+syn keyword rustTrait OrdIterator MutableDoubleEndedIterator
+syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul CheckedDiv
+syn keyword rustTrait Signed Unsigned Primitive Int Float
+syn keyword rustTrait FloatMath ToPrimitive FromPrimitive
 syn keyword rustTrait Box
 syn keyword rustTrait GenericPath Path PosixPath WindowsPath
 syn keyword rustTrait RawPtr
 syn keyword rustTrait Buffer Writer Reader Seek
-syn keyword rustTrait Str StrVector StrSlice OwnedStr IntoMaybeOwned
-syn keyword rustTrait StrAllocating
+syn keyword rustTrait Str StrVector StrSlice OwnedStr
+syn keyword rustTrait IntoMaybeOwned StrAllocating
 syn keyword rustTrait ToStr IntoStr
 syn keyword rustTrait Tuple1 Tuple2 Tuple3 Tuple4
 syn keyword rustTrait Tuple5 Tuple6 Tuple7 Tuple8
 syn keyword rustTrait Tuple9 Tuple10 Tuple11 Tuple12
-syn keyword rustTrait CloneableVector ImmutableCloneableVector MutableCloneableVector
+syn keyword rustTrait CloneableVector ImmutableCloneableVector
+syn keyword rustTrait MutableCloneableVector MutableOrdVector
 syn keyword rustTrait ImmutableVector MutableVector
-syn keyword rustTrait ImmutableEqVector ImmutableOrdVector MutableOrdVector
-syn keyword rustTrait Vector VectorVector OwnedVector MutableVectorAllocating
+syn keyword rustTrait ImmutableEqVector ImmutableOrdVector
+syn keyword rustTrait Vector VectorVector
+syn keyword rustTrait MutableVectorAllocating
 syn keyword rustTrait String
 syn keyword rustTrait Vec
 
index 83cc4a0b6620df31d0a83f73a03b7ba2ff92b9b4..d97bce39c2de947693943229e618881f7bd5bfe7 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
 
 /*! Task-local reference-counted boxes (`Rc` type)
 
-The `Rc` type provides shared ownership of an immutable value. Destruction is deterministic, and
-will occur as soon as the last owner is gone. It is marked as non-sendable because it avoids the
-overhead of atomic reference counting.
+The `Rc` type provides shared ownership of an immutable value. Destruction is
+deterministic, and will occur as soon as the last owner is gone. It is marked
+as non-sendable because it avoids the overhead of atomic reference counting.
 
-The `downgrade` method can be used to create a non-owning `Weak` pointer to the box. A `Weak`
-pointer can be upgraded to an `Rc` pointer, but will return `None` if the value has already been
-freed.
+The `downgrade` method can be used to create a non-owning `Weak` pointer to the
+box. A `Weak` pointer can be upgraded to an `Rc` pointer, but will return
+`None` if the value has already been freed.
 
-For example, a tree with parent pointers can be represented by putting the nodes behind `Strong`
-pointers, and then storing the parent pointers as `Weak` pointers.
+For example, a tree with parent pointers can be represented by putting the
+nodes behind strong `Rc` pointers, and then storing the parent pointers as
+`Weak` pointers.
+
+
+## Examples
+
+Consider a scenario where a set of Gadgets are owned by a given Owner.  We want
+to have our Gadgets point to their Owner.  We can't do this with unique
+ownership, because more than one gadget may belong to the same Owner.  Rc
+allows us to share an Owner between multiple Gadgets, and have the Owner kept
+alive as long as any Gadget points at it.
+
+```rust
+use std::rc::Rc;
+
+struct Owner {
+    name: String
+    // ...other fields
+}
+
+struct Gadget {
+    id: int,
+    owner: Rc<Owner>
+    // ...other fields
+}
+
+fn main() {
+    // Create a reference counted Owner.
+    let gadget_owner : Rc<Owner> = Rc::new(
+            Owner { name: String::from_str("Gadget Man") }
+    );
+
+    // Create Gadgets belonging to gadget_owner.  To increment the reference
+    // count we clone the Rc object.
+    let gadget1 = Gadget { id: 1, owner: gadget_owner.clone() };
+    let gadget2 = Gadget { id: 2, owner: gadget_owner.clone() };
+
+    drop(gadget_owner);
+
+    // Despite dropping gadget_owner, we're still able to print out the name of
+    // the Owner of the Gadgets. This is because we've only dropped the
+    // reference count object, not the Owner it wraps. As long as there are
+    // other Rc objects pointing at the same Owner, it will stay alive. Notice
+    // that the Rc wrapper around Gadget.owner gets automatically dereferenced
+    // for us.
+    println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name);
+    println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name);
+
+    // At the end of the method, gadget1 and gadget2 get destroyed, and with
+    // them the last counted references to our Owner.  Gadget Man now gets
+    // destroyed as well.
+}
+```
+
+If our requirements change, and we also need to be able to traverse from
+Owner->Gadget, we will run into problems: an Rc pointer from Owner->Gadget
+introduces a cycle between the objects.  This means that their reference counts
+can never reach 0, and the objects will stay alive: a memory leak.  In order to
+get around this, we can use `Weak` pointers.  These are reference counted
+pointers that don't keep an object alive if there are no normal `Rc` (or
+*strong*) pointers left.
+
+Rust actually makes it somewhat difficult to produce this loop in the first
+place: in order to end up with two objects that point at each other, one of
+them needs to be mutable.  This is problematic because Rc enforces memory
+safety by only giving out shared references to the object it wraps, and these
+don't allow direct mutation.  We need to wrap the part of the object we wish to
+mutate in a `RefCell`, which provides *interior mutability*: a method to
+achieve mutability through a shared reference.  `RefCell` enforces Rust's
+borrowing rules at runtime.  Read the `Cell` documentation for more details on
+interior mutability.
+
+```rust
+use std::rc::Rc;
+use std::rc::Weak;
+use std::cell::RefCell;
+
+struct Owner {
+    name: String,
+    gadgets: RefCell<Vec<Weak<Gadget>>>
+    // ...other fields
+}
+
+struct Gadget {
+    id: int,
+    owner: Rc<Owner>
+    // ...other fields
+}
+
+fn main() {
+    // Create a reference counted Owner.  Note the fact that we've put the
+    // Owner's vector of Gadgets inside a RefCell so that we can mutate it
+    // through a shared reference.
+    let gadget_owner : Rc<Owner> = Rc::new(
+            Owner {
+                name: "Gadget Man".to_string(),
+                gadgets: RefCell::new(Vec::new())
+            }
+    );
+
+    // Create Gadgets belonging to gadget_owner as before.
+    let gadget1 = Rc::new(Gadget{id: 1, owner: gadget_owner.clone()});
+    let gadget2 = Rc::new(Gadget{id: 2, owner: gadget_owner.clone()});
+
+    // Add the Gadgets to their Owner.  To do this we mutably borrow from
+    // the RefCell holding the Owner's Gadgets.
+    gadget_owner.gadgets.borrow_mut().push(gadget1.clone().downgrade());
+    gadget_owner.gadgets.borrow_mut().push(gadget2.clone().downgrade());
+
+    // Iterate over our Gadgets, printing their details out
+    for gadget_opt in gadget_owner.gadgets.borrow().iter() {
+
+        // gadget_opt is a Weak<Gadget>.  Since weak pointers can't guarantee
+        // that their object is still alive, we need to call upgrade() on them
+        // to turn them into a strong reference.  This returns an Option, which
+        // contains a reference to our object if it still exists.
+        let gadget = gadget_opt.upgrade().unwrap();
+        println!("Gadget {} owned by {}", gadget.id, gadget.owner.name);
+    }
+
+    // At the end of the method, gadget_owner, gadget1 and gadget2 get
+    // destroyed.  There are now no strong (Rc) references to the gadgets.
+    // Once they get destroyed, the Gadgets get destroyed.  This zeroes the
+    // reference count on Gadget Man, so he gets destroyed as well.
+}
+```
 
 */
 
index 7e47f02d21a0ce043546bd51281c19b03026fec6..aa2b38cfa9ddc5543a3f17f5f5b15ebfe25e80f5 100644 (file)
@@ -97,6 +97,15 @@ fn main() {
 ///
 /// Returns `Err` with the original vector if the vector contains invalid
 /// UTF-8.
+///
+/// # Example
+///
+/// ```rust
+/// use std::str;
+/// let hello_vec = vec![104, 101, 108, 108, 111];
+/// let string = str::from_utf8_owned(hello_vec);
+/// assert_eq!(string, Ok("hello".to_string()));
+/// ```
 pub fn from_utf8_owned(vv: Vec<u8>) -> Result<String, Vec<u8>> {
     String::from_utf8(vv)
 }
@@ -111,8 +120,8 @@ pub fn from_utf8_owned(vv: Vec<u8>) -> Result<String, Vec<u8>> {
 ///
 /// ```rust
 /// use std::str;
-/// let string = str::from_byte(66u8);
-/// assert_eq!(string.as_slice(), "B");
+/// let string = str::from_byte(104);
+/// assert_eq!(string.as_slice(), "h");
 /// ```
 pub fn from_byte(b: u8) -> String {
     assert!(b < 128u8);
@@ -120,6 +129,14 @@ pub fn from_byte(b: u8) -> String {
 }
 
 /// Convert a char to a string
+///
+/// # Example
+///
+/// ```rust
+/// use std::str;
+/// let string = str::from_char('b');
+/// assert_eq!(string.as_slice(), "b");
+/// ```
 pub fn from_char(ch: char) -> String {
     let mut buf = String::new();
     buf.push_char(ch);
@@ -127,6 +144,15 @@ pub fn from_char(ch: char) -> String {
 }
 
 /// Convert a vector of chars to a string
+///
+/// # Example
+///
+/// ```rust
+/// use std::str;
+/// let chars = ['h', 'e', 'l', 'l', 'o'];
+/// let string = str::from_chars(chars);
+/// assert_eq!(string.as_slice(), "hello");
+/// ```
 pub fn from_chars(chs: &[char]) -> String {
     chs.iter().map(|c| *c).collect()
 }
index a9e7efdf05a5ada6177858be6609b33f093ee568..0178c0318b81c2afde7be72eec396e4cfc55a425 100644 (file)
 
 #![doc(primitive = "slice")]
 
+// How this module is organized.
+//
+// The library infrastructure for slices is fairly messy. There's
+// a lot of stuff defined here. Let's keep it clean.
+//
+// Since slices don't support inherent methods; all operations
+// on them are defined on traits, which are then reexported from
+// the prelude for convenience. So there are a lot of traits here.
+//
+// The layout of this file is thus:
+//
+// * Slice-specific 'extension' traits and their implementations. This
+//   is where most of the slice API resides.
+// * Implementations of a few common traits with important slice ops.
+// * Definitions of a bunch of iterators.
+// * Free functions.
+// * The `raw` and `bytes` submodules.
+// * Boilerplate trait implementations.
+
 use mem::transmute;
 use clone::Clone;
 use collections::Collection;
-use cmp::{PartialEq, Ord, Ordering, Less, Equal, Greater};
+use cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering, Less, Equal, Greater, Equiv};
 use cmp;
 use default::Default;
 use iter::*;
 use kinds::marker;
 use raw::{Repr, Slice};
 
-/**
- * Converts a pointer to A into a slice of length 1 (without copying).
- */
-pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
-    unsafe {
-        transmute(Slice { data: s, len: 1 })
-    }
+//
+// Extension traits
+//
+
+/// Extension methods for vectors
+pub trait ImmutableVector<'a, T> {
+    /**
+     * Returns a slice of self spanning the interval [`start`, `end`).
+     *
+     * Fails when the slice (or part of it) is outside the bounds of self,
+     * or when `start` > `end`.
+     */
+    fn slice(&self, start: uint, end: uint) -> &'a [T];
+
+    /**
+     * Returns a slice of self from `start` to the end of the vec.
+     *
+     * Fails when `start` points outside the bounds of self.
+     */
+    fn slice_from(&self, start: uint) -> &'a [T];
+
+    /**
+     * Returns a slice of self from the start of the vec to `end`.
+     *
+     * Fails when `end` points outside the bounds of self.
+     */
+    fn slice_to(&self, end: uint) -> &'a [T];
+    /// Returns an iterator over the vector
+    fn iter(self) -> Items<'a, T>;
+    /// Returns an iterator over the subslices of the vector which are
+    /// separated by elements that match `pred`.  The matched element
+    /// is not contained in the subslices.
+    fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T>;
+    /// Returns an iterator over the subslices of the vector which are
+    /// separated by elements that match `pred`, limited to splitting
+    /// at most `n` times.  The matched element is not contained in
+    /// the subslices.
+    fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>;
+    /// Returns an iterator over the subslices of the vector which are
+    /// separated by elements that match `pred` limited to splitting
+    /// at most `n` times. This starts at the end of the vector and
+    /// works backwards.  The matched element is not contained in the
+    /// subslices.
+    fn rsplitn(self,  n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>;
+
+    /**
+     * Returns an iterator over all contiguous windows of length
+     * `size`. The windows overlap. If the vector is shorter than
+     * `size`, the iterator returns no values.
+     *
+     * # Failure
+     *
+     * Fails if `size` is 0.
+     *
+     * # Example
+     *
+     * Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`,
+     * `[3,4]`):
+     *
+     * ```rust
+     * let v = &[1i, 2, 3, 4];
+     * for win in v.windows(2) {
+     *     println!("{}", win);
+     * }
+     * ```
+     *
+     */
+    fn windows(self, size: uint) -> Windows<'a, T>;
+    /**
+     *
+     * Returns an iterator over `size` elements of the vector at a
+     * time. The chunks do not overlap. If `size` does not divide the
+     * length of the vector, then the last chunk will not have length
+     * `size`.
+     *
+     * # Failure
+     *
+     * Fails if `size` is 0.
+     *
+     * # Example
+     *
+     * Print the vector two elements at a time (i.e. `[1,2]`,
+     * `[3,4]`, `[5]`):
+     *
+     * ```rust
+     * let v = &[1i, 2, 3, 4, 5];
+     * for win in v.chunks(2) {
+     *     println!("{}", win);
+     * }
+     * ```
+     *
+     */
+    fn chunks(self, size: uint) -> Chunks<'a, T>;
+
+    /// Returns the element of a vector at the given index, or `None` if the
+    /// index is out of bounds
+    fn get(&self, index: uint) -> Option<&'a T>;
+    /// Returns the first element of a vector, or `None` if it is empty
+    fn head(&self) -> Option<&'a T>;
+    /// Returns all but the first element of a vector
+    fn tail(&self) -> &'a [T];
+    /// Returns all but the first `n' elements of a vector
+    fn tailn(&self, n: uint) -> &'a [T];
+    /// Returns all but the last element of a vector
+    fn init(&self) -> &'a [T];
+    /// Returns all but the last `n' elements of a vector
+    fn initn(&self, n: uint) -> &'a [T];
+    /// Returns the last element of a vector, or `None` if it is empty.
+    fn last(&self) -> Option<&'a T>;
+
+    /// Returns a pointer to the element at the given index, without doing
+    /// bounds checking.
+    unsafe fn unsafe_ref(self, index: uint) -> &'a T;
+
+    /**
+     * Returns an unsafe pointer to the vector's buffer
+     *
+     * The caller must ensure that the vector outlives the pointer this
+     * function returns, or else it will end up pointing to garbage.
+     *
+     * Modifying the vector may cause its buffer to be reallocated, which
+     * would also make any pointers to it invalid.
+     */
+    fn as_ptr(&self) -> *const T;
+
+    /**
+     * Binary search a sorted vector with a comparator function.
+     *
+     * The comparator function should implement an order consistent
+     * with the sort order of the underlying vector, returning an
+     * order code that indicates whether its argument is `Less`,
+     * `Equal` or `Greater` the desired target.
+     *
+     * Returns the index where the comparator returned `Equal`, or `None` if
+     * not found.
+     */
+    fn bsearch(&self, f: |&T| -> Ordering) -> Option<uint>;
+
+    /**
+     * Returns an immutable reference to the first element in this slice
+     * and adjusts the slice in place so that it no longer contains
+     * that element. O(1).
+     *
+     * Equivalent to:
+     *
+     * ```ignore
+     *     if self.len() == 0 { return None }
+     *     let head = &self[0];
+     *     *self = self.slice_from(1);
+     *     Some(head)
+     * ```
+     *
+     * Returns `None` if vector is empty
+     */
+    fn shift_ref(&mut self) -> Option<&'a T>;
+
+    /**
+     * Returns an immutable reference to the last element in this slice
+     * and adjusts the slice in place so that it no longer contains
+     * that element. O(1).
+     *
+     * Equivalent to:
+     *
+     * ```ignore
+     *     if self.len() == 0 { return None; }
+     *     let tail = &self[self.len() - 1];
+     *     *self = self.slice_to(self.len() - 1);
+     *     Some(tail)
+     * ```
+     *
+     * Returns `None` if slice is empty.
+     */
+    fn pop_ref(&mut self) -> Option<&'a T>;
 }
 
-/**
- * Converts a pointer to A into a slice of length 1 (without copying).
- */
-pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
-    unsafe {
-        let ptr: *const A = transmute(s);
-        transmute(Slice { data: ptr, len: 1 })
+impl<'a,T> ImmutableVector<'a, T> for &'a [T] {
+    #[inline]
+    fn slice(&self, start: uint, end: uint) -> &'a [T] {
+        assert!(start <= end);
+        assert!(end <= self.len());
+        unsafe {
+            transmute(Slice {
+                    data: self.as_ptr().offset(start as int),
+                    len: (end - start)
+                })
+        }
     }
-}
 
-/// An iterator over the slices of a vector separated by elements that
-/// match a predicate function.
-pub struct Splits<'a, T> {
-    v: &'a [T],
-    pred: |t: &T|: 'a -> bool,
-    finished: bool
-}
+    #[inline]
+    fn slice_from(&self, start: uint) -> &'a [T] {
+        self.slice(start, self.len())
+    }
 
-impl<'a, T> Iterator<&'a [T]> for Splits<'a, T> {
     #[inline]
-    fn next(&mut self) -> Option<&'a [T]> {
-        if self.finished { return None; }
+    fn slice_to(&self, end: uint) -> &'a [T] {
+        self.slice(0, end)
+    }
 
-        match self.v.iter().position(|x| (self.pred)(x)) {
-            None => {
-                self.finished = true;
-                Some(self.v)
-            }
-            Some(idx) => {
-                let ret = Some(self.v.slice(0, idx));
-                self.v = self.v.slice(idx + 1, self.v.len());
-                ret
+    #[inline]
+    fn iter(self) -> Items<'a, T> {
+        unsafe {
+            let p = self.as_ptr();
+            if mem::size_of::<T>() == 0 {
+                Items{ptr: p,
+                      end: (p as uint + self.len()) as *const T,
+                      marker: marker::ContravariantLifetime::<'a>}
+            } else {
+                Items{ptr: p,
+                      end: p.offset(self.len() as int),
+                      marker: marker::ContravariantLifetime::<'a>}
             }
         }
     }
 
     #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        if self.finished {
-            (0, Some(0))
-        } else {
-            (1, Some(self.v.len() + 1))
+    fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T> {
+        Splits {
+            v: self,
+            pred: pred,
+            finished: false
         }
     }
-}
 
-impl<'a, T> DoubleEndedIterator<&'a [T]> for Splits<'a, T> {
     #[inline]
-    fn next_back(&mut self) -> Option<&'a [T]> {
-        if self.finished { return None; }
-
-        match self.v.iter().rposition(|x| (self.pred)(x)) {
-            None => {
-                self.finished = true;
-                Some(self.v)
-            }
-            Some(idx) => {
-                let ret = Some(self.v.slice(idx + 1, self.v.len()));
-                self.v = self.v.slice(0, idx);
-                ret
-            }
+    fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T> {
+        SplitsN {
+            iter: self.split(pred),
+            count: n,
+            invert: false
         }
     }
-}
 
-/// An iterator over the slices of a vector separated by elements that
-/// match a predicate function, splitting at most a fixed number of times.
-pub struct SplitsN<'a, T> {
-    iter: Splits<'a, T>,
-    count: uint,
-    invert: bool
-}
-
-impl<'a, T> Iterator<&'a [T]> for SplitsN<'a, T> {
     #[inline]
-    fn next(&mut self) -> Option<&'a [T]> {
-        if self.count == 0 {
-            if self.iter.finished {
-                None
-            } else {
-                self.iter.finished = true;
-                Some(self.iter.v)
-            }
-        } else {
-            self.count -= 1;
-            if self.invert { self.iter.next_back() } else { self.iter.next() }
+    fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T> {
+        SplitsN {
+            iter: self.split(pred),
+            count: n,
+            invert: true
         }
     }
 
     #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        if self.iter.finished {
-            (0, Some(0))
-        } else {
-            (1, Some(cmp::min(self.count, self.iter.v.len()) + 1))
-        }
+    fn windows(self, size: uint) -> Windows<'a, T> {
+        assert!(size != 0);
+        Windows { v: self, size: size }
     }
-}
-
-// Functional utilities
 
-/// An iterator over the (overlapping) slices of length `size` within
-/// a vector.
-#[deriving(Clone)]
-pub struct Windows<'a, T> {
-    v: &'a [T],
-    size: uint
-}
+    #[inline]
+    fn chunks(self, size: uint) -> Chunks<'a, T> {
+        assert!(size != 0);
+        Chunks { v: self, size: size }
+    }
 
-impl<'a, T> Iterator<&'a [T]> for Windows<'a, T> {
     #[inline]
-    fn next(&mut self) -> Option<&'a [T]> {
-        if self.size > self.v.len() {
-            None
-        } else {
-            let ret = Some(self.v.slice(0, self.size));
-            self.v = self.v.slice(1, self.v.len());
-            ret
-        }
+    fn get(&self, index: uint) -> Option<&'a T> {
+        if index < self.len() { Some(&self[index]) } else { None }
     }
 
     #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        if self.size > self.v.len() {
-            (0, Some(0))
-        } else {
-            let x = self.v.len() - self.size;
-            (x.saturating_add(1), x.checked_add(&1u))
-        }
+    fn head(&self) -> Option<&'a T> {
+        if self.len() == 0 { None } else { Some(&self[0]) }
     }
-}
 
-/// An iterator over a vector in (non-overlapping) chunks (`size`
-/// elements at a time).
-///
-/// When the vector len is not evenly divided by the chunk size,
-/// the last slice of the iteration will be the remainder.
-#[deriving(Clone)]
-pub struct Chunks<'a, T> {
-    v: &'a [T],
-    size: uint
-}
+    #[inline]
+    fn tail(&self) -> &'a [T] { self.slice(1, self.len()) }
 
-impl<'a, T> Iterator<&'a [T]> for Chunks<'a, T> {
     #[inline]
-    fn next(&mut self) -> Option<&'a [T]> {
-        if self.v.len() == 0 {
-            None
-        } else {
-            let chunksz = cmp::min(self.v.len(), self.size);
-            let (fst, snd) = (self.v.slice_to(chunksz),
-                              self.v.slice_from(chunksz));
-            self.v = snd;
-            Some(fst)
-        }
-    }
+    fn tailn(&self, n: uint) -> &'a [T] { self.slice(n, self.len()) }
 
     #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        if self.v.len() == 0 {
-            (0, Some(0))
-        } else {
-            let (n, rem) = div_rem(self.v.len(), self.size);
-            let n = if rem > 0 { n+1 } else { n };
-            (n, Some(n))
-        }
+    fn init(&self) -> &'a [T] {
+        self.slice(0, self.len() - 1)
     }
-}
 
-impl<'a, T> DoubleEndedIterator<&'a [T]> for Chunks<'a, T> {
     #[inline]
-    fn next_back(&mut self) -> Option<&'a [T]> {
-        if self.v.len() == 0 {
-            None
-        } else {
-            let remainder = self.v.len() % self.size;
-            let chunksz = if remainder != 0 { remainder } else { self.size };
-            let (fst, snd) = (self.v.slice_to(self.v.len() - chunksz),
-                              self.v.slice_from(self.v.len() - chunksz));
-            self.v = fst;
-            Some(snd)
-        }
+    fn initn(&self, n: uint) -> &'a [T] {
+        self.slice(0, self.len() - n)
     }
-}
 
-impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> {
     #[inline]
-    fn indexable(&self) -> uint {
-        self.v.len()/self.size + if self.v.len() % self.size != 0 { 1 } else { 0 }
+    fn last(&self) -> Option<&'a T> {
+            if self.len() == 0 { None } else { Some(&self[self.len() - 1]) }
     }
 
     #[inline]
-    fn idx(&mut self, index: uint) -> Option<&'a [T]> {
-        if index < self.indexable() {
-            let lo = index * self.size;
-            let mut hi = lo + self.size;
-            if hi < lo || hi > self.v.len() { hi = self.v.len(); }
-
-            Some(self.v.slice(lo, hi))
-        } else {
-            None
-        }
+    unsafe fn unsafe_ref(self, index: uint) -> &'a T {
+        transmute(self.repr().data.offset(index as int))
     }
-}
 
-// Equality
+    #[inline]
+    fn as_ptr(&self) -> *const T {
+        self.repr().data
+    }
 
-#[allow(missing_doc)]
-pub mod traits {
-    use super::*;
 
-    use cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering, Equiv};
-    use iter::order;
-    use collections::Collection;
-    use option::Option;
+    fn bsearch(&self, f: |&T| -> Ordering) -> Option<uint> {
+        let mut base : uint = 0;
+        let mut lim : uint = self.len();
 
-    impl<'a,T:PartialEq> PartialEq for &'a [T] {
-        fn eq(&self, other: & &'a [T]) -> bool {
-            self.len() == other.len() &&
-                order::eq(self.iter(), other.iter())
-        }
-        fn ne(&self, other: & &'a [T]) -> bool {
-            self.len() != other.len() ||
-                order::ne(self.iter(), other.iter())
+        while lim != 0 {
+            let ix = base + (lim >> 1);
+            match f(&self[ix]) {
+                Equal => return Some(ix),
+                Less => {
+                    base = ix + 1;
+                    lim -= 1;
+                }
+                Greater => ()
+            }
+            lim >>= 1;
         }
+        return None;
     }
 
-    impl<'a,T:Eq> Eq for &'a [T] {}
-
-    impl<'a,T:PartialEq, V: Vector<T>> Equiv<V> for &'a [T] {
-        #[inline]
-        fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
-    }
-
-    impl<'a,T:Ord> Ord for &'a [T] {
-        fn cmp(&self, other: & &'a [T]) -> Ordering {
-            order::cmp(self.iter(), other.iter())
+    fn shift_ref(&mut self) -> Option<&'a T> {
+        unsafe {
+            let s: &mut Slice<T> = transmute(self);
+            match raw::shift_ptr(s) {
+                Some(p) => Some(&*p),
+                None => None
+            }
         }
     }
 
-    impl<'a, T: PartialOrd> PartialOrd for &'a [T] {
-        #[inline]
-        fn partial_cmp(&self, other: &&'a [T]) -> Option<Ordering> {
-            order::partial_cmp(self.iter(), other.iter())
-        }
-        #[inline]
-        fn lt(&self, other: & &'a [T]) -> bool {
-            order::lt(self.iter(), other.iter())
-        }
-        #[inline]
-        fn le(&self, other: & &'a [T]) -> bool {
-            order::le(self.iter(), other.iter())
-        }
-        #[inline]
-        fn ge(&self, other: & &'a [T]) -> bool {
-            order::ge(self.iter(), other.iter())
-        }
-        #[inline]
-        fn gt(&self, other: & &'a [T]) -> bool {
-            order::gt(self.iter(), other.iter())
+    fn pop_ref(&mut self) -> Option<&'a T> {
+        unsafe {
+            let s: &mut Slice<T> = transmute(self);
+            match raw::pop_ptr(s) {
+                Some(p) => Some(&*p),
+                None => None
+            }
         }
     }
 }
 
-/// Any vector that can be represented as a slice.
-pub trait Vector<T> {
-    /// Work with `self` as a slice.
-    fn as_slice<'a>(&'a self) -> &'a [T];
-}
-
-impl<'a,T> Vector<T> for &'a [T] {
-    #[inline(always)]
-    fn as_slice<'a>(&'a self) -> &'a [T] { *self }
-}
-
-impl<'a, T> Collection for &'a [T] {
-    /// Returns the length of a vector
-    #[inline]
-    fn len(&self) -> uint {
-        self.repr().len
-    }
-}
+/// Extension methods for vectors such that their elements are
+/// mutable.
+pub trait MutableVector<'a, T> {
+    /// Returns a mutable reference to the element at the given index,
+    /// or `None` if the index is out of bounds
+    fn get_mut(self, index: uint) -> Option<&'a mut T>;
+    /// Work with `self` as a mut slice.
+    /// Primarily intended for getting a &mut [T] from a [T, ..N].
+    fn as_mut_slice(self) -> &'a mut [T];
 
-/// Extension methods for vectors
-pub trait ImmutableVector<'a, T> {
-    /**
-     * Returns a slice of self spanning the interval [`start`, `end`).
-     *
-     * Fails when the slice (or part of it) is outside the bounds of self,
-     * or when `start` > `end`.
-     */
-    fn slice(&self, start: uint, end: uint) -> &'a [T];
+    /// Return a slice that points into another slice.
+    fn mut_slice(self, start: uint, end: uint) -> &'a mut [T];
 
     /**
      * Returns a slice of self from `start` to the end of the vec.
      *
      * Fails when `start` points outside the bounds of self.
      */
-    fn slice_from(&self, start: uint) -> &'a [T];
+    fn mut_slice_from(self, start: uint) -> &'a mut [T];
 
     /**
      * Returns a slice of self from the start of the vec to `end`.
      *
      * Fails when `end` points outside the bounds of self.
      */
-    fn slice_to(&self, end: uint) -> &'a [T];
-    /// Returns an iterator over the vector
-    fn iter(self) -> Items<'a, T>;
-    /// Returns an iterator over the subslices of the vector which are
-    /// separated by elements that match `pred`.  The matched element
-    /// is not contained in the subslices.
-    fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T>;
-    /// Returns an iterator over the subslices of the vector which are
-    /// separated by elements that match `pred`, limited to splitting
-    /// at most `n` times.  The matched element is not contained in
-    /// the subslices.
-    fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>;
-    /// Returns an iterator over the subslices of the vector which are
-    /// separated by elements that match `pred` limited to splitting
-    /// at most `n` times. This starts at the end of the vector and
-    /// works backwards.  The matched element is not contained in the
-    /// subslices.
-    fn rsplitn(self,  n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>;
+    fn mut_slice_to(self, end: uint) -> &'a mut [T];
+
+    /// Returns an iterator that allows modifying each value
+    fn mut_iter(self) -> MutItems<'a, T>;
+
+    /// Returns a mutable pointer to the last item in the vector.
+    fn mut_last(self) -> Option<&'a mut T>;
+
+    /// Returns an iterator over the mutable subslices of the vector
+    /// which are separated by elements that match `pred`.  The
+    /// matched element is not contained in the subslices.
+    fn mut_split(self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T>;
 
     /**
-     * Returns an iterator over all contiguous windows of length
-     * `size`. The windows overlap. If the vector is shorter than
-     * `size`, the iterator returns no values.
-     *
-     * # Failure
-     *
-     * Fails if `size` is 0.
-     *
-     * # Example
-     *
-     * Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`,
-     * `[3,4]`):
-     *
-     * ```rust
-     * let v = &[1i, 2, 3, 4];
-     * for win in v.windows(2) {
-     *     println!("{}", win);
-     * }
-     * ```
-     *
-     */
-    fn windows(self, size: uint) -> Windows<'a, T>;
-    /**
-     *
-     * Returns an iterator over `size` elements of the vector at a
-     * time. The chunks do not overlap. If `size` does not divide the
+     * Returns an iterator over `size` elements of the vector at a time.
+     * The chunks are mutable and do not overlap. If `size` does not divide the
      * length of the vector, then the last chunk will not have length
      * `size`.
      *
      * # Failure
      *
      * Fails if `size` is 0.
-     *
-     * # Example
-     *
-     * Print the vector two elements at a time (i.e. `[1,2]`,
-     * `[3,4]`, `[5]`):
-     *
-     * ```rust
-     * let v = &[1i, 2, 3, 4, 5];
-     * for win in v.chunks(2) {
-     *     println!("{}", win);
-     * }
-     * ```
-     *
-     */
-    fn chunks(self, size: uint) -> Chunks<'a, T>;
-
-    /// Returns the element of a vector at the given index, or `None` if the
-    /// index is out of bounds
-    fn get(&self, index: uint) -> Option<&'a T>;
-    /// Returns the first element of a vector, or `None` if it is empty
-    fn head(&self) -> Option<&'a T>;
-    /// Returns all but the first element of a vector
-    fn tail(&self) -> &'a [T];
-    /// Returns all but the first `n' elements of a vector
-    fn tailn(&self, n: uint) -> &'a [T];
-    /// Returns all but the last element of a vector
-    fn init(&self) -> &'a [T];
-    /// Returns all but the last `n' elements of a vector
-    fn initn(&self, n: uint) -> &'a [T];
-    /// Returns the last element of a vector, or `None` if it is empty.
-    fn last(&self) -> Option<&'a T>;
-
-    /// Returns a pointer to the element at the given index, without doing
-    /// bounds checking.
-    unsafe fn unsafe_ref(self, index: uint) -> &'a T;
-
-    /**
-     * Returns an unsafe pointer to the vector's buffer
-     *
-     * The caller must ensure that the vector outlives the pointer this
-     * function returns, or else it will end up pointing to garbage.
-     *
-     * Modifying the vector may cause its buffer to be reallocated, which
-     * would also make any pointers to it invalid.
-     */
-    fn as_ptr(&self) -> *const T;
-
-    /**
-     * Binary search a sorted vector with a comparator function.
-     *
-     * The comparator function should implement an order consistent
-     * with the sort order of the underlying vector, returning an
-     * order code that indicates whether its argument is `Less`,
-     * `Equal` or `Greater` the desired target.
-     *
-     * Returns the index where the comparator returned `Equal`, or `None` if
-     * not found.
      */
-    fn bsearch(&self, f: |&T| -> Ordering) -> Option<uint>;
+    fn mut_chunks(self, chunk_size: uint) -> MutChunks<'a, T>;
 
     /**
-     * Returns an immutable reference to the first element in this slice
+     * Returns a mutable reference to the first element in this slice
      * and adjusts the slice in place so that it no longer contains
      * that element. O(1).
      *
      * Equivalent to:
      *
      * ```ignore
-     *     if self.len() == 0 { return None }
-     *     let head = &self[0];
-     *     *self = self.slice_from(1);
+     *     if self.len() == 0 { return None; }
+     *     let head = &mut self[0];
+     *     *self = self.mut_slice_from(1);
      *     Some(head)
      * ```
      *
-     * Returns `None` if vector is empty
+     * Returns `None` if slice is empty
      */
-    fn shift_ref(&mut self) -> Option<&'a T>;
+    fn mut_shift_ref(&mut self) -> Option<&'a mut T>;
 
     /**
-     * Returns an immutable reference to the last element in this slice
+     * Returns a mutable reference to the last element in this slice
      * and adjusts the slice in place so that it no longer contains
      * that element. O(1).
      *
@@ -483,174 +461,282 @@ pub trait ImmutableVector<'a, T> {
      *
      * ```ignore
      *     if self.len() == 0 { return None; }
-     *     let tail = &self[self.len() - 1];
-     *     *self = self.slice_to(self.len() - 1);
+     *     let tail = &mut self[self.len() - 1];
+     *     *self = self.mut_slice_to(self.len() - 1);
      *     Some(tail)
      * ```
      *
      * Returns `None` if slice is empty.
      */
-    fn pop_ref(&mut self) -> Option<&'a T>;
-}
-
-impl<'a,T> ImmutableVector<'a, T> for &'a [T] {
-    #[inline]
-    fn slice(&self, start: uint, end: uint) -> &'a [T] {
-        assert!(start <= end);
-        assert!(end <= self.len());
-        unsafe {
-            transmute(Slice {
-                    data: self.as_ptr().offset(start as int),
-                    len: (end - start)
-                })
-        }
-    }
+    fn mut_pop_ref(&mut self) -> Option<&'a mut T>;
 
-    #[inline]
-    fn slice_from(&self, start: uint) -> &'a [T] {
-        self.slice(start, self.len())
-    }
+    /// Swaps two elements in a vector.
+    ///
+    /// Fails if `a` or `b` are out of bounds.
+    ///
+    /// # Arguments
+    ///
+    /// * a - The index of the first element
+    /// * b - The index of the second element
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let mut v = ["a", "b", "c", "d"];
+    /// v.swap(1, 3);
+    /// assert!(v == ["a", "d", "c", "b"]);
+    /// ```
+    fn swap(self, a: uint, b: uint);
 
-    #[inline]
-    fn slice_to(&self, end: uint) -> &'a [T] {
-        self.slice(0, end)
-    }
 
-    #[inline]
-    fn iter(self) -> Items<'a, T> {
-        unsafe {
-            let p = self.as_ptr();
-            if mem::size_of::<T>() == 0 {
-                Items{ptr: p,
-                      end: (p as uint + self.len()) as *const T,
-                      marker: marker::ContravariantLifetime::<'a>}
-            } else {
-                Items{ptr: p,
-                      end: p.offset(self.len() as int),
-                      marker: marker::ContravariantLifetime::<'a>}
-            }
-        }
-    }
+    /// Divides one `&mut` into two at an index.
+    ///
+    /// The first will contain all indices from `[0, mid)` (excluding
+    /// the index `mid` itself) and the second will contain all
+    /// indices from `[mid, len)` (excluding the index `len` itself).
+    ///
+    /// Fails if `mid > len`.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let mut v = [1i, 2, 3, 4, 5, 6];
+    ///
+    /// // scoped to restrict the lifetime of the borrows
+    /// {
+    ///    let (left, right) = v.mut_split_at(0);
+    ///    assert!(left == &mut []);
+    ///    assert!(right == &mut [1i, 2, 3, 4, 5, 6]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.mut_split_at(2);
+    ///     assert!(left == &mut [1i, 2]);
+    ///     assert!(right == &mut [3i, 4, 5, 6]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.mut_split_at(6);
+    ///     assert!(left == &mut [1i, 2, 3, 4, 5, 6]);
+    ///     assert!(right == &mut []);
+    /// }
+    /// ```
+    fn mut_split_at(self, mid: uint) -> (&'a mut [T], &'a mut [T]);
 
-    #[inline]
-    fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T> {
-        Splits {
-            v: self,
-            pred: pred,
-            finished: false
-        }
-    }
+    /// Reverse the order of elements in a vector, in place.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let mut v = [1i, 2, 3];
+    /// v.reverse();
+    /// assert!(v == [3i, 2, 1]);
+    /// ```
+    fn reverse(self);
 
-    #[inline]
-    fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T> {
-        SplitsN {
-            iter: self.split(pred),
-            count: n,
-            invert: false
-        }
-    }
+    /// Returns an unsafe mutable pointer to the element in index
+    unsafe fn unsafe_mut_ref(self, index: uint) -> &'a mut T;
 
+    /// Return an unsafe mutable pointer to the vector's buffer.
+    ///
+    /// The caller must ensure that the vector outlives the pointer this
+    /// function returns, or else it will end up pointing to garbage.
+    ///
+    /// Modifying the vector may cause its buffer to be reallocated, which
+    /// would also make any pointers to it invalid.
     #[inline]
-    fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T> {
-        SplitsN {
-            iter: self.split(pred),
-            count: n,
-            invert: true
-        }
-    }
+    fn as_mut_ptr(self) -> *mut T;
 
-    #[inline]
-    fn windows(self, size: uint) -> Windows<'a, T> {
-        assert!(size != 0);
-        Windows { v: self, size: size }
-    }
+    /// Unsafely sets the element in index to the value.
+    ///
+    /// This performs no bounds checks, and it is undefined behaviour
+    /// if `index` is larger than the length of `self`. However, it
+    /// does run the destructor at `index`. It is equivalent to
+    /// `self[index] = val`.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let mut v = ["foo".to_string(), "bar".to_string(), "baz".to_string()];
+    ///
+    /// unsafe {
+    ///     // `"baz".to_string()` is deallocated.
+    ///     v.unsafe_set(2, "qux".to_string());
+    ///
+    ///     // Out of bounds: could cause a crash, or overwriting
+    ///     // other data, or something else.
+    ///     // v.unsafe_set(10, "oops".to_string());
+    /// }
+    /// ```
+    unsafe fn unsafe_set(self, index: uint, val: T);
 
-    #[inline]
-    fn chunks(self, size: uint) -> Chunks<'a, T> {
-        assert!(size != 0);
-        Chunks { v: self, size: size }
-    }
+    /// Unchecked vector index assignment.  Does not drop the
+    /// old value and hence is only suitable when the vector
+    /// is newly allocated.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let mut v = ["foo".to_string(), "bar".to_string()];
+    ///
+    /// // memory leak! `"bar".to_string()` is not deallocated.
+    /// unsafe { v.init_elem(1, "baz".to_string()); }
+    /// ```
+    unsafe fn init_elem(self, i: uint, val: T);
 
-    #[inline]
-    fn get(&self, index: uint) -> Option<&'a T> {
-        if index < self.len() { Some(&self[index]) } else { None }
-    }
+    /// Copies raw bytes from `src` to `self`.
+    ///
+    /// This does not run destructors on the overwritten elements, and
+    /// ignores move semantics. `self` and `src` must not
+    /// overlap. Fails if `self` is shorter than `src`.
+    unsafe fn copy_memory(self, src: &[T]);
+}
 
+impl<'a,T> MutableVector<'a, T> for &'a mut [T] {
     #[inline]
-    fn head(&self) -> Option<&'a T> {
-        if self.len() == 0 { None } else { Some(&self[0]) }
+    fn get_mut(self, index: uint) -> Option<&'a mut T> {
+        if index < self.len() { Some(&mut self[index]) } else { None }
     }
 
     #[inline]
-    fn tail(&self) -> &'a [T] { self.slice(1, self.len()) }
+    fn as_mut_slice(self) -> &'a mut [T] { self }
 
-    #[inline]
-    fn tailn(&self, n: uint) -> &'a [T] { self.slice(n, self.len()) }
+    fn mut_slice(self, start: uint, end: uint) -> &'a mut [T] {
+        assert!(start <= end);
+        assert!(end <= self.len());
+        unsafe {
+            transmute(Slice {
+                    data: self.as_mut_ptr().offset(start as int) as *const T,
+                    len: (end - start)
+                })
+        }
+    }
 
     #[inline]
-    fn init(&self) -> &'a [T] {
-        self.slice(0, self.len() - 1)
+    fn mut_slice_from(self, start: uint) -> &'a mut [T] {
+        let len = self.len();
+        self.mut_slice(start, len)
     }
 
     #[inline]
-    fn initn(&self, n: uint) -> &'a [T] {
-        self.slice(0, self.len() - n)
+    fn mut_slice_to(self, end: uint) -> &'a mut [T] {
+        self.mut_slice(0, end)
     }
 
     #[inline]
-    fn last(&self) -> Option<&'a T> {
-            if self.len() == 0 { None } else { Some(&self[self.len() - 1]) }
+    fn mut_split_at(self, mid: uint) -> (&'a mut [T], &'a mut [T]) {
+        unsafe {
+            let len = self.len();
+            let self2: &'a mut [T] = mem::transmute_copy(&self);
+            (self.mut_slice(0, mid), self2.mut_slice(mid, len))
+        }
     }
 
     #[inline]
-    unsafe fn unsafe_ref(self, index: uint) -> &'a T {
-        transmute(self.repr().data.offset(index as int))
+    fn mut_iter(self) -> MutItems<'a, T> {
+        unsafe {
+            let p = self.as_mut_ptr();
+            if mem::size_of::<T>() == 0 {
+                MutItems{ptr: p,
+                         end: (p as uint + self.len()) as *mut T,
+                         marker: marker::ContravariantLifetime::<'a>,
+                         marker2: marker::NoCopy}
+            } else {
+                MutItems{ptr: p,
+                         end: p.offset(self.len() as int),
+                         marker: marker::ContravariantLifetime::<'a>,
+                         marker2: marker::NoCopy}
+            }
+        }
     }
 
     #[inline]
-    fn as_ptr(&self) -> *const T {
-        self.repr().data
+    fn mut_last(self) -> Option<&'a mut T> {
+        let len = self.len();
+        if len == 0 { return None; }
+        Some(&mut self[len - 1])
     }
 
+    #[inline]
+    fn mut_split(self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T> {
+        MutSplits { v: self, pred: pred, finished: false }
+    }
 
-    fn bsearch(&self, f: |&T| -> Ordering) -> Option<uint> {
-        let mut base : uint = 0;
-        let mut lim : uint = self.len();
-
-        while lim != 0 {
-            let ix = base + (lim >> 1);
-            match f(&self[ix]) {
-                Equal => return Some(ix),
-                Less => {
-                    base = ix + 1;
-                    lim -= 1;
-                }
-                Greater => ()
-            }
-            lim >>= 1;
-        }
-        return None;
+    #[inline]
+    fn mut_chunks(self, chunk_size: uint) -> MutChunks<'a, T> {
+        assert!(chunk_size > 0);
+        MutChunks { v: self, chunk_size: chunk_size }
     }
 
-    fn shift_ref(&mut self) -> Option<&'a T> {
+    fn mut_shift_ref(&mut self) -> Option<&'a mut T> {
         unsafe {
             let s: &mut Slice<T> = transmute(self);
             match raw::shift_ptr(s) {
-                Some(p) => Some(&*p),
-                None => None
+                // FIXME #13933: this `&` -> `&mut` cast is a little
+                // dubious
+                Some(p) => Some(&mut *(p as *mut _)),
+                None => None,
             }
         }
     }
 
-    fn pop_ref(&mut self) -> Option<&'a T> {
+    fn mut_pop_ref(&mut self) -> Option<&'a mut T> {
         unsafe {
             let s: &mut Slice<T> = transmute(self);
             match raw::pop_ptr(s) {
-                Some(p) => Some(&*p),
-                None => None
+                // FIXME #13933: this `&` -> `&mut` cast is a little
+                // dubious
+                Some(p) => Some(&mut *(p as *mut _)),
+                None => None,
             }
         }
     }
+
+    fn swap(self, a: uint, b: uint) {
+        unsafe {
+            // Can't take two mutable loans from one vector, so instead just cast
+            // them to their raw pointers to do the swap
+            let pa: *mut T = &mut self[a];
+            let pb: *mut T = &mut self[b];
+            ptr::swap(pa, pb);
+        }
+    }
+
+    fn reverse(self) {
+        let mut i: uint = 0;
+        let ln = self.len();
+        while i < ln / 2 {
+            self.swap(i, ln - i - 1);
+            i += 1;
+        }
+    }
+
+    #[inline]
+    unsafe fn unsafe_mut_ref(self, index: uint) -> &'a mut T {
+        transmute((self.repr().data as *mut T).offset(index as int))
+    }
+
+    #[inline]
+    fn as_mut_ptr(self) -> *mut T {
+        self.repr().data as *mut T
+    }
+
+    #[inline]
+    unsafe fn unsafe_set(self, index: uint, val: T) {
+        *self.unsafe_mut_ref(index) = val;
+    }
+
+    #[inline]
+    unsafe fn init_elem(self, i: uint, val: T) {
+        ptr::write(&mut (*self.as_mut_ptr().offset(i as int)), val);
+    }
+
+    #[inline]
+    unsafe fn copy_memory(self, src: &[T]) {
+        let len_src = src.len();
+        assert!(self.len() >= len_src);
+        ptr::copy_nonoverlapping_memory(self.as_mut_ptr(), src.as_ptr(), len_src)
+    }
 }
 
 /// Extension methods for vectors contain `PartialEq` elements.
@@ -716,395 +802,523 @@ fn bsearch_elem(&self, x: &T) -> Option<uint> {
     }
 }
 
-/// Extension methods for vectors such that their elements are
-/// mutable.
-pub trait MutableVector<'a, T> {
-    /// Returns a mutable reference to the element at the given index,
-    /// or `None` if the index is out of bounds
-    fn get_mut(self, index: uint) -> Option<&'a mut T>;
-    /// Work with `self` as a mut slice.
-    /// Primarily intended for getting a &mut [T] from a [T, ..N].
-    fn as_mut_slice(self) -> &'a mut [T];
+/// Trait for &[T] where T is Cloneable
+pub trait MutableCloneableVector<T> {
+    /// Copies as many elements from `src` as it can into `self` (the
+    /// shorter of `self.len()` and `src.len()`). Returns the number
+    /// of elements copied.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::slice::MutableCloneableVector;
+    ///
+    /// let mut dst = [0i, 0, 0];
+    /// let src = [1i, 2];
+    ///
+    /// assert!(dst.copy_from(src) == 2);
+    /// assert!(dst == [1, 2, 0]);
+    ///
+    /// let src2 = [3i, 4, 5, 6];
+    /// assert!(dst.copy_from(src2) == 3);
+    /// assert!(dst == [3i, 4, 5]);
+    /// ```
+    fn copy_from(self, &[T]) -> uint;
+}
 
-    /// Return a slice that points into another slice.
-    fn mut_slice(self, start: uint, end: uint) -> &'a mut [T];
+impl<'a, T:Clone> MutableCloneableVector<T> for &'a mut [T] {
+    #[inline]
+    fn copy_from(self, src: &[T]) -> uint {
+        for (a, b) in self.mut_iter().zip(src.iter()) {
+            a.clone_from(b);
+        }
+        cmp::min(self.len(), src.len())
+    }
+}
 
-    /**
-     * Returns a slice of self from `start` to the end of the vec.
-     *
-     * Fails when `start` points outside the bounds of self.
-     */
-    fn mut_slice_from(self, start: uint) -> &'a mut [T];
 
-    /**
-     * Returns a slice of self from the start of the vec to `end`.
-     *
-     * Fails when `end` points outside the bounds of self.
-     */
-    fn mut_slice_to(self, end: uint) -> &'a mut [T];
 
-    /// Returns an iterator that allows modifying each value
-    fn mut_iter(self) -> MutItems<'a, T>;
 
-    /// Returns a mutable pointer to the last item in the vector.
-    fn mut_last(self) -> Option<&'a mut T>;
+//
+// Common traits
+//
 
-    /// Returns an iterator over the mutable subslices of the vector
-    /// which are separated by elements that match `pred`.  The
-    /// matched element is not contained in the subslices.
-    fn mut_split(self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T>;
+/// Any vector that can be represented as a slice.
+pub trait Vector<T> {
+    /// Work with `self` as a slice.
+    fn as_slice<'a>(&'a self) -> &'a [T];
+}
 
-    /**
-     * Returns an iterator over `size` elements of the vector at a time.
-     * The chunks are mutable and do not overlap. If `size` does not divide the
-     * length of the vector, then the last chunk will not have length
-     * `size`.
-     *
-     * # Failure
-     *
-     * Fails if `size` is 0.
-     */
-    fn mut_chunks(self, chunk_size: uint) -> MutChunks<'a, T>;
+impl<'a,T> Vector<T> for &'a [T] {
+    #[inline(always)]
+    fn as_slice<'a>(&'a self) -> &'a [T] { *self }
+}
 
-    /**
-     * Returns a mutable reference to the first element in this slice
-     * and adjusts the slice in place so that it no longer contains
-     * that element. O(1).
-     *
-     * Equivalent to:
-     *
-     * ```ignore
-     *     if self.len() == 0 { return None; }
-     *     let head = &mut self[0];
-     *     *self = self.mut_slice_from(1);
-     *     Some(head)
-     * ```
-     *
-     * Returns `None` if slice is empty
-     */
-    fn mut_shift_ref(&mut self) -> Option<&'a mut T>;
+impl<'a, T> Collection for &'a [T] {
+    /// Returns the length of a vector
+    #[inline]
+    fn len(&self) -> uint {
+        self.repr().len
+    }
+}
 
-    /**
-     * Returns a mutable reference to the last element in this slice
-     * and adjusts the slice in place so that it no longer contains
-     * that element. O(1).
-     *
-     * Equivalent to:
-     *
-     * ```ignore
-     *     if self.len() == 0 { return None; }
-     *     let tail = &mut self[self.len() - 1];
-     *     *self = self.mut_slice_to(self.len() - 1);
-     *     Some(tail)
-     * ```
-     *
-     * Returns `None` if slice is empty.
-     */
-    fn mut_pop_ref(&mut self) -> Option<&'a mut T>;
+impl<'a, T> Default for &'a [T] {
+    fn default() -> &'a [T] { &[] }
+}
 
-    /// Swaps two elements in a vector.
-    ///
-    /// Fails if `a` or `b` are out of bounds.
-    ///
-    /// # Arguments
-    ///
-    /// * a - The index of the first element
-    /// * b - The index of the second element
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let mut v = ["a", "b", "c", "d"];
-    /// v.swap(1, 3);
-    /// assert!(v == ["a", "d", "c", "b"]);
-    /// ```
-    fn swap(self, a: uint, b: uint);
 
 
-    /// Divides one `&mut` into two at an index.
-    ///
-    /// The first will contain all indices from `[0, mid)` (excluding
-    /// the index `mid` itself) and the second will contain all
-    /// indices from `[mid, len)` (excluding the index `len` itself).
-    ///
-    /// Fails if `mid > len`.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let mut v = [1i, 2, 3, 4, 5, 6];
-    ///
-    /// // scoped to restrict the lifetime of the borrows
-    /// {
-    ///    let (left, right) = v.mut_split_at(0);
-    ///    assert!(left == &mut []);
-    ///    assert!(right == &mut [1i, 2, 3, 4, 5, 6]);
-    /// }
-    ///
-    /// {
-    ///     let (left, right) = v.mut_split_at(2);
-    ///     assert!(left == &mut [1i, 2]);
-    ///     assert!(right == &mut [3i, 4, 5, 6]);
-    /// }
-    ///
-    /// {
-    ///     let (left, right) = v.mut_split_at(6);
-    ///     assert!(left == &mut [1i, 2, 3, 4, 5, 6]);
-    ///     assert!(right == &mut []);
-    /// }
-    /// ```
-    fn mut_split_at(self, mid: uint) -> (&'a mut [T], &'a mut [T]);
 
-    /// Reverse the order of elements in a vector, in place.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let mut v = [1i, 2, 3];
-    /// v.reverse();
-    /// assert!(v == [3i, 2, 1]);
-    /// ```
-    fn reverse(self);
+//
+// Iterators
+//
 
-    /// Returns an unsafe mutable pointer to the element in index
-    unsafe fn unsafe_mut_ref(self, index: uint) -> &'a mut T;
+// The shared definition of the `Item` and `MutItems` iterators
+macro_rules! iterator {
+    (struct $name:ident -> $ptr:ty, $elem:ty) => {
+        impl<'a, T> Iterator<$elem> for $name<'a, T> {
+            #[inline]
+            fn next(&mut self) -> Option<$elem> {
+                // could be implemented with slices, but this avoids bounds checks
+                unsafe {
+                    if self.ptr == self.end {
+                        None
+                    } else {
+                        let old = self.ptr;
+                        self.ptr = if mem::size_of::<T>() == 0 {
+                            // purposefully don't use 'ptr.offset' because for
+                            // vectors with 0-size elements this would return the
+                            // same pointer.
+                            transmute(self.ptr as uint + 1)
+                        } else {
+                            self.ptr.offset(1)
+                        };
 
-    /// Return an unsafe mutable pointer to the vector's buffer.
-    ///
-    /// The caller must ensure that the vector outlives the pointer this
-    /// function returns, or else it will end up pointing to garbage.
-    ///
-    /// Modifying the vector may cause its buffer to be reallocated, which
-    /// would also make any pointers to it invalid.
+                        Some(transmute(old))
+                    }
+                }
+            }
+
+            #[inline]
+            fn size_hint(&self) -> (uint, Option<uint>) {
+                let diff = (self.end as uint) - (self.ptr as uint);
+                let size = mem::size_of::<T>();
+                let exact = diff / (if size == 0 {1} else {size});
+                (exact, Some(exact))
+            }
+        }
+
+        impl<'a, T> DoubleEndedIterator<$elem> for $name<'a, T> {
+            #[inline]
+            fn next_back(&mut self) -> Option<$elem> {
+                // could be implemented with slices, but this avoids bounds checks
+                unsafe {
+                    if self.end == self.ptr {
+                        None
+                    } else {
+                        self.end = if mem::size_of::<T>() == 0 {
+                            // See above for why 'ptr.offset' isn't used
+                            transmute(self.end as uint - 1)
+                        } else {
+                            self.end.offset(-1)
+                        };
+                        Some(transmute(self.end))
+                    }
+                }
+            }
+        }
+    }
+}
+
+/// Immutable slice iterator
+pub struct Items<'a, T> {
+    ptr: *const T,
+    end: *const T,
+    marker: marker::ContravariantLifetime<'a>
+}
+
+iterator!{struct Items -> *const T, &'a T}
+
+impl<'a, T> ExactSize<&'a T> for Items<'a, T> {}
+
+impl<'a, T> Clone for Items<'a, T> {
+    fn clone(&self) -> Items<'a, T> { *self }
+}
+
+impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
     #[inline]
-    fn as_mut_ptr(self) -> *mut T;
+    fn indexable(&self) -> uint {
+        let (exact, _) = self.size_hint();
+        exact
+    }
 
-    /// Unsafely sets the element in index to the value.
-    ///
-    /// This performs no bounds checks, and it is undefined behaviour
-    /// if `index` is larger than the length of `self`. However, it
-    /// does run the destructor at `index`. It is equivalent to
-    /// `self[index] = val`.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let mut v = ["foo".to_string(), "bar".to_string(), "baz".to_string()];
-    ///
-    /// unsafe {
-    ///     // `"baz".to_string()` is deallocated.
-    ///     v.unsafe_set(2, "qux".to_string());
-    ///
-    ///     // Out of bounds: could cause a crash, or overwriting
-    ///     // other data, or something else.
-    ///     // v.unsafe_set(10, "oops".to_string());
-    /// }
-    /// ```
-    unsafe fn unsafe_set(self, index: uint, val: T);
+    #[inline]
+    fn idx(&mut self, index: uint) -> Option<&'a T> {
+        unsafe {
+            if index < self.indexable() {
+                transmute(self.ptr.offset(index as int))
+            } else {
+                None
+            }
+        }
+    }
+}
 
-    /// Unchecked vector index assignment.  Does not drop the
-    /// old value and hence is only suitable when the vector
-    /// is newly allocated.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let mut v = ["foo".to_string(), "bar".to_string()];
-    ///
-    /// // memory leak! `"bar".to_string()` is not deallocated.
-    /// unsafe { v.init_elem(1, "baz".to_string()); }
-    /// ```
-    unsafe fn init_elem(self, i: uint, val: T);
+/// Mutable slice iterator
+pub struct MutItems<'a, T> {
+    ptr: *mut T,
+    end: *mut T,
+    marker: marker::ContravariantLifetime<'a>,
+    marker2: marker::NoCopy
+}
 
-    /// Copies raw bytes from `src` to `self`.
-    ///
-    /// This does not run destructors on the overwritten elements, and
-    /// ignores move semantics. `self` and `src` must not
-    /// overlap. Fails if `self` is shorter than `src`.
-    unsafe fn copy_memory(self, src: &[T]);
+iterator!{struct MutItems -> *mut T, &'a mut T}
+
+impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {}
+
+/// An iterator over the slices of a vector separated by elements that
+/// match a predicate function.
+pub struct Splits<'a, T> {
+    v: &'a [T],
+    pred: |t: &T|: 'a -> bool,
+    finished: bool
 }
 
-impl<'a,T> MutableVector<'a, T> for &'a mut [T] {
+impl<'a, T> Iterator<&'a [T]> for Splits<'a, T> {
     #[inline]
-    fn get_mut(self, index: uint) -> Option<&'a mut T> {
-        if index < self.len() { Some(&mut self[index]) } else { None }
+    fn next(&mut self) -> Option<&'a [T]> {
+        if self.finished { return None; }
+
+        match self.v.iter().position(|x| (self.pred)(x)) {
+            None => {
+                self.finished = true;
+                Some(self.v)
+            }
+            Some(idx) => {
+                let ret = Some(self.v.slice(0, idx));
+                self.v = self.v.slice(idx + 1, self.v.len());
+                ret
+            }
+        }
     }
 
     #[inline]
-    fn as_mut_slice(self) -> &'a mut [T] { self }
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        if self.finished {
+            (0, Some(0))
+        } else {
+            (1, Some(self.v.len() + 1))
+        }
+    }
+}
 
-    fn mut_slice(self, start: uint, end: uint) -> &'a mut [T] {
-        assert!(start <= end);
-        assert!(end <= self.len());
-        unsafe {
-            transmute(Slice {
-                    data: self.as_mut_ptr().offset(start as int) as *const T,
-                    len: (end - start)
-                })
+impl<'a, T> DoubleEndedIterator<&'a [T]> for Splits<'a, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a [T]> {
+        if self.finished { return None; }
+
+        match self.v.iter().rposition(|x| (self.pred)(x)) {
+            None => {
+                self.finished = true;
+                Some(self.v)
+            }
+            Some(idx) => {
+                let ret = Some(self.v.slice(idx + 1, self.v.len()));
+                self.v = self.v.slice(0, idx);
+                ret
+            }
+        }
+    }
+}
+
+/// An iterator over the subslices of the vector which are separated
+/// by elements that match `pred`.
+pub struct MutSplits<'a, T> {
+    v: &'a mut [T],
+    pred: |t: &T|: 'a -> bool,
+    finished: bool
+}
+
+impl<'a, T> Iterator<&'a mut [T]> for MutSplits<'a, T> {
+    #[inline]
+    fn next(&mut self) -> Option<&'a mut [T]> {
+        if self.finished { return None; }
+
+        let pred = &mut self.pred;
+        match self.v.iter().position(|x| (*pred)(x)) {
+            None => {
+                self.finished = true;
+                let tmp = mem::replace(&mut self.v, &mut []);
+                let len = tmp.len();
+                let (head, tail) = tmp.mut_split_at(len);
+                self.v = tail;
+                Some(head)
+            }
+            Some(idx) => {
+                let tmp = mem::replace(&mut self.v, &mut []);
+                let (head, tail) = tmp.mut_split_at(idx);
+                self.v = tail.mut_slice_from(1);
+                Some(head)
+            }
         }
     }
 
     #[inline]
-    fn mut_slice_from(self, start: uint) -> &'a mut [T] {
-        let len = self.len();
-        self.mut_slice(start, len)
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        if self.finished {
+            (0, Some(0))
+        } else {
+            // if the predicate doesn't match anything, we yield one slice
+            // if it matches every element, we yield len+1 empty slices.
+            (1, Some(self.v.len() + 1))
+        }
     }
+}
 
+impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T> {
     #[inline]
-    fn mut_slice_to(self, end: uint) -> &'a mut [T] {
-        self.mut_slice(0, end)
-    }
+    fn next_back(&mut self) -> Option<&'a mut [T]> {
+        if self.finished { return None; }
 
-    #[inline]
-    fn mut_split_at(self, mid: uint) -> (&'a mut [T], &'a mut [T]) {
-        unsafe {
-            let len = self.len();
-            let self2: &'a mut [T] = mem::transmute_copy(&self);
-            (self.mut_slice(0, mid), self2.mut_slice(mid, len))
+        let pred = &mut self.pred;
+        match self.v.iter().rposition(|x| (*pred)(x)) {
+            None => {
+                self.finished = true;
+                let tmp = mem::replace(&mut self.v, &mut []);
+                Some(tmp)
+            }
+            Some(idx) => {
+                let tmp = mem::replace(&mut self.v, &mut []);
+                let (head, tail) = tmp.mut_split_at(idx);
+                self.v = head;
+                Some(tail.mut_slice_from(1))
+            }
         }
     }
+}
+
+/// An iterator over the slices of a vector separated by elements that
+/// match a predicate function, splitting at most a fixed number of times.
+pub struct SplitsN<'a, T> {
+    iter: Splits<'a, T>,
+    count: uint,
+    invert: bool
+}
 
+impl<'a, T> Iterator<&'a [T]> for SplitsN<'a, T> {
     #[inline]
-    fn mut_iter(self) -> MutItems<'a, T> {
-        unsafe {
-            let p = self.as_mut_ptr();
-            if mem::size_of::<T>() == 0 {
-                MutItems{ptr: p,
-                         end: (p as uint + self.len()) as *mut T,
-                         marker: marker::ContravariantLifetime::<'a>,
-                         marker2: marker::NoCopy}
+    fn next(&mut self) -> Option<&'a [T]> {
+        if self.count == 0 {
+            if self.iter.finished {
+                None
             } else {
-                MutItems{ptr: p,
-                         end: p.offset(self.len() as int),
-                         marker: marker::ContravariantLifetime::<'a>,
-                         marker2: marker::NoCopy}
+                self.iter.finished = true;
+                Some(self.iter.v)
             }
+        } else {
+            self.count -= 1;
+            if self.invert { self.iter.next_back() } else { self.iter.next() }
         }
     }
 
     #[inline]
-    fn mut_last(self) -> Option<&'a mut T> {
-        let len = self.len();
-        if len == 0 { return None; }
-        Some(&mut self[len - 1])
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        if self.iter.finished {
+            (0, Some(0))
+        } else {
+            (1, Some(cmp::min(self.count, self.iter.v.len()) + 1))
+        }
     }
+}
 
-    #[inline]
-    fn mut_split(self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T> {
-        MutSplits { v: self, pred: pred, finished: false }
-    }
+/// An iterator over the (overlapping) slices of length `size` within
+/// a vector.
+#[deriving(Clone)]
+pub struct Windows<'a, T> {
+    v: &'a [T],
+    size: uint
+}
 
+impl<'a, T> Iterator<&'a [T]> for Windows<'a, T> {
     #[inline]
-    fn mut_chunks(self, chunk_size: uint) -> MutChunks<'a, T> {
-        assert!(chunk_size > 0);
-        MutChunks { v: self, chunk_size: chunk_size }
+    fn next(&mut self) -> Option<&'a [T]> {
+        if self.size > self.v.len() {
+            None
+        } else {
+            let ret = Some(self.v.slice(0, self.size));
+            self.v = self.v.slice(1, self.v.len());
+            ret
+        }
     }
 
-    fn mut_shift_ref(&mut self) -> Option<&'a mut T> {
-        unsafe {
-            let s: &mut Slice<T> = transmute(self);
-            match raw::shift_ptr(s) {
-                // FIXME #13933: this `&` -> `&mut` cast is a little
-                // dubious
-                Some(p) => Some(&mut *(p as *mut _)),
-                None => None,
-            }
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        if self.size > self.v.len() {
+            (0, Some(0))
+        } else {
+            let x = self.v.len() - self.size;
+            (x.saturating_add(1), x.checked_add(&1u))
         }
     }
+}
 
-    fn mut_pop_ref(&mut self) -> Option<&'a mut T> {
-        unsafe {
-            let s: &mut Slice<T> = transmute(self);
-            match raw::pop_ptr(s) {
-                // FIXME #13933: this `&` -> `&mut` cast is a little
-                // dubious
-                Some(p) => Some(&mut *(p as *mut _)),
-                None => None,
-            }
+/// An iterator over a vector in (non-overlapping) chunks (`size`
+/// elements at a time).
+///
+/// When the vector len is not evenly divided by the chunk size,
+/// the last slice of the iteration will be the remainder.
+#[deriving(Clone)]
+pub struct Chunks<'a, T> {
+    v: &'a [T],
+    size: uint
+}
+
+impl<'a, T> Iterator<&'a [T]> for Chunks<'a, T> {
+    #[inline]
+    fn next(&mut self) -> Option<&'a [T]> {
+        if self.v.len() == 0 {
+            None
+        } else {
+            let chunksz = cmp::min(self.v.len(), self.size);
+            let (fst, snd) = (self.v.slice_to(chunksz),
+                              self.v.slice_from(chunksz));
+            self.v = snd;
+            Some(fst)
         }
     }
 
-    fn swap(self, a: uint, b: uint) {
-        unsafe {
-            // Can't take two mutable loans from one vector, so instead just cast
-            // them to their raw pointers to do the swap
-            let pa: *mut T = &mut self[a];
-            let pb: *mut T = &mut self[b];
-            ptr::swap(pa, pb);
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        if self.v.len() == 0 {
+            (0, Some(0))
+        } else {
+            let (n, rem) = div_rem(self.v.len(), self.size);
+            let n = if rem > 0 { n+1 } else { n };
+            (n, Some(n))
         }
     }
+}
 
-    fn reverse(self) {
-        let mut i: uint = 0;
-        let ln = self.len();
-        while i < ln / 2 {
-            self.swap(i, ln - i - 1);
-            i += 1;
+impl<'a, T> DoubleEndedIterator<&'a [T]> for Chunks<'a, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a [T]> {
+        if self.v.len() == 0 {
+            None
+        } else {
+            let remainder = self.v.len() % self.size;
+            let chunksz = if remainder != 0 { remainder } else { self.size };
+            let (fst, snd) = (self.v.slice_to(self.v.len() - chunksz),
+                              self.v.slice_from(self.v.len() - chunksz));
+            self.v = fst;
+            Some(snd)
         }
     }
+}
 
+impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> {
     #[inline]
-    unsafe fn unsafe_mut_ref(self, index: uint) -> &'a mut T {
-        transmute((self.repr().data as *mut T).offset(index as int))
+    fn indexable(&self) -> uint {
+        self.v.len()/self.size + if self.v.len() % self.size != 0 { 1 } else { 0 }
     }
 
     #[inline]
-    fn as_mut_ptr(self) -> *mut T {
-        self.repr().data as *mut T
+    fn idx(&mut self, index: uint) -> Option<&'a [T]> {
+        if index < self.indexable() {
+            let lo = index * self.size;
+            let mut hi = lo + self.size;
+            if hi < lo || hi > self.v.len() { hi = self.v.len(); }
+
+            Some(self.v.slice(lo, hi))
+        } else {
+            None
+        }
     }
+}
+
+/// An iterator over a vector in (non-overlapping) mutable chunks (`size`  elements at a time). When
+/// the vector len is not evenly divided by the chunk size, the last slice of the iteration will be
+/// the remainder.
+pub struct MutChunks<'a, T> {
+    v: &'a mut [T],
+    chunk_size: uint
+}
 
+impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> {
     #[inline]
-    unsafe fn unsafe_set(self, index: uint, val: T) {
-        *self.unsafe_mut_ref(index) = val;
+    fn next(&mut self) -> Option<&'a mut [T]> {
+        if self.v.len() == 0 {
+            None
+        } else {
+            let sz = cmp::min(self.v.len(), self.chunk_size);
+            let tmp = mem::replace(&mut self.v, &mut []);
+            let (head, tail) = tmp.mut_split_at(sz);
+            self.v = tail;
+            Some(head)
+        }
     }
 
     #[inline]
-    unsafe fn init_elem(self, i: uint, val: T) {
-        ptr::write(&mut (*self.as_mut_ptr().offset(i as int)), val);
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        if self.v.len() == 0 {
+            (0, Some(0))
+        } else {
+            let (n, rem) = div_rem(self.v.len(), self.chunk_size);
+            let n = if rem > 0 { n + 1 } else { n };
+            (n, Some(n))
+        }
     }
+}
 
+impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> {
     #[inline]
-    unsafe fn copy_memory(self, src: &[T]) {
-        let len_src = src.len();
-        assert!(self.len() >= len_src);
-        ptr::copy_nonoverlapping_memory(self.as_mut_ptr(), src.as_ptr(), len_src)
+    fn next_back(&mut self) -> Option<&'a mut [T]> {
+        if self.v.len() == 0 {
+            None
+        } else {
+            let remainder = self.v.len() % self.chunk_size;
+            let sz = if remainder != 0 { remainder } else { self.chunk_size };
+            let tmp = mem::replace(&mut self.v, &mut []);
+            let tmp_len = tmp.len();
+            let (head, tail) = tmp.mut_split_at(tmp_len - sz);
+            self.v = head;
+            Some(tail)
+        }
     }
 }
 
-/// Trait for &[T] where T is Cloneable
-pub trait MutableCloneableVector<T> {
-    /// Copies as many elements from `src` as it can into `self` (the
-    /// shorter of `self.len()` and `src.len()`). Returns the number
-    /// of elements copied.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// use std::slice::MutableCloneableVector;
-    ///
-    /// let mut dst = [0i, 0, 0];
-    /// let src = [1i, 2];
-    ///
-    /// assert!(dst.copy_from(src) == 2);
-    /// assert!(dst == [1, 2, 0]);
-    ///
-    /// let src2 = [3i, 4, 5, 6];
-    /// assert!(dst.copy_from(src2) == 3);
-    /// assert!(dst == [3i, 4, 5]);
-    /// ```
-    fn copy_from(self, &[T]) -> uint;
+
+
+
+//
+// Free functions
+//
+
+/**
+ * Converts a pointer to A into a slice of length 1 (without copying).
+ */
+pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
+    unsafe {
+        transmute(Slice { data: s, len: 1 })
+    }
 }
 
-impl<'a, T:Clone> MutableCloneableVector<T> for &'a mut [T] {
-    #[inline]
-    fn copy_from(self, src: &[T]) -> uint {
-        for (a, b) in self.mut_iter().zip(src.iter()) {
-            a.clone_from(b);
-        }
-        cmp::min(self.len(), src.len())
+/**
+ * Converts a pointer to A into a slice of length 1 (without copying).
+ */
+pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
+    unsafe {
+        let ptr: *const A = transmute(s);
+        transmute(Slice { data: ptr, len: 1 })
     }
 }
 
+
+
+
+//
+// Submodules
+//
+
 /// Unsafe operations
 pub mod raw {
     use mem::transmute;
@@ -1201,224 +1415,56 @@ pub fn copy_memory(dst: &mut [u8], src: &[u8]) {
     }
 }
 
-/// Immutable slice iterator
-pub struct Items<'a, T> {
-    ptr: *const T,
-    end: *const T,
-    marker: marker::ContravariantLifetime<'a>
-}
-
-/// Mutable slice iterator
-pub struct MutItems<'a, T> {
-    ptr: *mut T,
-    end: *mut T,
-    marker: marker::ContravariantLifetime<'a>,
-    marker2: marker::NoCopy
-}
-
-macro_rules! iterator {
-    (struct $name:ident -> $ptr:ty, $elem:ty) => {
-        impl<'a, T> Iterator<$elem> for $name<'a, T> {
-            #[inline]
-            fn next(&mut self) -> Option<$elem> {
-                // could be implemented with slices, but this avoids bounds checks
-                unsafe {
-                    if self.ptr == self.end {
-                        None
-                    } else {
-                        let old = self.ptr;
-                        self.ptr = if mem::size_of::<T>() == 0 {
-                            // purposefully don't use 'ptr.offset' because for
-                            // vectors with 0-size elements this would return the
-                            // same pointer.
-                            transmute(self.ptr as uint + 1)
-                        } else {
-                            self.ptr.offset(1)
-                        };
 
-                        Some(transmute(old))
-                    }
-                }
-            }
 
-            #[inline]
-            fn size_hint(&self) -> (uint, Option<uint>) {
-                let diff = (self.end as uint) - (self.ptr as uint);
-                let size = mem::size_of::<T>();
-                let exact = diff / (if size == 0 {1} else {size});
-                (exact, Some(exact))
-            }
-        }
 
-        impl<'a, T> DoubleEndedIterator<$elem> for $name<'a, T> {
-            #[inline]
-            fn next_back(&mut self) -> Option<$elem> {
-                // could be implemented with slices, but this avoids bounds checks
-                unsafe {
-                    if self.end == self.ptr {
-                        None
-                    } else {
-                        self.end = if mem::size_of::<T>() == 0 {
-                            // See above for why 'ptr.offset' isn't used
-                            transmute(self.end as uint - 1)
-                        } else {
-                            self.end.offset(-1)
-                        };
-                        Some(transmute(self.end))
-                    }
-                }
-            }
-        }
-    }
-}
+//
+// Boilerplate traits
+//
 
-impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
-    #[inline]
-    fn indexable(&self) -> uint {
-        let (exact, _) = self.size_hint();
-        exact
+impl<'a,T:PartialEq> PartialEq for &'a [T] {
+    fn eq(&self, other: & &'a [T]) -> bool {
+        self.len() == other.len() &&
+            order::eq(self.iter(), other.iter())
     }
-
-    #[inline]
-    fn idx(&mut self, index: uint) -> Option<&'a T> {
-        unsafe {
-            if index < self.indexable() {
-                transmute(self.ptr.offset(index as int))
-            } else {
-                None
-            }
-        }
+    fn ne(&self, other: & &'a [T]) -> bool {
+        self.len() != other.len() ||
+            order::ne(self.iter(), other.iter())
     }
 }
 
-iterator!{struct Items -> *const T, &'a T}
-
-impl<'a, T> ExactSize<&'a T> for Items<'a, T> {}
-impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {}
-
-impl<'a, T> Clone for Items<'a, T> {
-    fn clone(&self) -> Items<'a, T> { *self }
-}
-
-iterator!{struct MutItems -> *mut T, &'a mut T}
-
-/// An iterator over the subslices of the vector which are separated
-/// by elements that match `pred`.
-pub struct MutSplits<'a, T> {
-    v: &'a mut [T],
-    pred: |t: &T|: 'a -> bool,
-    finished: bool
-}
+impl<'a,T:Eq> Eq for &'a [T] {}
 
-impl<'a, T> Iterator<&'a mut [T]> for MutSplits<'a, T> {
+impl<'a,T:PartialEq, V: Vector<T>> Equiv<V> for &'a [T] {
     #[inline]
-    fn next(&mut self) -> Option<&'a mut [T]> {
-        if self.finished { return None; }
+    fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
+}
 
-        let pred = &mut self.pred;
-        match self.v.iter().position(|x| (*pred)(x)) {
-            None => {
-                self.finished = true;
-                let tmp = mem::replace(&mut self.v, &mut []);
-                let len = tmp.len();
-                let (head, tail) = tmp.mut_split_at(len);
-                self.v = tail;
-                Some(head)
-            }
-            Some(idx) => {
-                let tmp = mem::replace(&mut self.v, &mut []);
-                let (head, tail) = tmp.mut_split_at(idx);
-                self.v = tail.mut_slice_from(1);
-                Some(head)
-            }
-        }
+impl<'a,T:Ord> Ord for &'a [T] {
+    fn cmp(&self, other: & &'a [T]) -> Ordering {
+        order::cmp(self.iter(), other.iter())
     }
+}
 
+impl<'a, T: PartialOrd> PartialOrd for &'a [T] {
     #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        if self.finished {
-            (0, Some(0))
-        } else {
-            // if the predicate doesn't match anything, we yield one slice
-            // if it matches every element, we yield len+1 empty slices.
-            (1, Some(self.v.len() + 1))
-        }
+    fn partial_cmp(&self, other: &&'a [T]) -> Option<Ordering> {
+        order::partial_cmp(self.iter(), other.iter())
     }
-}
-
-impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T> {
     #[inline]
-    fn next_back(&mut self) -> Option<&'a mut [T]> {
-        if self.finished { return None; }
-
-        let pred = &mut self.pred;
-        match self.v.iter().rposition(|x| (*pred)(x)) {
-            None => {
-                self.finished = true;
-                let tmp = mem::replace(&mut self.v, &mut []);
-                Some(tmp)
-            }
-            Some(idx) => {
-                let tmp = mem::replace(&mut self.v, &mut []);
-                let (head, tail) = tmp.mut_split_at(idx);
-                self.v = head;
-                Some(tail.mut_slice_from(1))
-            }
-        }
+    fn lt(&self, other: & &'a [T]) -> bool {
+        order::lt(self.iter(), other.iter())
     }
-}
-
-/// An iterator over a vector in (non-overlapping) mutable chunks (`size`  elements at a time). When
-/// the vector len is not evenly divided by the chunk size, the last slice of the iteration will be
-/// the remainder.
-pub struct MutChunks<'a, T> {
-    v: &'a mut [T],
-    chunk_size: uint
-}
-
-impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> {
     #[inline]
-    fn next(&mut self) -> Option<&'a mut [T]> {
-        if self.v.len() == 0 {
-            None
-        } else {
-            let sz = cmp::min(self.v.len(), self.chunk_size);
-            let tmp = mem::replace(&mut self.v, &mut []);
-            let (head, tail) = tmp.mut_split_at(sz);
-            self.v = tail;
-            Some(head)
-        }
+    fn le(&self, other: & &'a [T]) -> bool {
+        order::le(self.iter(), other.iter())
     }
-
     #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        if self.v.len() == 0 {
-            (0, Some(0))
-        } else {
-            let (n, rem) = div_rem(self.v.len(), self.chunk_size);
-            let n = if rem > 0 { n + 1 } else { n };
-            (n, Some(n))
-        }
+    fn ge(&self, other: & &'a [T]) -> bool {
+        order::ge(self.iter(), other.iter())
     }
-}
-
-impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> {
     #[inline]
-    fn next_back(&mut self) -> Option<&'a mut [T]> {
-        if self.v.len() == 0 {
-            None
-        } else {
-            let remainder = self.v.len() % self.chunk_size;
-            let sz = if remainder != 0 { remainder } else { self.chunk_size };
-            let tmp = mem::replace(&mut self.v, &mut []);
-            let tmp_len = tmp.len();
-            let (head, tail) = tmp.mut_split_at(tmp_len - sz);
-            self.v = head;
-            Some(tail)
-        }
+    fn gt(&self, other: & &'a [T]) -> bool {
+        order::gt(self.iter(), other.iter())
     }
 }
-
-impl<'a, T> Default for &'a [T] {
-    fn default() -> &'a [T] { &[] }
-}
index b562d48f49d32ce7eb93b9a3ce010f962b8c3a0d..30296cb318617af1fdc0a544374596a44e5a37c8 100644 (file)
@@ -30,7 +30,7 @@
 use middle::trans::adt; // for `adt::is_ffi_safe`
 use middle::typeck::astconv::ast_ty_to_ty;
 use middle::typeck::infer;
-use middle::{typeck, ty, def, pat_util};
+use middle::{typeck, ty, def, pat_util, stability};
 use util::ppaux::{ty_to_str};
 use util::nodemap::NodeSet;
 use lint::{Context, LintPass, LintArray};
@@ -1426,11 +1426,7 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
                     Some(method) => {
                         match method.origin {
                             typeck::MethodStatic(def_id) => {
-                                // If this implements a trait method, get def_id
-                                // of the method inside trait definition.
-                                // Otherwise, use the current def_id (which refers
-                                // to the method inside impl).
-                                ty::trait_method_of_method(cx.tcx, def_id).unwrap_or(def_id)
+                                def_id
                             }
                             typeck::MethodParam(typeck::MethodParam {
                                 trait_id: trait_id,
@@ -1454,8 +1450,7 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
         // check anything for crate-local usage.
         if ast_util::is_local(id) { return }
 
-        let stability = cx.tcx.stability.borrow_mut().lookup(&cx.tcx.sess.cstore, id);
-
+        let stability = stability::lookup(cx.tcx, id);
         let (lint, label) = match stability {
             // no stability attributes == Unstable
             None => (UNSTABLE, "unmarked"),
index c5789e4442a9d20e955af7b784dab36418718019..96284f8de261a78254f0faa3ff837c660049cf2b 100644 (file)
@@ -24,6 +24,7 @@
 use middle::astencode;
 use middle::ty;
 use middle::typeck;
+use middle::stability;
 use middle;
 use util::nodemap::{NodeMap, NodeSet};
 
@@ -328,7 +329,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
         encode_visibility(ebml_w, variant.node.vis);
         encode_attributes(ebml_w, variant.node.attrs.as_slice());
 
-        let stab = ecx.tcx.stability.borrow().lookup_local(variant.node.id);
+        let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
         encode_stability(ebml_w, stab);
 
         match variant.node.kind {
@@ -592,7 +593,9 @@ fn encode_info_for_mod(ecx: &EncodeContext,
 
     encode_path(ebml_w, path.clone());
     encode_visibility(ebml_w, vis);
-    encode_stability(ebml_w, ecx.tcx.stability.borrow().lookup_local(id));
+
+    let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
+    encode_stability(ebml_w, stab);
 
     // Encode the reexports of this module, if this module is public.
     if vis == Public {
@@ -722,7 +725,8 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
         encode_symbol(ecx, ebml_w, ctor_id);
     }
 
-    encode_stability(ebml_w, ecx.tcx.stability.borrow().lookup_local(ctor_id));
+    let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
+    encode_stability(ebml_w, stab);
 
     // indicate that this is a tuple struct ctor, because downstream users will normally want
     // the tuple struct definition, but without this there is no way for them to tell that
@@ -768,7 +772,7 @@ fn encode_info_for_method(ecx: &EncodeContext,
     encode_method_ty_fields(ecx, ebml_w, m);
     encode_parent_item(ebml_w, local_def(parent_id));
 
-    let stab = ecx.tcx.stability.borrow().lookup_local(m.def_id.node);
+    let stab = stability::lookup(ecx.tcx, m.def_id);
     encode_stability(ebml_w, stab);
 
     // The type for methods gets encoded twice, which is unfortunate.
@@ -915,10 +919,10 @@ fn add_to_index(item: &Item, ebml_w: &Encoder,
     }
 
     debug!("encoding info for item at {}",
-           ecx.tcx.sess.codemap().span_to_str(item.span));
+           tcx.sess.codemap().span_to_str(item.span));
 
     let def_id = local_def(item.id);
-    let stab = tcx.stability.borrow().lookup_local(item.id);
+    let stab = stability::lookup(tcx, ast_util::local_def(item.id));
 
     match item.node {
       ItemStatic(_, m, _) => {
@@ -1206,7 +1210,7 @@ fn add_to_index(item: &Item, ebml_w: &Encoder,
             encode_method_ty_fields(ecx, ebml_w, &*method_ty);
             encode_parent_item(ebml_w, def_id);
 
-            let stab = tcx.stability.borrow().lookup_local(method_def_id.node);
+            let stab = stability::lookup(tcx, method_def_id);
             encode_stability(ebml_w, stab);
 
             let elem = ast_map::PathName(method_ty.ident.name);
index fc76648ec5524c411768c2a1314a2d06809fec39..ac17bd07503521212b46b40f71055095d86649e3 100644 (file)
@@ -20,7 +20,8 @@
 use syntax::ast_util::is_local;
 use syntax::attr::Stability;
 use syntax::visit::{FnKind, FkMethod, Visitor};
-use metadata::{cstore, csearch};
+use middle::ty;
+use metadata::csearch;
 
 /// A stability index, giving the stability level for items and methods.
 pub struct Index {
@@ -105,21 +106,24 @@ pub fn build(krate: &Crate) -> Index {
                           attr::find_stability(krate.attrs.as_slice()));
         annotator.index
     }
+}
 
-    /// Lookup the stability for a node, loading external crate
-    /// metadata as necessary.
-    pub fn lookup(&mut self, cstore: &cstore::CStore, id: DefId) -> Option<Stability> {
-        if is_local(id) {
-            self.lookup_local(id.node)
-        } else {
-            let stab = csearch::get_stability(cstore, id);
-            self.extern_cache.insert(id, stab.clone());
+/// Lookup the stability for a node, loading external crate
+/// metadata as necessary.
+pub fn lookup(tcx: &ty::ctxt,  id: DefId) -> Option<Stability> {
+    // is this definition the implementation of a trait method?
+    match ty::trait_method_of_method(tcx, id) {
+        Some(trait_method_id) if trait_method_id != id => {
+            lookup(tcx, trait_method_id)
+        }
+        _ if is_local(id) => {
+            tcx.stability.borrow().local.find_copy(&id.node)
+        }
+        _ => {
+            let stab = csearch::get_stability(&tcx.sess.cstore, id);
+            let mut index = tcx.stability.borrow_mut();
+            (*index).extern_cache.insert(id, stab.clone());
             stab
         }
     }
-
-    /// Lookup the stability for a local node without loading any external crates
-    pub fn lookup_local(&self, id: NodeId) -> Option<Stability> {
-        self.local.find_copy(&id)
-    }
 }
index d243c61ddaff8ba3d91bdab8fb135e9888352d12..2d498e7f302d3fca3330b0182ea547608eac6c68 100644 (file)
@@ -18,6 +18,7 @@
 use rustc::metadata::decoder;
 use rustc::middle::def;
 use rustc::middle::ty;
+use rustc::middle::stability;
 
 use core;
 use doctree;
@@ -102,6 +103,7 @@ fn try_inline_def(cx: &core::DocContext,
         attrs: load_attrs(tcx, did),
         inner: inner,
         visibility: Some(ast::Public),
+        stability: stability::lookup(tcx, did).clean(),
         def_id: did,
     });
     Some(ret)
@@ -317,6 +319,7 @@ fn build_impl(cx: &core::DocContext,
         name: None,
         attrs: attrs,
         visibility: Some(ast::Inherited),
+        stability: stability::lookup(tcx, did).clean(),
         def_id: did,
     })
 }
index d7bbb439dbb7788f175130fbf9f8a1db2ae771a3..87151708812e54a5f106291d5a04fd851bf6a0dc 100644 (file)
@@ -29,6 +29,7 @@
 use rustc::middle::subst;
 use rustc::middle::subst::VecPerParamSpace;
 use rustc::middle::ty;
+use rustc::middle::stability;
 
 use std::rc::Rc;
 use std::u32;
 
 mod inline;
 
+// load the current DocContext from TLD
+fn get_cx() -> Gc<core::DocContext> {
+    *super::ctxtkey.get().unwrap()
+}
+
+// extract the stability index for a node from TLD, if possible
+fn get_stability(def_id: ast::DefId) -> Option<Stability> {
+    get_cx().tcx_opt().and_then(|tcx| stability::lookup(tcx, def_id))
+            .map(|stab| stab.clean())
+}
+
 pub trait Clean<T> {
     fn clean(&self) -> T;
 }
@@ -97,7 +109,7 @@ pub struct Crate {
 
 impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
     fn clean(&self) -> Crate {
-        let cx = super::ctxtkey.get().unwrap();
+        let cx = get_cx();
 
         let mut externs = Vec::new();
         cx.sess().cstore.iter_crate_data(|n, meta| {
@@ -158,6 +170,7 @@ fn clean(&self) -> Crate {
                     name: Some(prim.to_url_str().to_string()),
                     attrs: Vec::new(),
                     visibility: None,
+                    stability: None,
                     def_id: ast_util::local_def(prim.to_node_id()),
                     inner: PrimitiveItem(prim),
                 };
@@ -193,25 +206,18 @@ pub struct ExternalCrate {
 impl Clean<ExternalCrate> for cstore::crate_metadata {
     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(def::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(..) => {}
-        }
+        get_cx().tcx_opt().map(|tcx| {
+            csearch::each_top_level_item_of_crate(&tcx.sess.cstore,
+                                                  self.cnum,
+                                                  |def, _, _| {
+                let did = match def {
+                    decoder::DlDef(def::DefMod(did)) => did,
+                    _ => return
+                };
+                let attrs = inline::load_attrs(tcx, did);
+                Primitive::find(attrs.as_slice()).map(|prim| primitives.push(prim));
+            })
+        });
         ExternalCrate {
             name: self.name.to_string(),
             attrs: decoder::get_crate_attributes(self.data()).clean(),
@@ -233,6 +239,7 @@ pub struct Item {
     pub inner: ItemEnum,
     pub visibility: Option<Visibility>,
     pub def_id: ast::DefId,
+    pub stability: Option<Stability>,
 }
 
 impl Item {
@@ -380,6 +387,7 @@ fn clean(&self) -> Item {
             attrs: self.attrs.clean(),
             source: where.clean(),
             visibility: self.vis.clean(),
+            stability: self.stab.clean(),
             def_id: ast_util::local_def(self.id),
             inner: ModuleItem(Module {
                is_crate: self.is_crate,
@@ -465,9 +473,8 @@ fn clean(&self) -> TyParam {
 
 impl Clean<TyParam> for ty::TypeParameterDef {
     fn clean(&self) -> TyParam {
-        let cx = super::ctxtkey.get().unwrap();
-        cx.external_typarams.borrow_mut().get_mut_ref().insert(self.def_id,
-                                                               self.ident.clean());
+        get_cx().external_typarams.borrow_mut().get_mut_ref()
+                .insert(self.def_id, self.ident.clean());
         TyParam {
             name: self.ident.clean(),
             did: self.def_id,
@@ -515,7 +522,7 @@ fn external_path(name: &str, substs: &subst::Substs) -> Path {
 
 impl Clean<TyParamBound> for ty::BuiltinBound {
     fn clean(&self) -> TyParamBound {
-        let cx = super::ctxtkey.get().unwrap();
+        let cx = get_cx();
         let tcx = match cx.maybe_typed {
             core::Typed(ref tcx) => tcx,
             core::NotTyped(_) => return RegionBound,
@@ -550,7 +557,7 @@ fn clean(&self) -> TyParamBound {
 
 impl Clean<TyParamBound> for ty::TraitRef {
     fn clean(&self) -> TyParamBound {
-        let cx = super::ctxtkey.get().unwrap();
+        let cx = get_cx();
         let tcx = match cx.maybe_typed {
             core::Typed(ref tcx) => tcx,
             core::NotTyped(_) => return RegionBound,
@@ -709,8 +716,9 @@ fn clean(&self) -> Item {
             name: Some(self.ident.clean()),
             attrs: self.attrs.clean().move_iter().collect(),
             source: self.span.clean(),
-            def_id: ast_util::local_def(self.id.clone()),
+            def_id: ast_util::local_def(self.id),
             visibility: self.vis.clean(),
+            stability: get_stability(ast_util::local_def(self.id)),
             inner: MethodItem(Method {
                 generics: self.generics.clean(),
                 self_: self.explicit_self.node.clean(),
@@ -749,6 +757,7 @@ fn clean(&self) -> Item {
             source: self.span.clean(),
             def_id: ast_util::local_def(self.id),
             visibility: None,
+            stability: get_stability(ast_util::local_def(self.id)),
             inner: TyMethodItem(TyMethod {
                 fn_style: self.fn_style.clone(),
                 decl: decl,
@@ -792,6 +801,7 @@ fn clean(&self) -> Item {
             attrs: self.attrs.clean(),
             source: self.where.clean(),
             visibility: self.vis.clean(),
+            stability: self.stab.clean(),
             def_id: ast_util::local_def(self.id),
             inner: FunctionItem(Function {
                 decl: self.decl.clean(),
@@ -854,14 +864,10 @@ fn clean(&self) -> FnDecl {
 
 impl<'a> Clean<FnDecl> for (ast::DefId, &'a ty::FnSig) {
     fn clean(&self) -> FnDecl {
-        let cx = super::ctxtkey.get().unwrap();
-        let tcx = match cx.maybe_typed {
-            core::Typed(ref tcx) => tcx,
-            core::NotTyped(_) => unreachable!(),
-        };
+        let cx = get_cx();
         let (did, sig) = *self;
         let mut names = if did.node != 0 {
-            csearch::get_method_arg_names(&tcx.sess.cstore, did).move_iter()
+            csearch::get_method_arg_names(&cx.tcx().sess.cstore, did).move_iter()
         } else {
             Vec::new().move_iter()
         }.peekable();
@@ -932,6 +938,7 @@ fn clean(&self) -> Item {
             source: self.where.clean(),
             def_id: ast_util::local_def(self.id),
             visibility: self.vis.clean(),
+            stability: self.stab.clean(),
             inner: TraitItem(Trait {
                 methods: self.methods.clean(),
                 generics: self.generics.clean(),
@@ -985,11 +992,7 @@ fn clean(&self) -> TraitMethod {
 
 impl Clean<Item> for ty::Method {
     fn clean(&self) -> Item {
-        let cx = super::ctxtkey.get().unwrap();
-        let tcx = match cx.maybe_typed {
-            core::Typed(ref tcx) => tcx,
-            core::NotTyped(_) => unreachable!(),
-        };
+        let cx = get_cx();
         let (self_, sig) = match self.explicit_self {
             ast::SelfStatic => (ast::SelfStatic.clean(), self.fty.sig.clone()),
             s => {
@@ -1015,8 +1018,9 @@ fn clean(&self) -> Item {
         Item {
             name: Some(self.ident.clean()),
             visibility: Some(ast::Inherited),
+            stability: get_stability(self.def_id),
             def_id: self.def_id,
-            attrs: inline::load_attrs(tcx, self.def_id),
+            attrs: inline::load_attrs(cx.tcx(), self.def_id),
             source: Span::empty(),
             inner: TyMethodItem(TyMethod {
                 fn_style: self.fty.fn_style,
@@ -1261,12 +1265,7 @@ fn clean(&self) -> Type {
             ty::ty_struct(did, ref substs) |
             ty::ty_enum(did, ref substs) |
             ty::ty_trait(box ty::TyTrait { def_id: did, ref substs, .. }) => {
-                let cx = super::ctxtkey.get().unwrap();
-                let tcx = match cx.maybe_typed {
-                    core::Typed(ref tycx) => tycx,
-                    core::NotTyped(_) => unreachable!(),
-                };
-                let fqn = csearch::get_item_path(tcx, did);
+                let fqn = csearch::get_item_path(get_cx().tcx(), did);
                 let fqn: Vec<String> = fqn.move_iter().map(|i| {
                     i.to_str()
                 }).collect();
@@ -1277,8 +1276,8 @@ fn clean(&self) -> Type {
                 };
                 let path = external_path(fqn.last().unwrap().to_str().as_slice(),
                                          substs);
-                cx.external_paths.borrow_mut().get_mut_ref().insert(did,
-                                                                    (fqn, kind));
+                get_cx().external_paths.borrow_mut().get_mut_ref()
+                                       .insert(did, (fqn, kind));
                 ResolvedPath {
                     path: path,
                     typarams: None,
@@ -1318,6 +1317,7 @@ fn clean(&self) -> Item {
             attrs: self.node.attrs.clean().move_iter().collect(),
             source: self.span.clean(),
             visibility: Some(vis),
+            stability: get_stability(ast_util::local_def(self.node.id)),
             def_id: ast_util::local_def(self.node.id),
             inner: StructFieldItem(TypedStructField(self.node.ty.clean())),
         }
@@ -1332,17 +1332,14 @@ fn clean(&self) -> Item {
         } else {
             Some(self.name)
         };
-        let cx = super::ctxtkey.get().unwrap();
-        let tcx = match cx.maybe_typed {
-            core::Typed(ref tycx) => tycx,
-            core::NotTyped(_) => unreachable!(),
-        };
-        let ty = ty::lookup_item_type(tcx, self.id);
+        let cx = get_cx();
+        let ty = ty::lookup_item_type(cx.tcx(), self.id);
         Item {
             name: name.clean(),
-            attrs: inline::load_attrs(tcx, self.id),
+            attrs: inline::load_attrs(cx.tcx(), self.id),
             source: Span::empty(),
             visibility: Some(self.vis),
+            stability: get_stability(self.id),
             def_id: self.id,
             inner: StructFieldItem(TypedStructField(ty.ty.clean())),
         }
@@ -1373,6 +1370,7 @@ fn clean(&self) -> Item {
             source: self.where.clean(),
             def_id: ast_util::local_def(self.id),
             visibility: self.vis.clean(),
+            stability: self.stab.clean(),
             inner: StructItem(Struct {
                 struct_type: self.struct_type,
                 generics: self.generics.clean(),
@@ -1418,6 +1416,7 @@ fn clean(&self) -> Item {
             source: self.where.clean(),
             def_id: ast_util::local_def(self.id),
             visibility: self.vis.clean(),
+            stability: self.stab.clean(),
             inner: EnumItem(Enum {
                 variants: self.variants.clean(),
                 generics: self.generics.clean(),
@@ -1439,6 +1438,7 @@ fn clean(&self) -> Item {
             attrs: self.attrs.clean(),
             source: self.where.clean(),
             visibility: self.vis.clean(),
+            stability: self.stab.clean(),
             def_id: ast_util::local_def(self.id),
             inner: VariantItem(Variant {
                 kind: self.kind.clean(),
@@ -1450,11 +1450,7 @@ fn clean(&self) -> Item {
 impl Clean<Item> for ty::VariantInfo {
     fn clean(&self) -> Item {
         // use syntax::parse::token::special_idents::unnamed_field;
-        let cx = super::ctxtkey.get().unwrap();
-        let tcx = match cx.maybe_typed {
-            core::Typed(ref tycx) => tycx,
-            core::NotTyped(_) => fail!("tcx not present"),
-        };
+        let cx = get_cx();
         let kind = match self.arg_names.as_ref().map(|s| s.as_slice()) {
             None | Some([]) if self.args.len() == 0 => CLikeVariant,
             None | Some([]) => {
@@ -1470,6 +1466,7 @@ fn clean(&self) -> Item {
                             name: Some(name.clean()),
                             attrs: Vec::new(),
                             visibility: Some(ast::Public),
+                            stability: get_stability(self.id),
                             // FIXME: this is not accurate, we need an id for
                             //        the specific field but we're using the id
                             //        for the whole variant. Nothing currently
@@ -1485,11 +1482,12 @@ fn clean(&self) -> Item {
         };
         Item {
             name: Some(self.name.clean()),
-            attrs: inline::load_attrs(tcx, self.id),
+            attrs: inline::load_attrs(cx.tcx(), self.id),
             source: Span::empty(),
             visibility: Some(ast::Public),
             def_id: self.id,
             inner: VariantItem(Variant { kind: kind }),
+            stability: None,
         }
     }
 }
@@ -1626,6 +1624,7 @@ fn clean(&self) -> Item {
             source: self.where.clean(),
             def_id: ast_util::local_def(self.id.clone()),
             visibility: self.vis.clean(),
+            stability: self.stab.clean(),
             inner: TypedefItem(Typedef {
                 type_: self.ty.clean(),
                 generics: self.gen.clean(),
@@ -1675,6 +1674,7 @@ fn clean(&self) -> Item {
             source: self.where.clean(),
             def_id: ast_util::local_def(self.id),
             visibility: self.vis.clean(),
+            stability: self.stab.clean(),
             inner: StaticItem(Static {
                 type_: self.type_.clean(),
                 mutability: self.mutability.clean(),
@@ -1720,6 +1720,7 @@ fn clean(&self) -> Item {
             source: self.where.clean(),
             def_id: ast_util::local_def(self.id),
             visibility: self.vis.clean(),
+            stability: self.stab.clean(),
             inner: ImplItem(Impl {
                 generics: self.generics.clean(),
                 trait_: self.trait_.clean(),
@@ -1754,6 +1755,7 @@ fn clean(&self) -> Vec<Item> {
                 source: self.span.clean(),
                 def_id: ast_util::local_def(0),
                 visibility: self.vis.clean(),
+                stability: None,
                 inner: ViewItemItem(ViewItem { inner: node.clean() }),
             }
         };
@@ -1895,6 +1897,7 @@ fn clean(&self) -> Item {
             source: self.span.clean(),
             def_id: ast_util::local_def(self.id),
             visibility: self.vis.clean(),
+            stability: None,
             inner: inner,
         }
     }
@@ -1977,7 +1980,7 @@ fn name_from_pat(p: &ast::Pat) -> String {
 /// Given a Type, resolve it using the def_map
 fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>,
                 id: ast::NodeId) -> Type {
-    let cx = super::ctxtkey.get().unwrap();
+    let cx = get_cx();
     let tycx = match cx.maybe_typed {
         core::Typed(ref tycx) => tycx,
         // If we're extracting tests, this return value doesn't matter.
@@ -2012,7 +2015,7 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>,
         def::DefTyParamBinder(i) => return TyParamBinder(i),
         _ => {}
     };
-    let did = register_def(&**cx, def);
+    let did = register_def(&*cx, def);
     ResolvedPath { path: path, typarams: tpbs, did: did }
 }
 
@@ -2051,13 +2054,9 @@ fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
 }
 
 fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
-    let cx = super::ctxtkey.get().unwrap();
-    match cx.maybe_typed {
-        core::Typed(ref tcx) => {
-            tcx.def_map.borrow().find(&id).map(|&def| register_def(&**cx, def))
-        }
-        core::NotTyped(_) => None
-    }
+    get_cx().tcx_opt().and_then(|tcx| {
+        tcx.def_map.borrow().find(&id).map(|&def| register_def(&*get_cx(), def))
+    })
 }
 
 #[deriving(Clone, Encodable, Decodable)]
@@ -2072,6 +2071,7 @@ fn clean(&self) -> Item {
             attrs: self.attrs.clean(),
             source: self.where.clean(),
             visibility: ast::Public.clean(),
+            stability: self.stab.clean(),
             def_id: ast_util::local_def(self.id),
             inner: MacroItem(Macro {
                 source: self.where.to_src(),
@@ -2079,3 +2079,19 @@ fn clean(&self) -> Item {
         }
     }
 }
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Stability {
+    pub level: attr::StabilityLevel,
+    pub text: String
+}
+
+impl Clean<Stability> for attr::Stability {
+    fn clean(&self) -> Stability {
+        Stability {
+            level: self.level,
+            text: self.text.as_ref().map_or("".to_string(),
+                                            |interned| interned.get().to_string()),
+        }
+    }
+}
index ba0161da7e664054f9affe3d72cfc5c6c932c030..245b2d162a77b02c76632dd77042628834119b65 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc;
 use rustc::{driver, middle};
-use rustc::middle::privacy;
+use rustc::middle::{privacy, ty};
 use rustc::lint;
 
 use syntax::ast;
@@ -26,6 +26,7 @@
 use clean;
 use clean::Clean;
 
+/// Are we generating documentation (`Typed`) or tests (`NotTyped`)?
 pub enum MaybeTyped {
     Typed(middle::ty::ctxt),
     NotTyped(driver::session::Session)
@@ -52,6 +53,18 @@ pub fn sess<'a>(&'a self) -> &'a driver::session::Session {
             NotTyped(ref sess) => sess
         }
     }
+
+    pub fn tcx_opt<'a>(&'a self) -> Option<&'a ty::ctxt> {
+        match self.maybe_typed {
+            Typed(ref tcx) => Some(tcx),
+            NotTyped(_) => None
+        }
+    }
+
+    pub fn tcx<'a>(&'a self) -> &'a ty::ctxt {
+        let tcx_opt = self.tcx_opt();
+        tcx_opt.expect("tcx not present")
+    }
 }
 
 pub struct CrateAnalysis {
index b8a2a6195b7a539ab09507485823bc492960c544..313f1c81c79e81ba8df55f0d5af5fb24b11cd01a 100644 (file)
@@ -14,6 +14,7 @@
 use syntax;
 use syntax::codemap::Span;
 use syntax::ast;
+use syntax::attr;
 use syntax::ast::{Ident, NodeId};
 
 use std::gc::Gc;
@@ -32,6 +33,7 @@ pub struct Module {
     pub statics: Vec<Static>,
     pub traits: Vec<Trait>,
     pub vis: ast::Visibility,
+    pub stab: Option<attr::Stability>,
     pub impls: Vec<Impl>,
     pub foreigns: Vec<ast::ForeignMod>,
     pub view_items: Vec<ast::ViewItem>,
@@ -45,6 +47,7 @@ pub fn new(name: Option<Ident>) -> Module {
             name       : name,
             id: 0,
             vis: ast::Inherited,
+            stab: None,
             where_outer: syntax::codemap::DUMMY_SP,
             where_inner: syntax::codemap::DUMMY_SP,
             attrs      : Vec::new(),
@@ -83,6 +86,7 @@ pub enum TypeBound {
 
 pub struct Struct {
     pub vis: ast::Visibility,
+    pub stab: Option<attr::Stability>,
     pub id: NodeId,
     pub struct_type: StructType,
     pub name: Ident,
@@ -94,6 +98,7 @@ pub struct Struct {
 
 pub struct Enum {
     pub vis: ast::Visibility,
+    pub stab: Option<attr::Stability>,
     pub variants: Vec<Variant>,
     pub generics: ast::Generics,
     pub attrs: Vec<ast::Attribute>,
@@ -108,6 +113,7 @@ pub struct Variant {
     pub kind: ast::VariantKind,
     pub id: ast::NodeId,
     pub vis: ast::Visibility,
+    pub stab: Option<attr::Stability>,
     pub where: Span,
 }
 
@@ -117,6 +123,7 @@ pub struct Function {
     pub id: NodeId,
     pub name: Ident,
     pub vis: ast::Visibility,
+    pub stab: Option<attr::Stability>,
     pub fn_style: ast::FnStyle,
     pub where: Span,
     pub generics: ast::Generics,
@@ -130,6 +137,7 @@ pub struct Typedef {
     pub attrs: Vec<ast::Attribute>,
     pub where: Span,
     pub vis: ast::Visibility,
+    pub stab: Option<attr::Stability>,
 }
 
 pub struct Static {
@@ -139,6 +147,7 @@ pub struct Static {
     pub name: Ident,
     pub attrs: Vec<ast::Attribute>,
     pub vis: ast::Visibility,
+    pub stab: Option<attr::Stability>,
     pub id: ast::NodeId,
     pub where: Span,
 }
@@ -152,6 +161,7 @@ pub struct Trait {
     pub id: ast::NodeId,
     pub where: Span,
     pub vis: ast::Visibility,
+    pub stab: Option<attr::Stability>,
 }
 
 pub struct Impl {
@@ -162,6 +172,7 @@ pub struct Impl {
     pub attrs: Vec<ast::Attribute>,
     pub where: Span,
     pub vis: ast::Visibility,
+    pub stab: Option<attr::Stability>,
     pub id: ast::NodeId,
 }
 
@@ -170,6 +181,7 @@ pub struct Macro {
     pub id: ast::NodeId,
     pub attrs: Vec<ast::Attribute>,
     pub where: Span,
+    pub stab: Option<attr::Stability>,
 }
 
 pub fn struct_type_from_def(sd: &ast::StructDef) -> StructType {
index 77b12aec97b41bd72357bd709b329212d696871a..60853f450ab329dcb0a5d3ad5a5bedaf5d33a509 100644 (file)
@@ -19,7 +19,7 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
 
     /// don't override!
     fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
-        let Item { attrs, name, source, visibility, def_id, inner } = item;
+        let Item { attrs, name, source, visibility, def_id, inner, stability } = item;
         let inner = inner;
         let inner = match inner {
             StructItem(mut i) => {
@@ -83,7 +83,7 @@ fn vtrm<T: DocFolder>(this: &mut T, trm: TraitMethod) -> Option<TraitMethod> {
         };
 
         Some(Item { attrs: attrs, name: name, source: source, inner: inner,
-                    visibility: visibility, def_id: def_id })
+                    visibility: visibility, stability: stability, def_id: def_id })
     }
 
     fn fold_mod(&mut self, m: Module) -> Module {
index fa18b6291be74140dce46cf3e5eba7f419fbc678..9677b9004cdf1a12e015b56191ab3426747f1e1d 100644 (file)
 pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl);
 /// Similar to VisSpace, but used for mutability
 pub struct MutableSpace(pub clean::Mutability);
+/// Wrapper struct for properly emitting the stability level.
+pub struct Stability<'a>(pub &'a Option<clean::Stability>);
+/// Wrapper struct for emitting the stability level concisely.
+pub struct ConciseStability<'a>(pub &'a Option<clean::Stability>);
 
 impl VisSpace {
     pub fn get(&self) -> Option<ast::Visibility> {
@@ -596,3 +600,34 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         }
     }
 }
+
+impl<'a> fmt::Show for Stability<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let Stability(stab) = *self;
+        match *stab {
+            Some(ref stability) => {
+                write!(f, "<a class='stability {lvl}' title='{reason}'>{lvl}</a>",
+                       lvl = stability.level.to_str(),
+                       reason = stability.text)
+            }
+            None => Ok(())
+        }
+    }
+}
+
+impl<'a> fmt::Show for ConciseStability<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let ConciseStability(stab) = *self;
+        match *stab {
+            Some(ref stability) => {
+                write!(f, "<a class='stability {lvl}' title='{lvl}{colon}{reason}'></a>",
+                       lvl = stability.level.to_str(),
+                       colon = if stability.text.len() > 0 { ": " } else { "" },
+                       reason = stability.text)
+            }
+            None => {
+                write!(f, "<a class='stability Unmarked' title='No stability level'></a>")
+            }
+        }
+    }
+}
index f5d379c4bafa10844c903ec6789f3638ff0498e2..917eab4eeb9918e547fc2e42f105b85c83c2d516 100644 (file)
 use serialize::json::ToJson;
 use syntax::ast;
 use syntax::ast_util;
-use syntax::attr;
-use syntax::parse::token::InternedString;
 use rustc::util::nodemap::NodeSet;
 
 use clean;
 use doctree;
 use fold::DocFolder;
-use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace};
+use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace, Stability};
+use html::format::{ConciseStability};
 use html::highlight;
 use html::item_type::{ItemType, shortty};
 use html::item_type;
@@ -114,6 +113,15 @@ pub struct Implementor {
     generics: clean::Generics,
     trait_: clean::Type,
     for_: clean::Type,
+    stability: Option<clean::Stability>,
+}
+
+/// Metadata about implementations for a type.
+#[deriving(Clone)]
+pub struct Impl {
+    impl_: clean::Impl,
+    dox: Option<String>,
+    stability: Option<clean::Stability>,
 }
 
 /// This cache is used to store information about the `clean::Crate` being
@@ -137,7 +145,7 @@ pub struct Cache {
     ///
     /// The values of the map are a list of implementations and documentation
     /// found on that implementation.
-    pub impls: HashMap<ast::DefId, Vec<(clean::Impl, Option<String>)>>,
+    pub impls: HashMap<ast::DefId, Vec<Impl>>,
 
     /// Maintains a mapping of local crate node ids to the fully qualified name
     /// and "short type description" of that node. This is used when generating
@@ -550,7 +558,8 @@ fn collect(path: &Path, krate: &str,
             // going on). If they're in different crates then the crate defining
             // the trait will be interested in our implementation.
             if imp.def_id.krate == did.krate { continue }
-            try!(write!(&mut f, r#""impl{} {} for {}","#,
+            try!(write!(&mut f, r#""{}impl{} {} for {}","#,
+                        ConciseStability(&imp.stability),
                         imp.generics, imp.trait_, imp.for_));
         }
         try!(writeln!(&mut f, r"];"));
@@ -782,6 +791,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                             generics: i.generics.clone(),
                             trait_: i.trait_.get_ref().clone(),
                             for_: i.for_.clone(),
+                            stability: item.stability.clone(),
                         });
                     }
                     Some(..) | None => {}
@@ -967,7 +977,11 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                                 let v = self.impls.find_or_insert_with(did, |_| {
                                     Vec::new()
                                 });
-                                v.push((i, dox));
+                                v.push(Impl {
+                                    impl_: i,
+                                    dox: dox,
+                                    stability: item.stability.clone(),
+                                });
                             }
                             None => {}
                         }
@@ -1248,19 +1262,8 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(fmt, "<a class='{}' href=''>{}</a>",
                     shortty(self.item), self.item.name.get_ref().as_slice()));
 
-        // Write stability attributes
-        match attr::find_stability_generic(self.item.attrs.iter()) {
-            Some((ref stability, _)) => {
-                try!(write!(fmt,
-                       "<a class='stability {lvl}' title='{reason}'>{lvl}</a>",
-                       lvl = stability.level.to_str(),
-                       reason = match stability.text {
-                           Some(ref s) => (*s).clone(),
-                           None => InternedString::new(""),
-                       }));
-            }
-            None => {}
-        }
+        // Write stability level
+        try!(write!(fmt, "{}", Stability(&self.item.stability)));
 
         // Write `src` tag
         //
@@ -1454,10 +1457,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
                 try!(write!(w, "
                     <tr>
-                        <td><code>{}static {}{}: {}</code>{}</td>
+                        <td>{}<code>{}static {}{}: {}</code>{}</td>
                         <td class='docblock'>{}&nbsp;</td>
                     </tr>
                 ",
+                ConciseStability(&myitem.stability),
                 VisSpace(myitem.visibility),
                 MutableSpace(s.mutability),
                 *myitem.name.get_ref(),
@@ -1492,7 +1496,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 if myitem.name.is_none() { continue }
                 try!(write!(w, "
                     <tr>
-                        <td><a class='{class}' href='{href}'
+                        <td>{stab}<a class='{class}' href='{href}'
                                title='{title}'>{}</a></td>
                         <td class='docblock short'>{}</td>
                     </tr>
@@ -1501,7 +1505,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 Markdown(shorter(myitem.doc_value())),
                 class = shortty(myitem),
                 href = item_path(myitem),
-                title = full_path(cx, myitem)));
+                title = full_path(cx, myitem),
+                stab = ConciseStability(&myitem.stability)));
             }
         }
     }
@@ -1565,9 +1570,10 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     try!(document(w, it));
 
     fn meth(w: &mut fmt::Formatter, m: &clean::TraitMethod) -> fmt::Result {
-        try!(write!(w, "<h3 id='{}.{}' class='method'><code>",
-                      shortty(m.item()),
-                      *m.item().name.get_ref()));
+        try!(write!(w, "<h3 id='{}.{}' class='method'>{}<code>",
+                    shortty(m.item()),
+                    *m.item().name.get_ref(),
+                    ConciseStability(&m.item().stability)));
         try!(render_method(w, m.item()));
         try!(write!(w, "</code></h3>"));
         try!(document(w, m.item()));
@@ -1604,7 +1610,8 @@ fn meth(w: &mut fmt::Formatter, m: &clean::TraitMethod) -> fmt::Result {
     match cache.implementors.find(&it.def_id) {
         Some(implementors) => {
             for i in implementors.iter() {
-                try!(writeln!(w, "<li><code>impl{} {} for {}</code></li>",
+                try!(writeln!(w, "<li>{}<code>impl{} {} for {}</code></li>",
+                              ConciseStability(&i.stability),
                               i.generics, i.trait_, i.for_));
             }
         }
@@ -1677,7 +1684,8 @@ fn item_struct(w: &mut fmt::Formatter, it: &clean::Item,
             try!(write!(w, "<h2 class='fields'>Fields</h2>\n<table>"));
             for field in fields {
                 try!(write!(w, "<tr><td id='structfield.{name}'>\
-                                  <code>{name}</code></td><td>",
+                                  {stab}<code>{name}</code></td><td>",
+                              stab = ConciseStability(&field.stability),
                               name = field.name.get_ref().as_slice()));
                 try!(document(w, field));
                 try!(write!(w, "</td></tr>"));
@@ -1743,7 +1751,8 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item,
     if e.variants.len() > 0 {
         try!(write!(w, "<h2 class='variants'>Variants</h2>\n<table>"));
         for variant in e.variants.iter() {
-            try!(write!(w, "<tr><td id='variant.{name}'><code>{name}</code></td><td>",
+            try!(write!(w, "<tr><td id='variant.{name}'>{stab}<code>{name}</code></td><td>",
+                          stab = ConciseStability(&variant.stability),
                           name = variant.name.get_ref().as_slice()));
             try!(document(w, variant));
             match variant.inner {
@@ -1853,39 +1862,25 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
 fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
     match cache_key.get().unwrap().impls.find(&it.def_id) {
         Some(v) => {
-            let mut non_trait = v.iter().filter(|p| {
-                p.ref0().trait_.is_none()
-            });
-            let non_trait = non_trait.collect::<Vec<&(clean::Impl, Option<String>)>>();
-            let mut traits = v.iter().filter(|p| {
-                p.ref0().trait_.is_some()
-            });
-            let traits = traits.collect::<Vec<&(clean::Impl, Option<String>)>>();
-
+            let (non_trait, traits) = v.partitioned(|i| i.impl_.trait_.is_none());
             if non_trait.len() > 0 {
                 try!(write!(w, "<h2 id='methods'>Methods</h2>"));
-                for &(ref i, ref dox) in non_trait.move_iter() {
-                    try!(render_impl(w, i, dox));
+                for i in non_trait.iter() {
+                    try!(render_impl(w, i));
                 }
             }
             if traits.len() > 0 {
                 try!(write!(w, "<h2 id='implementations'>Trait \
                                   Implementations</h2>"));
-                let mut any_derived = false;
-                for & &(ref i, ref dox) in traits.iter() {
-                    if !i.derived {
-                        try!(render_impl(w, i, dox));
-                    } else {
-                        any_derived = true;
-                    }
+                let (derived, manual) = traits.partition(|i| i.impl_.derived);
+                for i in manual.iter() {
+                    try!(render_impl(w, i));
                 }
-                if any_derived {
+                if derived.len() > 0 {
                     try!(write!(w, "<h3 id='derived_implementations'>Derived Implementations \
                                 </h3>"));
-                    for &(ref i, ref dox) in traits.move_iter() {
-                        if i.derived {
-                            try!(render_impl(w, i, dox));
-                        }
+                    for i in derived.iter() {
+                        try!(render_impl(w, i));
                     }
                 }
             }
@@ -1895,15 +1890,16 @@ fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
     Ok(())
 }
 
-fn render_impl(w: &mut fmt::Formatter, i: &clean::Impl,
-               dox: &Option<String>) -> fmt::Result {
-    try!(write!(w, "<h3 class='impl'><code>impl{} ", i.generics));
-    match i.trait_ {
+fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
+    try!(write!(w, "<h3 class='impl'>{}<code>impl{} ",
+                ConciseStability(&i.stability),
+                i.impl_.generics));
+    match i.impl_.trait_ {
         Some(ref ty) => try!(write!(w, "{} for ", *ty)),
         None => {}
     }
-    try!(write!(w, "{}</code></h3>", i.for_));
-    match *dox {
+    try!(write!(w, "{}</code></h3>", i.impl_.for_));
+    match i.dox {
         Some(ref dox) => {
             try!(write!(w, "<div class='docblock'>{}</div>",
                           Markdown(dox.as_slice())));
@@ -1913,8 +1909,9 @@ fn render_impl(w: &mut fmt::Formatter, i: &clean::Impl,
 
     fn docmeth(w: &mut fmt::Formatter, item: &clean::Item,
                dox: bool) -> fmt::Result {
-        try!(write!(w, "<h4 id='method.{}' class='method'><code>",
-                      *item.name.get_ref()));
+        try!(write!(w, "<h4 id='method.{}' class='method'>{}<code>",
+                    *item.name.get_ref(),
+                    ConciseStability(&item.stability)));
         try!(render_method(w, item));
         try!(write!(w, "</code></h4>\n"));
         match item.doc_value() {
@@ -1926,8 +1923,8 @@ fn docmeth(w: &mut fmt::Formatter, item: &clean::Item,
         }
     }
 
-    try!(write!(w, "<div class='methods'>"));
-    for meth in i.methods.iter() {
+    try!(write!(w, "<div class='impl-methods'>"));
+    for meth in i.impl_.methods.iter() {
         try!(docmeth(w, meth, true));
     }
 
@@ -1948,11 +1945,11 @@ fn render_default_methods(w: &mut fmt::Formatter,
 
     // If we've implemented a trait, then also emit documentation for all
     // default methods which weren't overridden in the implementation block.
-    match i.trait_ {
+    match i.impl_.trait_ {
         Some(clean::ResolvedPath { did, .. }) => {
             try!({
                 match cache_key.get().unwrap().traits.find(&did) {
-                    Some(t) => try!(render_default_methods(w, t, i)),
+                    Some(t) => try!(render_default_methods(w, t, &i.impl_)),
                     None => {}
                 }
                 Ok(())
index a88992f6c4c508344f3ebac359ff0bdfb0f69072..97048229ac4c1842180a90c6ace19b7c5dff06a0 100644 (file)
@@ -258,8 +258,9 @@ nav.sub {
 .content .multi-column li { width: 100%; display: inline-block; }
 
 .content .method { font-size: 1em; }
-.content .methods { margin-left: 20px; }
-.content .methods .docblock { margin-left: 20px; }
+.content .methods .docblock { margin-left: 40px; }
+
+.content .impl-methods .docblock { margin-left: 40px; }
 
 nav {
     border-bottom: 1px solid #e0e0e0;
@@ -372,20 +373,29 @@ p a:hover { text-decoration: underline; }
 }
 
 .stability {
-    border-left: 6px solid #000;
+    border-left: 6px solid;
+    padding: 3px 6px;
     border-radius: 3px;
-    font-weight: 400;
-    padding: 4px 10px;
+}
+
+h1 .stability {
     text-transform: lowercase;
+    font-weight: 400;
     margin-left: 14px;
+    padding: 4px 10px;
+}
+
+.impl-methods .stability {
+    margin-right: 20px;
 }
 
-.stability.Deprecated { border-color: #D60027; color: #880017; }
-.stability.Experimental { border-color: #EC5315; color: #a53c0e; }
-.stability.Unstable { border-color: #FFD700; color: #b39800; }
-.stability.Stable { border-color: #AEC516; color: #7c8b10; }
+.stability.Deprecated { border-color: #A071A8; color: #82478C; }
+.stability.Experimental { border-color: #D46D6A; color: #AA3C39; }
+.stability.Unstable { border-color: #D4B16A; color: #AA8439; }
+.stability.Stable { border-color: #54A759; color: #2D8632; }
 .stability.Frozen { border-color: #009431; color: #007726; }
 .stability.Locked { border-color: #0084B6; color: #00668c; }
+.stability.Unmarked { border-color: #FFFFFF; }
 
 :target { background: #FDFFD3; }
 
index 00fe0134f00ee356907c2f725e4f7adf4116c9cb..b7ef0956a7c7640a57593b0fbf133405d1b570cc 100644 (file)
 use syntax::ast;
 use syntax::ast_util;
 use syntax::ast_map;
+use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::codemap::Span;
 
+use rustc::middle::stability;
+
 use std::gc::{Gc, GC};
 
 use core;
@@ -41,6 +44,14 @@ pub fn new<'b>(cx: &'b core::DocContext,
         }
     }
 
+    fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> {
+        let tcx = match self.cx.maybe_typed {
+            core::Typed(ref tcx) => tcx,
+            core::NotTyped(_) => return None
+        };
+        stability::lookup(tcx, ast_util::local_def(id))
+    }
+
     pub fn visit(&mut self, krate: &ast::Crate) {
         self.attrs = krate.attrs.iter().map(|x| (*x).clone()).collect();
 
@@ -65,6 +76,7 @@ pub fn visit_struct_def(&mut self, item: &ast::Item, sd: Gc<ast::StructDef>,
             struct_type: struct_type,
             name: item.ident,
             vis: item.vis,
+            stab: self.stability(item.id),
             attrs: item.attrs.iter().map(|x| *x).collect(),
             generics: generics.clone(),
             fields: sd.fields.iter().map(|x| (*x).clone()).collect(),
@@ -81,6 +93,7 @@ pub fn visit_enum_def(&mut self, it: &ast::Item, def: &ast::EnumDef,
                 name: x.node.name,
                 attrs: x.node.attrs.iter().map(|x| *x).collect(),
                 vis: x.node.vis,
+                stab: self.stability(x.node.id),
                 id: x.node.id,
                 kind: x.node.kind.clone(),
                 where: x.span,
@@ -90,6 +103,7 @@ pub fn visit_enum_def(&mut self, it: &ast::Item, def: &ast::EnumDef,
             name: it.ident,
             variants: vars,
             vis: it.vis,
+            stab: self.stability(it.id),
             generics: params.clone(),
             attrs: it.attrs.iter().map(|x| *x).collect(),
             id: it.id,
@@ -104,6 +118,7 @@ pub fn visit_fn(&mut self, item: &ast::Item, fd: &ast::FnDecl,
         Function {
             id: item.id,
             vis: item.vis,
+            stab: self.stability(item.id),
             attrs: item.attrs.iter().map(|x| *x).collect(),
             decl: fd.clone(),
             name: item.ident,
@@ -125,6 +140,7 @@ pub fn visit_mod_contents(&mut self, span: Span, attrs: Vec<ast::Attribute> ,
         om.where_inner = m.inner;
         om.attrs = attrs;
         om.vis = vis;
+        om.stab = self.stability(id);
         om.id = id;
         for i in m.items.iter() {
             self.visit_item(&**i, &mut om);
@@ -258,6 +274,7 @@ pub fn visit_item(&mut self, item: &ast::Item, om: &mut Module) {
                     attrs: item.attrs.iter().map(|x| *x).collect(),
                     where: item.span,
                     vis: item.vis,
+                    stab: self.stability(item.id),
                 };
                 om.typedefs.push(t);
             },
@@ -271,6 +288,7 @@ pub fn visit_item(&mut self, item: &ast::Item, om: &mut Module) {
                     attrs: item.attrs.iter().map(|x| *x).collect(),
                     where: item.span,
                     vis: item.vis,
+                    stab: self.stability(item.id),
                 };
                 om.statics.push(s);
             },
@@ -284,6 +302,7 @@ pub fn visit_item(&mut self, item: &ast::Item, om: &mut Module) {
                     attrs: item.attrs.iter().map(|x| *x).collect(),
                     where: item.span,
                     vis: item.vis,
+                    stab: self.stability(item.id),
                 };
                 om.traits.push(t);
             },
@@ -297,6 +316,7 @@ pub fn visit_item(&mut self, item: &ast::Item, om: &mut Module) {
                     id: item.id,
                     where: item.span,
                     vis: item.vis,
+                    stab: self.stability(item.id),
                 };
                 om.impls.push(i);
             },
@@ -309,6 +329,7 @@ pub fn visit_item(&mut self, item: &ast::Item, om: &mut Module) {
                     attrs: item.attrs.iter().map(|x| *x).collect(),
                     name: item.ident,
                     where: item.span,
+                    stab: self.stability(item.id),
                 })
             }
         }
index 2730d90f05fc121b6acccad4eb3bd89d466bf468..fae1b933210d52a9c2f8f49499583eeb03f49873 100644 (file)
@@ -10,6 +10,8 @@
 
 //! Operations on ASCII strings and characters
 
+#![experimental]
+
 use collections::Collection;
 use fmt;
 use iter::Iterator;
index 7d821983075b1c66a3f78b5b9b8e4a854374008d..834d461f20ba1517f85fede4cd68ccdbfaaf264d 100644 (file)
 //! - `insert`: inserts the specified flags in-place
 //! - `remove`: removes the specified flags in-place
 
+#![experimental]
 #![macro_escape]
 
 #[macro_export]
index 1926d6b1b960fc4f36bb19bc76c03609c5191e8a..a7d697c8665ef639132dac200953b41e65d885c1 100644 (file)
@@ -33,6 +33,8 @@
 //! handled correctly, i.e. that allocated memory is eventually freed
 //! if necessary.
 
+#![experimental]
+
 use collections::Collection;
 use kinds::Send;
 use mem;
index 9e5288f9541b8c1869ac400f8936e36998dbe2b2..ccef1c0fd2adb80331da2b646ff06de772ffba05 100644 (file)
@@ -12,6 +12,8 @@
  * Collection types.
  */
 
+#![experimental]
+
 pub use core_collections::{Collection, Mutable, Map, MutableMap};
 pub use core_collections::{Set, MutableSet, Deque};
 pub use core_collections::{Bitv, BitvSet, BTree, DList, EnumSet};
index d1552f0bd10122e3d10c455e1099c298aae51dbc..47ff85e2806d562caf77f6e81d12dc1255e36e9f 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![experimental]
+
 use alloc::owned::Box;
 use any::{Any, AnyRefExt};
 use fmt;
index ef0c59268c3c04af9c9f662c652b930b0ab9a984..5834e576b0814039d6c9c8d8396d052f58c41ea9 100644 (file)
@@ -412,6 +412,8 @@ fn my_fmt_fn(args: &fmt::Arguments) {
 
 */
 
+#![experimental]
+
 use io::Writer;
 use io;
 use result::{Ok, Err};
index 642bec48b836bda2f8beb086ba48428f9d2f76a3..1ca72bca20bdb5cbec9b983e2e90f7f8e7991262 100644 (file)
@@ -10,6 +10,8 @@
 
 //! The `FromStr` trait for types that can be created from strings
 
+#![experimental]
+
 use option::{Option, Some, None};
 use string::String;
 use str::StrAllocating;
index 80f1cbe6cb29e3bcdc07836c4c347bebef525f7d..47b7426633c7b0c34e1631d922211cd44ab2397e 100644 (file)
@@ -16,6 +16,7 @@
 
 */
 
+#![experimental]
 #![allow(experimental)]
 
 use clone::Clone;
index 8014759c88ab0c3c239b51323d1ad1c8e13ff1c9..1d339b03af6717d9eb68e4908f3e6e4e7333bbf8 100644 (file)
@@ -216,6 +216,7 @@ fn file_product(p: &Path) -> IoResult<u32> {
 
 */
 
+#![experimental]
 #![deny(unused_must_use)]
 
 use char::Char;
index f63e69f3cca0a17af6720d38f95608212ccee046..48ccd1aa22ce3be3b18f6d517b8816aec688f4b2 100644 (file)
@@ -95,6 +95,7 @@
 //! and `format!`, also available to all Rust code.
 
 #![crate_id = "std#0.11.0-pre"]
+#![unstable]
 #![comment = "The Rust standard library"]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
index 4db15d2cbbe0b03a216ef26dfb82edfbdd541ee9..8b79af8c9310d27c4ad8f6fa73711417a47dd91d 100644 (file)
@@ -14,6 +14,7 @@
 //! library. Each macro is available for use when linking against the standard
 //! library.
 
+#![experimental]
 #![macro_escape]
 
 /// The entry point for failure of rust tasks.
index bbf1458da216e0852d5c7d11b8f3d3182265ddcd..2b2ffb9f4e281706052a95a1797d3c10b984cf00 100644 (file)
@@ -10,6 +10,7 @@
 
 //! Operations and constants for 32-bits floats (`f32` type)
 
+#![experimental]
 #![allow(missing_doc)]
 #![allow(unsigned_negate)]
 #![doc(primitive = "f32")]
index cfa8534160bae9fd6d2c52c1d7a5061a009d6856..e156d2ce553240b629b6594429b60ef3eb303725 100644 (file)
@@ -10,6 +10,7 @@
 
 //! Operations and constants for 64-bits floats (`f64` type)
 
+#![experimental]
 #![allow(missing_doc)]
 #![doc(primitive = "f64")]
 
index 3e403219a4fbaffdc207d8c2015ba88431a4e67f..519de85edde65f3c4fa6aa535ce3a9064ee77f99 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![experimental]
 #![macro_escape]
 #![doc(hidden)]
 
index 9b3c9d29cc74a193a0d3e98200beb0ebc0d7b075..a4200b55a5906f575aa1bc6942f6a7a7f7cc4a47 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![experimental]
 #![macro_escape]
 #![doc(hidden)]
 
index 65056652e3f97860ba05665c05475dc48a39d07c..27ee1e3ce3bb31d8c1e42d05b9b9e670261b47cc 100644 (file)
@@ -13,6 +13,7 @@
 //! These are implemented for the primitive numeric types in `std::{u8, u16,
 //! u32, u64, uint, i8, i16, i32, i64, int, f32, f64}`.
 
+#![experimental]
 #![allow(missing_doc)]
 
 use option::Option;
index 19e45b292fbb5f731e06eb9f20154022f7ccb877..7f2efe034a24a77b8c4acb8ae83e1abef89eff64 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![experimental]
 #![macro_escape]
 #![doc(hidden)]
 #![allow(unsigned_negate)]
index 5201a81179144e2f7658f6c3d688ff101399c754..6674dd532aeb0b5f76d924b3e8c5a5555a863a00 100644 (file)
@@ -26,6 +26,8 @@
  * to write OS-ignorant code by default.
  */
 
+#![experimental]
+
 #![allow(missing_doc)]
 #![allow(non_snake_case_functions)]
 
index 6d48122b1867e98c69afb6d6dcc79a496c003398..7d814df8ebf95dd11190f7d00f0db804f31c7fad 100644 (file)
@@ -63,6 +63,8 @@
 
 */
 
+#![experimental]
+
 use collections::Collection;
 use c_str::CString;
 use clone::Clone;
index dfe6988624eb017dce9c5243489ab9ed0cc5503b..61e8b63af359ef6d042d511d7b785a049a82f0c3 100644 (file)
@@ -37,6 +37,8 @@
 //! particularly useful standalone functions, like `from_str`, `range`, and
 //! `drop`, `spawn`, and `channel`.
 
+#![experimental]
+
 // Reexported core operators
 #[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Share};
 #[doc(no_inline)] pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
index f48d487461ef4b70cd968f8f63a25cba480e4348..0ffaadef0a1303c876c52d3a4bcd8cc8f68b9659 100644 (file)
@@ -73,6 +73,8 @@
 ```
 */
 
+#![experimental]
+
 use cell::RefCell;
 use clone::Clone;
 use io::IoResult;
index 19853138afd547ce5f44295429a4444486ac89d8..4490977bde619ef833f725c75af39cb9fa8ef796 100644 (file)
@@ -51,6 +51,8 @@
 
 */
 
+#![experimental]
+
 // FIXME: this should not be here.
 #![allow(missing_doc)]
 
index f8bfde52261632f1887ccffe786d263f9b4d45e3..0ffac99775c11a75ceac8651d1083d98b41ba7fc 100644 (file)
@@ -12,6 +12,8 @@
 //! the standard library This varies per-platform, but these libraries are
 //! necessary for running libstd.
 
+#![experimental]
+
 // All platforms need to link to rustrt
 #[link(name = "rust_builtin", kind = "static")]
 extern {}
index 5f45ce25502231d710191657f90ff51c5a98858d..cc32818baa4561df7fd3e75a37440cae33388b38 100644 (file)
@@ -15,6 +15,8 @@
 //! and/or blocking at all, but rather provide the necessary tools to build
 //! other types of concurrent primitives.
 
+#![experimental]
+
 pub use core_sync::{atomics, deque, mpmc_bounded_queue, mpsc_queue, spsc_queue};
 pub use core_sync::{Arc, Weak, Mutex, MutexGuard, Condvar, Barrier};
 pub use core_sync::{RWLock, RWLockReadGuard, RWLockWriteGuard};
index 6492717d3ecafd95d8321818cd902c3b53af9ec4..c20cbea0ae7cced97332673d8e1eda74ea934486 100644 (file)
@@ -91,6 +91,8 @@
 //! # }
 //! ```
 
+#![experimental]
+
 use any::Any;
 use comm::channel;
 use io::{Writer, stdio};
index 5deb7f151bb625252ed77627190413322f111bc1..e51e2c4d9ce5e5acbff2437c02d9e37d26bc2a2e 100644 (file)
@@ -14,6 +14,8 @@
 
 */
 
+#![experimental]
+
 use fmt;
 use string::String;