]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #14831 : alexcrichton/rust/format-intl, r=brson
authorbors <bors@rust-lang.org>
Fri, 13 Jun 2014 14:42:03 +0000 (14:42 +0000)
committerbors <bors@rust-lang.org>
Fri, 13 Jun 2014 14:42:03 +0000 (14:42 +0000)
* The select/plural methods from format strings are removed
* The # character no longer needs to be escaped
* The \-based escapes have been removed
* '{{' is now an escape for '{'
* '}}' is now an escape for '}'

Closes #14810
[breaking-change]

95 files changed:
.travis.yml
configure
mk/rt.mk
src/doc/guide-lifetimes.md
src/doc/rust.md
src/doc/tutorial.md
src/liballoc/heap.rs
src/libcollections/hash/mod.rs
src/libcollections/hash/sip.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/vec.rs
src/libcore/cell.rs
src/libcore/clone.rs
src/libcore/failure.rs
src/libcore/fmt/mod.rs
src/libcore/intrinsics.rs
src/libcore/iter.rs
src/libcore/lib.rs
src/libcore/option.rs
src/libcore/ptr.rs
src/libcore/raw.rs
src/libcore/slice.rs
src/libdebug/reflect.rs
src/libdebug/repr.rs
src/libflate/lib.rs
src/libfourcc/lib.rs
src/libgetopts/lib.rs
src/libglob/lib.rs
src/libgraphviz/maybe_owned_vec.rs
src/libgreen/context.rs
src/libgreen/lib.rs
src/libhexfloat/lib.rs
src/liblog/lib.rs
src/libnum/lib.rs
src/libregex/lib.rs
src/librustc/driver/config.rs
src/librustc/driver/driver.rs
src/librustc/driver/mod.rs
src/librustc/driver/session.rs
src/librustc/lib.rs
src/librustc/lib/llvm.rs
src/librustc/middle/dataflow.rs
src/librustc/middle/lint.rs
src/librustc/middle/resolve.rs
src/librustc/middle/save/mod.rs [new file with mode: 0644]
src/librustc/middle/save/recorder.rs [new file with mode: 0644]
src/librustc/middle/save/span_utils.rs [new file with mode: 0644]
src/librustc/middle/trans/debuginfo.rs
src/librustc/middle/ty.rs
src/librustrt/local_data.rs
src/libsemver/lib.rs
src/libserialize/json.rs
src/libserialize/serialize.rs
src/libstd/ascii.rs
src/libstd/io/comm_adapters.rs
src/libstd/io/extensions.rs
src/libstd/io/fs.rs
src/libstd/io/mem.rs
src/libstd/io/process.rs
src/libstd/io/util.rs
src/libstd/os.rs
src/libstd/path/mod.rs
src/libstd/path/posix.rs
src/libstd/path/windows.rs
src/libstd/prelude.rs
src/libstd/rand/mod.rs
src/libstd/rand/reader.rs
src/libstd/to_str.rs
src/libsync/lib.rs
src/libsync/one.rs
src/libsyntax/codemap.rs
src/libsyntax/parse/obsolete.rs
src/libsyntax/parse/parser.rs
src/libtest/lib.rs
src/libtest/stats.rs
src/libtime/lib.rs
src/rustllvm/RustWrapper.cpp
src/test/auxiliary/cross_crate_debuginfo_type_uniquing.rs [new file with mode: 0644]
src/test/bench/shootout-regex-dna.rs
src/test/compile-fail/borrowck-use-in-index-lvalue.rs
src/test/compile-fail/issue-2150.rs
src/test/compile-fail/lint-deprecated-owned-vector.rs [deleted file]
src/test/compile-fail/lint-heap-memory.rs
src/test/compile-fail/lint-unused-imports.rs
src/test/compile-fail/lint-unused-mut-variables.rs
src/test/compile-fail/lint-unused-unsafe.rs
src/test/compile-fail/shadowing-in-the-same-pattern.rs [new file with mode: 0644]
src/test/debuginfo/cross-crate-type-uniquing.rs [new file with mode: 0644]
src/test/run-make/save-analysis/Makefile [new file with mode: 0644]
src/test/run-make/save-analysis/foo.rs [new file with mode: 0644]
src/test/run-pass/empty-allocation-non-null.rs
src/test/run-pass/ifmt.rs
src/test/run-pass/overloaded-autoderef.rs
src/test/run-pass/reflect-visit-type.rs

index 76e3af05d55cca8674ae8b52e8c33952d7d32aef..e3cec33ad070d340397e66e7e6a2f6295f3da90a 100644 (file)
@@ -27,7 +27,8 @@ before_script:
   - ln -nsf /usr/bin/llvm-dis-$LLVM_VERSION local-llvm/bin/llvm-dis
   - ln -nsf /usr/bin/llc-$LLVM_VERSION local-llvm/bin/llc
   - ln -nsf /usr/include/llvm-$LLVM_VERSION local-llvm/include
-  - ./configure --disable-optimize-tests --llvm-root=`pwd`/local-llvm --enable-fast-make --enable-clang
+  - ./configure --disable-optimize-tests --llvm-root=`pwd`/local-llvm
+    --enable-fast-make --enable-clang
 
 # Tidy everything up first, then build a few things, and then run a few tests.
 # Note that this is meant to run in a "fairly small" amount of time, so this
index e3cf990d47ca9da955c31ec09907b4fa1f24e03f..fe29e4883166b764c13ac2627e7c18501b630811 100755 (executable)
--- a/configure
+++ b/configure
@@ -425,6 +425,8 @@ opt verify-install 1 "verify installed binaries work"
 valopt prefix "/usr/local" "set installation prefix"
 valopt local-rust-root "/usr/local" "set prefix for local rust binary"
 valopt llvm-root "" "set LLVM root"
+valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located"
+valopt libuv-root "" "set directory where libuv.a is located"
 valopt android-cross-path "/opt/ndk_standalone" "Android NDK standalone path"
 valopt mingw32-cross-path "" "MinGW32 cross compiler path"
 
@@ -1198,6 +1200,8 @@ putvar CFG_ANDROID_CROSS_PATH
 putvar CFG_MINGW32_CROSS_PATH
 putvar CFG_MANDIR
 putvar CFG_DISABLE_INJECT_STD_VERSION
+putvar CFG_JEMALLOC_ROOT
+putvar CFG_LIBUV_ROOT
 
 # Avoid spurious warnings from clang by feeding it original source on
 # ccache-miss rather than preprocessed input.
index a75cb8aa4deb2f3a88e8dcb38db56b71fed4614d..1c4efd641f063752dafe38f430268e8ae23a5cdc 100644 (file)
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -204,19 +204,17 @@ $$(LIBUV_MAKEFILE_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS) $$(LIBUV_STAMP_$(1))
 # theory when we support msvc then we should be using gyp's msvc output instead
 # of mingw's makefile for windows
 ifdef CFG_WINDOWSY_$(1)
-$$(LIBUV_LIB_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS)
+LIBUV_LOCAL_$(1) := $$(S)src/libuv/libuv.a
+$$(LIBUV_LOCAL_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS)
        $$(Q)$$(MAKE) -C $$(S)src/libuv -f Makefile.mingw \
                LDFLAGS="$$(CFG_GCCISH_LINK_FLAGS_$(1))" \
                CC="$$(CC_$(1)) $$(LIBUV_CFLAGS_$(1)) $$(SNAP_DEFINES)" \
                CXX="$$(CXX_$(1))" \
                AR="$$(AR_$(1))" \
                V=$$(VERBOSE)
-       $$(Q)cp $$(S)src/libuv/libuv.a $$@
 else
-$$(LIBUV_LIB_$(1)): $$(LIBUV_DIR_$(1))/Release/libuv.a $$(MKFILE_DEPS)
-       $$(Q)cp $$< $$@
-$$(LIBUV_DIR_$(1))/Release/libuv.a: $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) \
-                                   $$(MKFILE_DEPS)
+LIBUV_LOCAL_$(1) := $$(LIBUV_DIR_$(1))/Release/libuv.a
+$$(LIBUV_LOCAL_$(1)): $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) $$(MKFILE_DEPS)
        $$(Q)$$(MAKE) -C $$(LIBUV_DIR_$(1)) \
                CFLAGS="$$(LIBUV_CFLAGS_$(1)) $$(SNAP_DEFINES)" \
                LDFLAGS="$$(CFG_GCCISH_LINK_FLAGS_$(1))" \
@@ -231,6 +229,19 @@ $$(LIBUV_DIR_$(1))/Release/libuv.a: $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) \
 
 endif
 
+ifeq ($(1),$$(CFG_BUILD))
+ifneq ($$(CFG_LIBUV_ROOT),)
+$$(LIBUV_LIB_$(1)): $$(CFG_LIBUV_ROOT)/libuv.a
+       $$(Q)cp $$< $$@
+else
+$$(LIBUV_LIB_$(1)): $$(LIBUV_LOCAL_$(1))
+       $$(Q)cp $$< $$@
+endif
+else
+$$(LIBUV_LIB_$(1)): $$(LIBUV_LOCAL_$(1))
+       $$(Q)cp $$< $$@
+endif
+
 ################################################################################
 # jemalloc
 ################################################################################
@@ -253,8 +264,9 @@ else
 endif
 JEMALLOC_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(JEMALLOC_NAME_$(1))
 JEMALLOC_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/jemalloc
+JEMALLOC_LOCAL_$(1) := $$(JEMALLOC_BUILD_DIR_$(1))/lib/$$(JEMALLOC_REAL_NAME_$(1))
 
-$$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
+$$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
        @$$(call E, make: jemalloc)
        cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \
                $$(JEMALLOC_ARGS_$(1)) --enable-cc-silence --with-jemalloc-prefix=je_ \
@@ -265,7 +277,20 @@ $$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
                CPPFLAGS="-I $(S)src/rt/" \
                EXTRA_CFLAGS="$$(CFG_CFLAGS_$(1)) -g1"
        $$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static
-       $$(Q)cp $$(JEMALLOC_BUILD_DIR_$(1))/lib/$$(JEMALLOC_REAL_NAME_$(1)) $$(JEMALLOC_LIB_$(1))
+
+ifeq ($(1),$$(CFG_BUILD))
+ifneq ($$(CFG_JEMALLOC_ROOT),)
+$$(JEMALLOC_LIB_$(1)): $$(CFG_JEMALLOC_ROOT)/libjemalloc_pic.a
+       @$$(call E, copy: jemalloc)
+       $$(Q)cp $$< $$@
+else
+$$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_LOCAL_$(1))
+       $$(Q)cp $$< $$@
+endif
+else
+$$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_LOCAL_$(1))
+       $$(Q)cp $$< $$@
+endif
 
 ################################################################################
 # compiler-rt
index 65f37031674c7caf637b6c067c5179a7fe4af95c..66b9ef1ea724605ae000790c4bb8aaa12167f218 100644 (file)
@@ -78,7 +78,7 @@ value. We also call this _borrowing_ the local variable
 name for the same data.
 
 In the case of `on_the_heap`, however, no explicit action is necessary. 
-The compiler will automatically convert a box box point to a reference like &point. 
+The compiler will automatically convert a box point to a reference like &point. 
 This is another form of borrowing; in this case, the contents of the owned box 
 are being lent out.
 
@@ -275,8 +275,10 @@ invalidate the pointer `owner_age`.
 
 # Borrowing and enums
 
-The previous example showed that the type system forbids any borrowing
-of owned boxes found in aliasable, mutable memory. This restriction
+The previous example showed that the type system forbids any mutations
+of owned boxed values while they are being borrowed. In general, the type
+system also forbids borrowing a value as mutable if it is already being
+borrowed - either as a mutable reference or an immutable one. This restriction
 prevents pointers from pointing into freed memory. There is one other
 case where the compiler must be very careful to ensure that pointers
 remain valid: pointers into the interior of an `enum`.
index 35d356bb1b56cd8e4935a627d0a20b1f1134b072..8f47e81ba5c8ecbf747eddba4dcf8988606feee9 100644 (file)
@@ -160,8 +160,8 @@ block_comment_body : [block_comment | character] * ;
 line_comment : "//" non_eol * ;
 ~~~~
 
-Comments in Rust code follow the general C++ style of line and block-comment forms,
-with no nesting of block-comment delimiters.
+Comments in Rust code follow the general C++ style of line and block-comment forms
+Nested block comments are supported.
 
 Line comments beginning with exactly _three_ slashes (`///`), and block
 comments beginning with exactly one repeated asterisk in the block-open
index 802f7cd40bfd401d2a52c99d41349315b42cd7ce..9322985a922ca19d48b9a904a142ec0a78f0e6f2 100644 (file)
@@ -2459,7 +2459,7 @@ fn draw_all(shapes: &[Box<Drawable>]) {
 }
 ~~~~
 
-In this example, there is no type parameter. Instead, the `~Drawable`
+In this example, there is no type parameter. Instead, the `Box<Drawable>`
 type denotes any owned box value that implements the `Drawable` trait.
 To construct such a value, you use the `as` operator to cast a value
 to an object:
index ba3180cefd665fc68dfb92155c84944f8ffb18ef..b03486a6c224c5ccd4cf580f5f686e0adb21e684 100644 (file)
@@ -155,24 +155,6 @@ unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint, align: uin
     alloc as *mut u8
 }
 
-// hack for libcore
-#[no_mangle]
-#[doc(hidden)]
-#[deprecated]
-#[cfg(not(test))]
-pub unsafe extern "C" fn rust_allocate(size: uint, align: uint) -> *mut u8 {
-    allocate(size, align)
-}
-
-// hack for libcore
-#[no_mangle]
-#[doc(hidden)]
-#[deprecated]
-#[cfg(not(test))]
-pub unsafe extern "C" fn rust_deallocate(ptr: *mut u8, size: uint, align: uint) {
-    deallocate(ptr, size, align)
-}
-
 #[cfg(test)]
 mod bench {
     extern crate test;
@@ -184,11 +166,4 @@ fn alloc_owned_small(b: &mut Bencher) {
             box 10
         })
     }
-
-    #[bench]
-    fn alloc_owned_big(b: &mut Bencher) {
-        b.iter(|| {
-            box [10, ..1000]
-        })
-    }
 }
index b484b2c8128f13f7b903ace57837b8d3a55e3aef..bd7bab456ba012cb962336c9498d895459d7ccf9 100644 (file)
@@ -213,13 +213,6 @@ fn hash(&self, state: &mut S) {
     }
 }
 
-impl<S: Writer, T: Hash<S>> Hash<S> for ~[T] {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.as_slice().hash(state);
-    }
-}
-
 impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
     #[inline]
     fn hash(&self, state: &mut S) {
index 74e93284d2ac4ff67d6ee222eeac98a86f0896d5..887b0fb0b8abe22b51facc05e4721fc023c24d66 100644 (file)
@@ -276,6 +276,7 @@ mod tests {
     use str::Str;
     use string::String;
     use slice::{Vector, ImmutableVector};
+    use vec::Vec;
 
     use super::super::{Hash, Writer};
     use super::{SipState, hash, hash_with_keys};
@@ -376,8 +377,8 @@ fn to_hex_str(r: &[u8, ..8]) -> String {
             s
         }
 
-        fn result_bytes(h: u64) -> ~[u8] {
-            box [(h >> 0) as u8,
+        fn result_bytes(h: u64) -> Vec<u8> {
+            vec![(h >> 0) as u8,
               (h >> 8) as u8,
               (h >> 16) as u8,
               (h >> 24) as u8,
index 1bc563686933e5efa23a23d4407ad8b8c878f55c..865da9eff136a1a6527965bb427ae0dcf104b04a 100644 (file)
 
 use core::prelude::*;
 
-use alloc::heap::{allocate, deallocate};
 use core::cmp;
-use core::finally::try_finally;
 use core::mem::size_of;
-use core::mem::transmute;
 use core::mem;
 use core::ptr;
 use core::iter::{range_step, MultiplicativeIterator};
@@ -255,18 +252,18 @@ fn size_hint(&self) -> (uint, Option<uint>) {
 /// Generates even and odd permutations alternately.
 pub struct Permutations<T> {
     swaps: ElementSwaps,
-    v: ~[T],
+    v: Vec<T>,
 }
 
-impl<T: Clone> Iterator<~[T]> for Permutations<T> {
+impl<T: Clone> Iterator<Vec<T>> for Permutations<T> {
     #[inline]
-    fn next(&mut self) -> Option<~[T]> {
+    fn next(&mut self) -> Option<Vec<T>> {
         match self.swaps.next() {
             None => None,
             Some((0,0)) => Some(self.v.clone()),
             Some((a, b)) => {
                 let elt = self.v.clone();
-                self.v.swap(a, b);
+                self.v.as_mut_slice().swap(a, b);
                 Some(elt)
             }
         }
@@ -281,73 +278,20 @@ fn size_hint(&self) -> (uint, Option<uint>) {
 /// Extension methods for vector slices with cloneable elements
 pub trait CloneableVector<T> {
     /// Copy `self` into a new owned vector
-    fn to_owned(&self) -> ~[T];
+    fn to_owned(&self) -> Vec<T>;
 
     /// Convert `self` into an owned vector, not making a copy if possible.
-    fn into_owned(self) -> ~[T];
+    fn into_owned(self) -> Vec<T>;
 }
 
 /// Extension methods for vector slices
 impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
     /// Returns a copy of `v`.
     #[inline]
-    fn to_owned(&self) -> ~[T] {
-        use RawVec = core::raw::Vec;
-        use core::num::{CheckedAdd, CheckedMul};
-        use core::ptr;
-
-        let len = self.len();
-        let data_size = len.checked_mul(&mem::size_of::<T>());
-        let data_size = data_size.expect("overflow in to_owned()");
-        let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
-        let size = size.expect("overflow in to_owned()");
-
-        unsafe {
-            // this should pass the real required alignment
-            let ret = allocate(size, 8) as *mut RawVec<()>;
-
-            let a_size = mem::size_of::<T>();
-            let a_size = if a_size == 0 {1} else {a_size};
-            (*ret).fill = len * a_size;
-            (*ret).alloc = len * a_size;
-
-            // Be careful with the following loop. We want it to be optimized
-            // to a memcpy (or something similarly fast) when T is Copy. LLVM
-            // is easily confused, so any extra operations during the loop can
-            // prevent this optimization.
-            let mut i = 0;
-            let p = &mut (*ret).data as *mut _ as *mut T;
-            try_finally(
-                &mut i, (),
-                |i, ()| while *i < len {
-                    ptr::write(
-                        &mut(*p.offset(*i as int)),
-                        self.unsafe_ref(*i).clone());
-                    *i += 1;
-                },
-                |i| if *i < len {
-                    // we must be failing, clean up after ourselves
-                    for j in range(0, *i as int) {
-                        ptr::read(&*p.offset(j));
-                    }
-                    // FIXME: #13994 (should pass align and size here)
-                    deallocate(ret as *mut u8, 0, 8);
-                });
-            mem::transmute(ret)
-        }
-    }
+    fn to_owned(&self) -> Vec<T> { Vec::from_slice(*self) }
 
     #[inline(always)]
-    fn into_owned(self) -> ~[T] { self.to_owned() }
-}
-
-/// Extension methods for owned vectors
-impl<T: Clone> CloneableVector<T> for ~[T] {
-    #[inline]
-    fn to_owned(&self) -> ~[T] { self.clone() }
-
-    #[inline(always)]
-    fn into_owned(self) -> ~[T] { self }
+    fn into_owned(self) -> Vec<T> { self.to_owned() }
 }
 
 /// Extension methods for vectors containing `Clone` elements.
@@ -387,57 +331,6 @@ fn permutations(self) -> Permutations<T> {
 
 }
 
-/// Extension methods for owned vectors.
-pub trait OwnedVector<T> {
-    /// Creates a consuming iterator, that is, one that moves each
-    /// value out of the vector (from start to end). The vector cannot
-    /// be used after calling this.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let v = ~["a".to_string(), "b".to_string()];
-    /// for s in v.move_iter() {
-    ///   // s has type ~str, not &~str
-    ///   println!("{}", s);
-    /// }
-    /// ```
-    fn move_iter(self) -> MoveItems<T>;
-
-    /**
-     * Partitions the vector into two vectors `(A,B)`, where all
-     * elements of `A` satisfy `f` and all elements of `B` do not.
-     */
-    fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>);
-}
-
-impl<T> OwnedVector<T> for ~[T] {
-    #[inline]
-    fn move_iter(self) -> MoveItems<T> {
-        unsafe {
-            let iter = transmute(self.iter());
-            let ptr = transmute(self);
-            MoveItems { allocation: ptr, iter: iter }
-        }
-    }
-
-    #[inline]
-    fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
-        let mut lefts  = Vec::new();
-        let mut rights = Vec::new();
-
-        for elt in self.move_iter() {
-            if f(&elt) {
-                lefts.push(elt);
-            } else {
-                rights.push(elt);
-            }
-        }
-
-        (lefts, rights)
-    }
-}
-
 fn insertion_sort<T>(v: &mut [T], compare: |&T, &T| -> Ordering) {
     let len = v.len() as int;
     let buf_v = v.as_mut_ptr();
@@ -676,7 +569,7 @@ pub trait MutableVectorAllocating<'a, T> {
      * * start - The index into `src` to start copying from
      * * end - The index into `str` to stop copying from
      */
-    fn move_from(self, src: ~[T], start: uint, end: uint) -> uint;
+    fn move_from(self, src: Vec<T>, start: uint, end: uint) -> uint;
 }
 
 impl<'a,T> MutableVectorAllocating<'a, T> for &'a mut [T] {
@@ -686,7 +579,7 @@ fn sort_by(self, compare: |&T, &T| -> Ordering) {
     }
 
     #[inline]
-    fn move_from(self, mut src: ~[T], start: uint, end: uint) -> uint {
+    fn move_from(self, mut src: Vec<T>, start: uint, end: uint) -> uint {
         for (a, b) in self.mut_iter().zip(src.mut_slice(start, end).mut_iter()) {
             mem::swap(a, b);
         }
@@ -815,47 +708,6 @@ pub mod raw {
     pub use core::slice::raw::{shift_ptr, pop_ptr};
 }
 
-/// An iterator that moves out of a vector.
-pub struct MoveItems<T> {
-    allocation: *mut u8, // the block of memory allocated for the vector
-    iter: Items<'static, T>
-}
-
-impl<T> Iterator<T> for MoveItems<T> {
-    #[inline]
-    fn next(&mut self) -> Option<T> {
-        unsafe {
-            self.iter.next().map(|x| ptr::read(x))
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<T> DoubleEndedIterator<T> for MoveItems<T> {
-    #[inline]
-    fn next_back(&mut self) -> Option<T> {
-        unsafe {
-            self.iter.next_back().map(|x| ptr::read(x))
-        }
-    }
-}
-
-#[unsafe_destructor]
-impl<T> Drop for MoveItems<T> {
-    fn drop(&mut self) {
-        // destroy the remaining elements
-        for _x in *self {}
-        unsafe {
-            // FIXME: #13994 (should pass align and size here)
-            deallocate(self.allocation, 0, 8)
-        }
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use std::cell::Cell;
@@ -944,92 +796,92 @@ fn test_len_divzero() {
 
     #[test]
     fn test_get() {
-        let mut a = box [11];
-        assert_eq!(a.get(1), None);
-        a = box [11, 12];
-        assert_eq!(a.get(1).unwrap(), &12);
-        a = box [11, 12, 13];
-        assert_eq!(a.get(1).unwrap(), &12);
+        let mut a = vec![11];
+        assert_eq!(a.as_slice().get(1), None);
+        a = vec![11, 12];
+        assert_eq!(a.as_slice().get(1).unwrap(), &12);
+        a = vec![11, 12, 13];
+        assert_eq!(a.as_slice().get(1).unwrap(), &12);
     }
 
     #[test]
     fn test_head() {
-        let mut a = box [];
-        assert_eq!(a.head(), None);
-        a = box [11];
-        assert_eq!(a.head().unwrap(), &11);
-        a = box [11, 12];
-        assert_eq!(a.head().unwrap(), &11);
+        let mut a = vec![];
+        assert_eq!(a.as_slice().head(), None);
+        a = vec![11];
+        assert_eq!(a.as_slice().head().unwrap(), &11);
+        a = vec![11, 12];
+        assert_eq!(a.as_slice().head().unwrap(), &11);
     }
 
     #[test]
     fn test_tail() {
-        let mut a = box [11];
+        let mut a = vec![11];
         assert_eq!(a.tail(), &[]);
-        a = box [11, 12];
+        a = vec![11, 12];
         assert_eq!(a.tail(), &[12]);
     }
 
     #[test]
     #[should_fail]
     fn test_tail_empty() {
-        let a: ~[int] = box [];
+        let a: Vec<int> = vec![];
         a.tail();
     }
 
     #[test]
     fn test_tailn() {
-        let mut a = box [11, 12, 13];
+        let mut a = vec![11, 12, 13];
         assert_eq!(a.tailn(0), &[11, 12, 13]);
-        a = box [11, 12, 13];
+        a = vec![11, 12, 13];
         assert_eq!(a.tailn(2), &[13]);
     }
 
     #[test]
     #[should_fail]
     fn test_tailn_empty() {
-        let a: ~[int] = box [];
+        let a: Vec<int> = vec![];
         a.tailn(2);
     }
 
     #[test]
     fn test_init() {
-        let mut a = box [11];
+        let mut a = vec![11];
         assert_eq!(a.init(), &[]);
-        a = box [11, 12];
+        a = vec![11, 12];
         assert_eq!(a.init(), &[11]);
     }
 
     #[test]
     #[should_fail]
     fn test_init_empty() {
-        let a: ~[int] = box [];
+        let a: Vec<int> = vec![];
         a.init();
     }
 
     #[test]
     fn test_initn() {
-        let mut a = box [11, 12, 13];
-        assert_eq!(a.initn(0), &[11, 12, 13]);
-        a = box [11, 12, 13];
-        assert_eq!(a.initn(2), &[11]);
+        let mut a = vec![11, 12, 13];
+        assert_eq!(a.as_slice().initn(0), &[11, 12, 13]);
+        a = vec![11, 12, 13];
+        assert_eq!(a.as_slice().initn(2), &[11]);
     }
 
     #[test]
     #[should_fail]
     fn test_initn_empty() {
-        let a: ~[int] = box [];
-        a.initn(2);
+        let a: Vec<int> = vec![];
+        a.as_slice().initn(2);
     }
 
     #[test]
     fn test_last() {
-        let mut a = box [];
-        assert_eq!(a.last(), None);
-        a = box [11];
-        assert_eq!(a.last().unwrap(), &11);
-        a = box [11, 12];
-        assert_eq!(a.last().unwrap(), &12);
+        let mut a = vec![];
+        assert_eq!(a.as_slice().last(), None);
+        a = vec![11];
+        assert_eq!(a.as_slice().last().unwrap(), &11);
+        a = vec![11, 12];
+        assert_eq!(a.as_slice().last().unwrap(), &12);
     }
 
     #[test]
@@ -1038,6 +890,7 @@ fn test_slice() {
         let vec_fixed = [1, 2, 3, 4];
         let v_a = vec_fixed.slice(1u, vec_fixed.len()).to_owned();
         assert_eq!(v_a.len(), 3u);
+        let v_a = v_a.as_slice();
         assert_eq!(v_a[0], 2);
         assert_eq!(v_a[1], 3);
         assert_eq!(v_a[2], 4);
@@ -1046,13 +899,15 @@ fn test_slice() {
         let vec_stack = &[1, 2, 3];
         let v_b = vec_stack.slice(1u, 3u).to_owned();
         assert_eq!(v_b.len(), 2u);
+        let v_b = v_b.as_slice();
         assert_eq!(v_b[0], 2);
         assert_eq!(v_b[1], 3);
 
         // Test `Box<[T]>`
-        let vec_unique = box [1, 2, 3, 4, 5, 6];
+        let vec_unique = vec![1, 2, 3, 4, 5, 6];
         let v_d = vec_unique.slice(1u, 6u).to_owned();
         assert_eq!(v_d.len(), 5u);
+        let v_d = v_d.as_slice();
         assert_eq!(v_d[0], 2);
         assert_eq!(v_d[1], 3);
         assert_eq!(v_d[2], 4);
@@ -1295,15 +1150,15 @@ fn test_permutations() {
             let (min_size, max_opt) = it.size_hint();
             assert_eq!(min_size, 3*2);
             assert_eq!(max_opt.unwrap(), 3*2);
-            assert_eq!(it.next(), Some(box [1,2,3]));
-            assert_eq!(it.next(), Some(box [1,3,2]));
-            assert_eq!(it.next(), Some(box [3,1,2]));
+            assert_eq!(it.next(), Some(vec![1,2,3]));
+            assert_eq!(it.next(), Some(vec![1,3,2]));
+            assert_eq!(it.next(), Some(vec![3,1,2]));
             let (min_size, max_opt) = it.size_hint();
             assert_eq!(min_size, 3);
             assert_eq!(max_opt.unwrap(), 3);
-            assert_eq!(it.next(), Some(box [3,2,1]));
-            assert_eq!(it.next(), Some(box [2,3,1]));
-            assert_eq!(it.next(), Some(box [2,1,3]));
+            assert_eq!(it.next(), Some(vec![3,2,1]));
+            assert_eq!(it.next(), Some(vec![2,3,1]));
+            assert_eq!(it.next(), Some(vec![2,1,3]));
             assert_eq!(it.next(), None);
         }
         {
@@ -1378,11 +1233,11 @@ fn test_lexicographic_permutations_empty_and_short() {
     fn test_position_elem() {
         assert!([].position_elem(&1).is_none());
 
-        let v1 = box [1, 2, 3, 3, 2, 5];
-        assert_eq!(v1.position_elem(&1), Some(0u));
-        assert_eq!(v1.position_elem(&2), Some(1u));
-        assert_eq!(v1.position_elem(&5), Some(5u));
-        assert!(v1.position_elem(&4).is_none());
+        let v1 = vec![1, 2, 3, 3, 2, 5];
+        assert_eq!(v1.as_slice().position_elem(&1), Some(0u));
+        assert_eq!(v1.as_slice().position_elem(&2), Some(1u));
+        assert_eq!(v1.as_slice().position_elem(&5), Some(5u));
+        assert!(v1.as_slice().position_elem(&4).is_none());
     }
 
     #[test]
@@ -1432,14 +1287,14 @@ fn test_bsearch_elem() {
 
     #[test]
     fn test_reverse() {
-        let mut v: ~[int] = box [10, 20];
-        assert_eq!(v[0], 10);
-        assert_eq!(v[1], 20);
+        let mut v: Vec<int> = vec![10, 20];
+        assert_eq!(*v.get(0), 10);
+        assert_eq!(*v.get(1), 20);
         v.reverse();
-        assert_eq!(v[0], 20);
-        assert_eq!(v[1], 10);
+        assert_eq!(*v.get(0), 20);
+        assert_eq!(*v.get(1), 10);
 
-        let mut v3: ~[int] = box [];
+        let mut v3: Vec<int> = vec![];
         v3.reverse();
         assert!(v3.is_empty());
     }
@@ -1505,10 +1360,10 @@ fn test_sort_stability() {
 
     #[test]
     fn test_partition() {
-        assert_eq!((box []).partition(|x: &int| *x < 3), (vec![], vec![]));
-        assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
-        assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 2), (vec![1], vec![2, 3]));
-        assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
+        assert_eq!((vec![]).partition(|x: &int| *x < 3), (vec![], vec![]));
+        assert_eq!((vec![1, 2, 3]).partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
+        assert_eq!((vec![1, 2, 3]).partition(|x: &int| *x < 2), (vec![1], vec![2, 3]));
+        assert_eq!((vec![1, 2, 3]).partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
     }
 
     #[test]
@@ -1521,19 +1376,19 @@ fn test_partitioned() {
 
     #[test]
     fn test_concat() {
-        let v: [~[int], ..0] = [];
+        let v: [Vec<int>, ..0] = [];
         assert_eq!(v.concat_vec(), vec![]);
-        assert_eq!([box [1], box [2,3]].concat_vec(), vec![1, 2, 3]);
+        assert_eq!([vec![1], vec![2,3]].concat_vec(), vec![1, 2, 3]);
 
         assert_eq!([&[1], &[2,3]].concat_vec(), vec![1, 2, 3]);
     }
 
     #[test]
     fn test_connect() {
-        let v: [~[int], ..0] = [];
+        let v: [Vec<int>, ..0] = [];
         assert_eq!(v.connect_vec(&0), vec![]);
-        assert_eq!([box [1], box [2, 3]].connect_vec(&0), vec![1, 0, 2, 3]);
-        assert_eq!([box [1], box [2], box [3]].connect_vec(&0), vec![1, 0, 2, 0, 3]);
+        assert_eq!([vec![1], vec![2, 3]].connect_vec(&0), vec![1, 0, 2, 3]);
+        assert_eq!([vec![1], vec![2], vec![3]].connect_vec(&0), vec![1, 0, 2, 0, 3]);
 
         assert_eq!([&[1], &[2, 3]].connect_vec(&0), vec![1, 0, 2, 3]);
         assert_eq!([&[1], &[2], &[3]].connect_vec(&0), vec![1, 0, 2, 0, 3]);
@@ -1808,13 +1663,13 @@ fn test_mut_rev_iterator() {
 
     #[test]
     fn test_move_iterator() {
-        let xs = box [1u,2,3,4,5];
+        let xs = vec![1u,2,3,4,5];
         assert_eq!(xs.move_iter().fold(0, |a: uint, b: uint| 10*a + b), 12345);
     }
 
     #[test]
     fn test_move_rev_iterator() {
-        let xs = box [1u,2,3,4,5];
+        let xs = vec![1u,2,3,4,5];
         assert_eq!(xs.move_iter().rev().fold(0, |a: uint, b: uint| 10*a + b), 54321);
     }
 
@@ -1927,19 +1782,19 @@ fn test_chunksator_0() {
     #[test]
     fn test_move_from() {
         let mut a = [1,2,3,4,5];
-        let b = box [6,7,8];
+        let b = vec![6,7,8];
         assert_eq!(a.move_from(b, 0, 3), 3);
         assert!(a == [6,7,8,4,5]);
         let mut a = [7,2,8,1];
-        let b = box [3,1,4,1,5,9];
+        let b = vec![3,1,4,1,5,9];
         assert_eq!(a.move_from(b, 0, 6), 4);
         assert!(a == [3,1,4,1]);
         let mut a = [1,2,3,4];
-        let b = box [5,6,7,8,9,0];
+        let b = vec![5,6,7,8,9,0];
         assert_eq!(a.move_from(b, 2, 3), 1);
         assert!(a == [7,2,3,4]);
         let mut a = [1,2,3,4,5];
-        let b = box [5,6,7,8,9,0];
+        let b = vec![5,6,7,8,9,0];
         assert_eq!(a.mut_slice(2,4).move_from(b,1,6), 2);
         assert!(a == [1,2,6,7,5]);
     }
@@ -1972,11 +1827,11 @@ macro_rules! test_show_vec(
                 assert_eq!(format!("{}", x.as_slice()), x_str);
             })
         )
-        let empty: ~[int] = box [];
+        let empty: Vec<int> = vec![];
         test_show_vec!(empty, "[]".to_string());
-        test_show_vec!(box [1], "[1]".to_string());
-        test_show_vec!(box [1, 2, 3], "[1, 2, 3]".to_string());
-        test_show_vec!(box [box [], box [1u], box [1u, 1u]],
+        test_show_vec!(vec![1], "[1]".to_string());
+        test_show_vec!(vec![1, 2, 3], "[1, 2, 3]".to_string());
+        test_show_vec!(vec![vec![], vec![1u], vec![1u, 1u]],
                        "[[], [1], [1, 1]]".to_string());
 
         let empty_mut: &mut [int] = &mut[];
@@ -1997,7 +1852,6 @@ macro_rules! t (
         );
 
         t!(&[int]);
-        t!(~[int]);
         t!(Vec<int>);
     }
 
@@ -2392,13 +2246,6 @@ fn zero_1kb_set_memory(b: &mut Bencher) {
         });
     }
 
-    #[bench]
-    fn zero_1kb_fixed_repeat(b: &mut Bencher) {
-        b.iter(|| {
-            box [0u8, ..1024]
-        });
-    }
-
     #[bench]
     fn zero_1kb_loop_set(b: &mut Bencher) {
         b.iter(|| {
index 49d8775dd9cb649a97570ac2416828c7779b7e7d..83601be83dec0f194ae923a26edcd6aa54d968b0 100644 (file)
@@ -707,7 +707,7 @@ fn test_from_buf_len() {
         use str::StrAllocating;
 
         unsafe {
-            let a = ~[65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
+            let a = vec![65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
             let b = a.as_ptr();
             let c = from_buf_len(b, 3u);
             assert_eq!(c, "AAA".to_string());
@@ -1124,7 +1124,7 @@ fn half_a_million_letter_a() -> String {
         assert!(half_a_million_letter_a() ==
             unsafe {raw::slice_bytes(letters.as_slice(),
                                      0u,
-                                     500000)}.to_owned());
+                                     500000)}.to_string());
     }
 
     #[test]
@@ -1219,7 +1219,7 @@ fn test_slice() {
         assert_eq!("", data.slice(3, 3));
         assert_eq!("华", data.slice(30, 33));
 
-        fn a_million_letter_X() -> String {
+        fn a_million_letter_x() -> String {
             let mut i = 0;
             let mut rs = String::new();
             while i < 100000 {
@@ -1228,7 +1228,7 @@ fn a_million_letter_X() -> String {
             }
             rs
         }
-        fn half_a_million_letter_X() -> String {
+        fn half_a_million_letter_x() -> String {
             let mut i = 0;
             let mut rs = String::new();
             while i < 100000 {
@@ -1237,9 +1237,9 @@ fn half_a_million_letter_X() -> String {
             }
             rs
         }
-        let letters = a_million_letter_X();
-        assert!(half_a_million_letter_X() ==
-            letters.as_slice().slice(0u, 3u * 500000u).to_owned());
+        let letters = a_million_letter_x();
+        assert!(half_a_million_letter_x() ==
+            letters.as_slice().slice(0u, 3u * 500000u).to_string());
     }
 
     #[test]
@@ -1464,7 +1464,7 @@ fn test_is_utf16() {
     #[test]
     fn test_raw_from_c_str() {
         unsafe {
-            let a = box [65, 65, 65, 65, 65, 65, 65, 0];
+            let a = vec![65, 65, 65, 65, 65, 65, 65, 0];
             let b = a.as_ptr();
             let c = raw::from_c_str(b);
             assert_eq!(c, "AAAAAAA".to_string());
@@ -1682,7 +1682,7 @@ fn test_truncate_utf16_at_nul() {
     #[test]
     fn test_char_at() {
         let s = "ศไทย中华Việt Nam";
-        let v = box ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+        let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
         let mut pos = 0;
         for ch in v.iter() {
             assert!(s.char_at(pos) == *ch);
@@ -1693,7 +1693,7 @@ fn test_char_at() {
     #[test]
     fn test_char_at_reverse() {
         let s = "ศไทย中华Việt Nam";
-        let v = box ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+        let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
         let mut pos = s.len();
         for ch in v.iter().rev() {
             assert!(s.char_at_reverse(pos) == *ch);
@@ -1756,7 +1756,7 @@ fn test_char_range_at_reverse_underflow() {
     #[test]
     fn test_iterator() {
         let s = "ศไทย中华Việt Nam";
-        let v = box ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+        let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
 
         let mut pos = 0;
         let mut it = s.chars();
@@ -1771,7 +1771,7 @@ fn test_iterator() {
     #[test]
     fn test_rev_iterator() {
         let s = "ศไทย中华Việt Nam";
-        let v = box ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
+        let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
 
         let mut pos = 0;
         let mut it = s.chars().rev();
index dbef73efc479462b1539acf7ed8d47eb305648c8..acb7b2c27040fd384f0fe82d3d57d256f88ee39a 100644 (file)
@@ -13,7 +13,6 @@
 use core::prelude::*;
 
 use alloc::heap::{allocate, reallocate, deallocate};
-use RawVec = core::raw::Vec;
 use core::raw::Slice;
 use core::cmp::max;
 use core::default::Default;
@@ -25,7 +24,7 @@
 use core::uint;
 
 use {Collection, Mutable};
-use slice::{MutableOrdVector, OwnedVector, MutableVectorAllocating};
+use slice::{MutableOrdVector, MutableVectorAllocating, CloneableVector};
 use slice::{Items, MutItems};
 
 /// An owned, growable vector.
@@ -387,6 +386,11 @@ fn lt(&self, other: &Vec<T>) -> bool {
 
 impl<T: Eq> Eq for Vec<T> {}
 
+impl<T: PartialEq, V: Vector<T>> Equiv<V> for Vec<T> {
+    #[inline]
+    fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
+}
+
 impl<T: Ord> Ord for Vec<T> {
     #[inline]
     fn cmp(&self, other: &Vec<T>) -> Ordering {
@@ -401,6 +405,11 @@ fn len(&self) -> uint {
     }
 }
 
+impl<T: Clone> CloneableVector<T> for Vec<T> {
+    fn to_owned(&self) -> Vec<T> { self.clone() }
+    fn into_owned(self) -> Vec<T> { self }
+}
+
 // FIXME: #13996: need a way to mark the return value as `noalias`
 #[inline(never)]
 unsafe fn alloc_or_realloc<T>(ptr: *mut T, size: uint, old_size: uint) -> *mut T {
@@ -1511,52 +1520,6 @@ pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (Vec<T>, Vec<U>) {
     (ts, us)
 }
 
-/// Mechanism to convert from a `Vec<T>` to a `[T]`.
-///
-/// In a post-DST world this will be used to convert to any `Ptr<[T]>`.
-///
-/// This could be implemented on more types than just pointers to vectors, but
-/// the recommended approach for those types is to implement `FromIterator`.
-// FIXME(#12938): Update doc comment when DST lands
-pub trait FromVec<T> {
-    /// Convert a `Vec<T>` into the receiver type.
-    fn from_vec(v: Vec<T>) -> Self;
-}
-
-impl<T> FromVec<T> for ~[T] {
-    fn from_vec(mut v: Vec<T>) -> ~[T] {
-        let len = v.len();
-        let data_size = len.checked_mul(&mem::size_of::<T>());
-        let data_size = data_size.expect("overflow in from_vec()");
-        let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
-        let size = size.expect("overflow in from_vec()");
-
-        // In a post-DST world, we can attempt to reuse the Vec allocation by calling
-        // shrink_to_fit() on it. That may involve a reallocation+memcpy, but that's no
-        // different than what we're doing manually here.
-
-        let vp = v.as_mut_ptr();
-
-        unsafe {
-            let ret = allocate(size, 8) as *mut RawVec<()>;
-
-            let a_size = mem::size_of::<T>();
-            let a_size = if a_size == 0 {1} else {a_size};
-            (*ret).fill = len * a_size;
-            (*ret).alloc = len * a_size;
-
-            ptr::copy_nonoverlapping_memory(&mut (*ret).data as *mut _ as *mut u8,
-                                            vp as *u8, data_size);
-
-            // we've transferred ownership of the contents from v, but we can't drop it
-            // as it still needs to free its own allocation.
-            v.set_len(0);
-
-            mem::transmute(ret)
-        }
-    }
-}
-
 /// Unsafe operations
 pub mod raw {
     use super::Vec;
@@ -1580,8 +1543,7 @@ pub unsafe fn from_buf<T>(ptr: *T, elts: uint) -> Vec<T> {
 mod tests {
     use std::prelude::*;
     use std::mem::size_of;
-    use std::kinds::marker;
-    use super::{unzip, raw, FromVec, Vec};
+    use super::{unzip, raw, Vec};
 
     #[test]
     fn test_small_vec_struct() {
@@ -1830,39 +1792,13 @@ fn test_unsafe_ptrs() {
             assert_eq!(b, vec![1, 2, 3]);
 
             // Test on-heap copy-from-buf.
-            let c = box [1, 2, 3, 4, 5];
+            let c = vec![1, 2, 3, 4, 5];
             let ptr = c.as_ptr();
             let d = raw::from_buf(ptr, 5u);
             assert_eq!(d, vec![1, 2, 3, 4, 5]);
         }
     }
 
-    #[test]
-    fn test_from_vec() {
-        let a = vec![1u, 2, 3];
-        let b: ~[uint] = FromVec::from_vec(a);
-        assert_eq!(b.as_slice(), &[1u, 2, 3]);
-
-        let a = vec![];
-        let b: ~[u8] = FromVec::from_vec(a);
-        assert_eq!(b.as_slice(), &[]);
-
-        let a = vec!["one".to_string(), "two".to_string()];
-        let b: ~[String] = FromVec::from_vec(a);
-        assert_eq!(b.as_slice(), &["one".to_string(), "two".to_string()]);
-
-        struct Foo {
-            x: uint,
-            nocopy: marker::NoCopy
-        }
-
-        let a = vec![Foo{x: 42, nocopy: marker::NoCopy}, Foo{x: 84, nocopy: marker::NoCopy}];
-        let b: ~[Foo] = FromVec::from_vec(a);
-        assert_eq!(b.len(), 2);
-        assert_eq!(b[0].x, 42);
-        assert_eq!(b[1].x, 84);
-    }
-
     #[test]
     fn test_vec_truncate_drop() {
         static mut drops: uint = 0;
index eef133181e1298352407f9da53ecbba7ad93c006..7ab2ae307d465fbb476ec12b858336038d04311f 100644 (file)
@@ -385,6 +385,7 @@ fn deref_mut<'a>(&'a mut self) -> &'a mut T {
 #[cfg(test)]
 mod test {
     use super::*;
+    use mem::drop;
 
     #[test]
     fn smoketest_cell() {
@@ -412,6 +413,22 @@ fn cell_has_sensible_show() {
         assert!(format!("{}", x).as_slice().contains(x.get()));
     }
 
+    #[test]
+    fn ref_and_refmut_have_sensible_show() {
+        use str::StrSlice;
+        use realstd::str::Str;
+
+        let refcell = RefCell::new("foo");
+
+        let refcell_refmut = refcell.borrow_mut();
+        assert!(format!("{}", refcell_refmut).as_slice().contains("foo"));
+        drop(refcell_refmut);
+
+        let refcell_ref = refcell.borrow();
+        assert!(format!("{}", refcell_ref).as_slice().contains("foo"));
+        drop(refcell_ref);
+    }
+
     #[test]
     fn double_imm_borrow() {
         let x = RefCell::new(0);
index f7680e6f8479cdb11e42d8e199b713d233fecea3..e6c462c62d2979fd98757d508783b70da07f3e60 100644 (file)
@@ -159,7 +159,7 @@ impl Empty for int {}
 
         fn test_fn_a() -> f64 { 1.0 }
         fn test_fn_b<T: Empty>(x: T) -> T { x }
-        fn test_fn_c(_: int, _: f64, _: ~[int], _: int, _: int, _: int) {}
+        fn test_fn_c(_: int, _: f64, _: int, _: int, _: int) {}
 
         let _ = test_fn_a.clone();
         let _ = test_fn_b::<int>.clone();
index d4571eb3a43511ca61d4b1ca9dafa414addc6130..763ca843c11e97035262e4e3a9b5568a5ad9a2f9 100644 (file)
@@ -29,7 +29,7 @@
 #![allow(dead_code, missing_doc)]
 
 use fmt;
-use intrinsics;
+#[cfg(not(test))] use intrinsics;
 
 #[cold] #[inline(never)] // this is the slow path, always
 #[lang="fail_"]
index a8d458664b8667be62658a455dcc19bd56c6724d..053dbbe5da9d8c983aa4a81b3d76021697bfe05a 100644 (file)
 #![allow(unused_variable)]
 
 use any;
-use cell::Cell;
+use cell::{Cell, Ref, RefMut};
 use char::Char;
 use collections::Collection;
 use iter::{Iterator, range};
 use kinds::Copy;
 use mem;
 use option::{Option, Some, None};
+use ops::Deref;
 use result::{Ok, Err};
 use result;
 use slice::{Vector, ImmutableVector};
@@ -736,12 +737,6 @@ fn fmt(&self, f: &mut Formatter) -> Result {
     }
 }
 
-impl<T: Show> Show for ~[T] {
-    fn fmt(&self, f: &mut Formatter) -> Result {
-        secret_show(&self.as_slice(), f)
-    }
-}
-
 impl Show for () {
     fn fmt(&self, f: &mut Formatter) -> Result {
         f.pad("()")
@@ -759,5 +754,17 @@ fn fmt(&self, f: &mut Formatter) -> Result {
     }
 }
 
+impl<'b, T: Show> Show for Ref<'b, T> {
+    fn fmt(&self, f: &mut Formatter) -> Result {
+        (**self).fmt(f)
+    }
+}
+
+impl<'b, T: Show> Show for RefMut<'b, T> {
+    fn fmt(&self, f: &mut Formatter) -> Result {
+        (*(self.deref())).fmt(f)
+    }
+}
+
 // If you expected tests to be here, look instead at the run-pass/ifmt.rs test,
 // it's a lot easier than creating all of the rt::Piece structures here.
index 35c8afee4b6be8c129ec9dbb40348aae47c82026..d61416a68e0d0298b4d210314fd6f37790799a63 100644 (file)
@@ -100,7 +100,9 @@ pub trait TyVisitor {
 
     fn visit_char(&mut self) -> bool;
 
+    #[cfg(stage0)]
     fn visit_estr_box(&mut self) -> bool;
+    #[cfg(stage0)]
     fn visit_estr_uniq(&mut self) -> bool;
     fn visit_estr_slice(&mut self) -> bool;
     fn visit_estr_fixed(&mut self, n: uint, sz: uint, align: uint) -> bool;
@@ -110,7 +112,9 @@ pub trait TyVisitor {
     fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
 
+    #[cfg(stage0)]
     fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+    #[cfg(stage0)]
     fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
index 64c53b658eff12006d8b3d5e974a339fcf78a986..bb11ec5502e83ce991a7b00aa874fe3f899c71ec 100644 (file)
@@ -35,7 +35,7 @@ trait defined in this module. For loops can be viewed as a syntactical expansion
 translated to the `loop` below.
 
 ```rust
-let values = ~[1, 2, 3];
+let values = vec![1, 2, 3];
 
 // "Syntactical sugar" taking advantage of an iterator
 for &x in values.iter() {
@@ -378,7 +378,7 @@ fn flat_map<'r, B, U: Iterator<B>>(self, f: |A|: 'r -> U)
     ///     }
     ///     sum
     /// }
-    /// let x = ~[1,2,3,7,8,9];
+    /// let x = vec![1,2,3,7,8,9];
     /// assert_eq!(process(x.move_iter()), 1006);
     /// ```
     #[inline]
@@ -2425,7 +2425,7 @@ fn test_iterator_enumerate() {
 
     #[test]
     fn test_iterator_peekable() {
-        let xs = box [0u, 1, 2, 3, 4, 5];
+        let xs = vec![0u, 1, 2, 3, 4, 5];
         let mut it = xs.iter().map(|&x|x).peekable();
         assert_eq!(it.peek().unwrap(), &0);
         assert_eq!(it.next().unwrap(), 0);
@@ -2809,7 +2809,7 @@ fn test_double_ended_filter_map() {
     #[test]
     fn test_double_ended_chain() {
         let xs = [1, 2, 3, 4, 5];
-        let ys = box [7, 9, 11];
+        let ys = [7, 9, 11];
         let mut it = xs.iter().chain(ys.iter()).rev();
         assert_eq!(it.next().unwrap(), &11)
         assert_eq!(it.next().unwrap(), &9)
@@ -2826,7 +2826,7 @@ fn test_double_ended_chain() {
     fn test_rposition() {
         fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
         fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' }
-        let v = box [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+        let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
 
         assert_eq!(v.iter().rposition(f), Some(3u));
         assert!(v.iter().rposition(g).is_none());
@@ -2887,7 +2887,7 @@ fn test_double_ended_flat_map() {
     #[test]
     fn test_random_access_chain() {
         let xs = [1, 2, 3, 4, 5];
-        let ys = box [7, 9, 11];
+        let ys = [7, 9, 11];
         let mut it = xs.iter().chain(ys.iter());
         assert_eq!(it.idx(0).unwrap(), &1);
         assert_eq!(it.idx(5).unwrap(), &7);
@@ -3131,7 +3131,7 @@ fn test_min_max() {
     }
 
     #[test]
-    fn test_MinMaxResult() {
+    fn test_min_max_result() {
         let r: MinMaxResult<int> = NoElements;
         assert_eq!(r.into_option(), None)
 
index 5661c6683739b58ffb7b80c7d0a8218265dc7a1e..5c7b588a9c9a529ae44083cefc5298f2249dba73 100644 (file)
 pub mod tuple;
 pub mod fmt;
 
-// FIXME: this module should not exist. Once owned allocations are no longer a
-//        language type, this module can move outside to the owned allocation
-//        crate.
-mod should_not_exist;
-
 #[doc(hidden)]
 mod core {
     pub use failure;
index 45ccf657dbdd1251050a5e322b8a41f0f9ad2c6a..a71727c3f8ee2b87ee754d1d61927afd181a8419 100644 (file)
@@ -660,7 +660,7 @@ fn drop(&mut self) {
             }
         }
 
-        fn R(i: Rc<RefCell<int>>) -> R {
+        fn r(i: Rc<RefCell<int>>) -> R {
             R {
                 i: i
             }
@@ -673,7 +673,7 @@ fn realclone<T: ::realstd::clone::Clone>(t: &T) -> T {
 
         let i = Rc::new(RefCell::new(0));
         {
-            let x = R(realclone(&i));
+            let x = r(realclone(&i));
             let opt = Some(x);
             let _y = opt.unwrap();
         }
index b2776b78b1ce3bdcc5f62664f54cca133716dab0..c37c66f9862174ffe3f4fd29289cbc4f93fe2906 100644 (file)
@@ -503,7 +503,8 @@ fn lt(&self, other: &*mut T) -> bool { *self < *other }
 }
 
 #[cfg(test)]
-pub mod ptr_tests {
+#[allow(deprecated, experimental)]
+pub mod test {
     use super::*;
     use prelude::*;
 
@@ -512,6 +513,8 @@ pub mod ptr_tests {
     use libc;
     use realstd::str;
     use realstd::str::Str;
+    use realstd::vec::Vec;
+    use realstd::collections::Collection;
     use slice::{ImmutableVector, MutableVector};
 
     #[test]
@@ -534,20 +537,24 @@ struct Pair {
             assert_eq!(p.fst, 50);
             assert_eq!(p.snd, 60);
 
-            let v0 = box [32000u16, 32001u16, 32002u16];
-            let mut v1 = box [0u16, 0u16, 0u16];
+            let v0 = vec![32000u16, 32001u16, 32002u16];
+            let mut v1 = vec![0u16, 0u16, 0u16];
 
             copy_memory(v1.as_mut_ptr().offset(1),
                         v0.as_ptr().offset(1), 1);
-            assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16));
+            assert!((*v1.get(0) == 0u16 &&
+                     *v1.get(1) == 32001u16 &&
+                     *v1.get(2) == 0u16));
             copy_memory(v1.as_mut_ptr(),
                         v0.as_ptr().offset(2), 1);
-            assert!((v1[0] == 32002u16 && v1[1] == 32001u16 &&
-                     v1[2] == 0u16));
+            assert!((*v1.get(0) == 32002u16 &&
+                     *v1.get(1) == 32001u16 &&
+                     *v1.get(2) == 0u16));
             copy_memory(v1.as_mut_ptr().offset(2),
                         v0.as_ptr(), 1u);
-            assert!((v1[0] == 32002u16 && v1[1] == 32001u16 &&
-                     v1[2] == 32000u16));
+            assert!((*v1.get(0) == 32002u16 &&
+                     *v1.get(1) == 32001u16 &&
+                     *v1.get(2) == 32000u16));
         }
     }
 
@@ -569,7 +576,7 @@ fn test_buf_len() {
         "hello".with_c_str(|p0| {
             "there".with_c_str(|p1| {
                 "thing".with_c_str(|p2| {
-                    let v = box [p0, p1, p2, null()];
+                    let v = vec![p0, p1, p2, null()];
                     unsafe {
                         assert_eq!(buf_len(v.as_ptr()), 3u);
                     }
@@ -617,7 +624,7 @@ fn test_to_option() {
     #[test]
     fn test_ptr_addition() {
         unsafe {
-            let xs = box [5, ..16];
+            let xs = Vec::from_elem(16, 5);
             let mut ptr = xs.as_ptr();
             let end = ptr.offset(16);
 
@@ -626,7 +633,7 @@ fn test_ptr_addition() {
                 ptr = ptr.offset(1);
             }
 
-            let mut xs_mut = xs.clone();
+            let mut xs_mut = xs;
             let mut m_ptr = xs_mut.as_mut_ptr();
             let m_end = m_ptr.offset(16);
 
@@ -635,14 +642,14 @@ fn test_ptr_addition() {
                 m_ptr = m_ptr.offset(1);
             }
 
-            assert_eq!(xs_mut, box [10, ..16]);
+            assert!(xs_mut == Vec::from_elem(16, 10));
         }
     }
 
     #[test]
     fn test_ptr_subtraction() {
         unsafe {
-            let xs = box [0,1,2,3,4,5,6,7,8,9];
+            let xs = vec![0,1,2,3,4,5,6,7,8,9];
             let mut idx = 9i8;
             let ptr = xs.as_ptr();
 
@@ -651,7 +658,7 @@ fn test_ptr_subtraction() {
                 idx = idx - 1i8;
             }
 
-            let mut xs_mut = xs.clone();
+            let mut xs_mut = xs;
             let m_start = xs_mut.as_mut_ptr();
             let mut m_ptr = m_start.offset(9);
 
@@ -660,7 +667,7 @@ fn test_ptr_subtraction() {
                 m_ptr = m_ptr.offset(-1);
             }
 
-            assert_eq!(xs_mut, box [0,2,4,6,8,10,12,14,16,18]);
+            assert!(xs_mut == vec![0,2,4,6,8,10,12,14,16,18]);
         }
     }
 
@@ -670,10 +677,10 @@ fn test_ptr_array_each_with_len() {
             let one = "oneOne".to_c_str();
             let two = "twoTwo".to_c_str();
             let three = "threeThree".to_c_str();
-            let arr = box [
+            let arr = vec![
                 one.with_ref(|buf| buf),
                 two.with_ref(|buf| buf),
-                three.with_ref(|buf| buf),
+                three.with_ref(|buf| buf)
             ];
             let expected_arr = [
                 one, two, three
@@ -700,12 +707,12 @@ fn test_ptr_array_each() {
             let one = "oneOne".to_c_str();
             let two = "twoTwo".to_c_str();
             let three = "threeThree".to_c_str();
-            let arr = box [
+            let arr = vec![
                 one.with_ref(|buf| buf),
                 two.with_ref(|buf| buf),
                 three.with_ref(|buf| buf),
                 // fake a null terminator
-                null(),
+                null()
             ];
             let expected_arr = [
                 one, two, three
index 56db4ee8059fab8596cda3a784f6e1489e8f6dae..0a2a756c6b1c24739813d3dfdfb3d087617b6547 100644 (file)
@@ -29,16 +29,6 @@ pub struct Box<T> {
     pub data: T,
 }
 
-/// The representation of a Rust vector
-pub struct Vec<T> {
-    pub fill: uint,
-    pub alloc: uint,
-    pub data: T,
-}
-
-/// The representation of a Rust string
-pub type String = Vec<u8>;
-
 /// The representation of a Rust slice
 pub struct Slice<T> {
     pub data: *T,
@@ -79,7 +69,6 @@ fn repr(&self) -> T { unsafe { mem::transmute_copy(self) } }
 
 impl<'a, T> Repr<Slice<T>> for &'a [T] {}
 impl<'a> Repr<Slice<u8>> for &'a str {}
-impl<T> Repr<*Vec<T>> for ~[T] {}
 
 #[cfg(test)]
 mod tests {
index 585373ec70ca560cea9de2e4b4d2b953a8ca29b4..d579d04489240abed234aaa410fc6d8f2948bc4e 100644 (file)
@@ -266,38 +266,19 @@ fn ne(&self, other: & &'a [T]) -> bool {
         }
     }
 
-    impl<T:PartialEq> PartialEq for ~[T] {
-        #[inline]
-        fn eq(&self, other: &~[T]) -> bool { self.as_slice() == *other }
-        #[inline]
-        fn ne(&self, other: &~[T]) -> bool { !self.eq(other) }
-    }
-
     impl<'a,T:Eq> Eq for &'a [T] {}
 
-    impl<T:Eq> Eq for ~[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:PartialEq, V: Vector<T>> Equiv<V> for ~[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())
         }
     }
 
-    impl<T: Ord> Ord for ~[T] {
-        #[inline]
-        fn cmp(&self, other: &~[T]) -> Ordering { self.as_slice().cmp(&other.as_slice()) }
-    }
-
     impl<'a, T: PartialOrd> PartialOrd for &'a [T] {
         fn lt(&self, other: & &'a [T]) -> bool {
             order::lt(self.iter(), other.iter())
@@ -315,17 +296,6 @@ fn gt(&self, other: & &'a [T]) -> bool {
             order::gt(self.iter(), other.iter())
         }
     }
-
-    impl<T: PartialOrd> PartialOrd for ~[T] {
-        #[inline]
-        fn lt(&self, other: &~[T]) -> bool { self.as_slice() < other.as_slice() }
-        #[inline]
-        fn le(&self, other: &~[T]) -> bool { self.as_slice() <= other.as_slice() }
-        #[inline]
-        fn ge(&self, other: &~[T]) -> bool { self.as_slice() >= other.as_slice() }
-        #[inline]
-        fn gt(&self, other: &~[T]) -> bool { self.as_slice() > other.as_slice() }
-    }
 }
 
 #[cfg(test)]
@@ -342,11 +312,6 @@ impl<'a,T> Vector<T> for &'a [T] {
     fn as_slice<'a>(&'a self) -> &'a [T] { *self }
 }
 
-impl<T> Vector<T> for ~[T] {
-    #[inline(always)]
-    fn as_slice<'a>(&'a self) -> &'a [T] { let v: &'a [T] = *self; v }
-}
-
 impl<'a, T> Collection for &'a [T] {
     /// Returns the length of a vector
     #[inline]
@@ -355,14 +320,6 @@ fn len(&self) -> uint {
     }
 }
 
-impl<T> Collection for ~[T] {
-    /// Returns the length of a vector
-    #[inline]
-    fn len(&self) -> uint {
-        self.as_slice().len()
-    }
-}
-
 /// Extension methods for vectors
 pub trait ImmutableVector<'a, T> {
     /**
@@ -927,7 +884,7 @@ pub trait MutableVector<'a, T> {
     /// # Example
     ///
     /// ```rust
-    /// let mut v = ~["foo".to_string(), "bar".to_string(), "baz".to_string()];
+    /// let mut v = ["foo".to_string(), "bar".to_string(), "baz".to_string()];
     ///
     /// unsafe {
     ///     // `"baz".to_string()` is deallocated.
@@ -1455,7 +1412,3 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
 impl<'a, T> Default for &'a [T] {
     fn default() -> &'a [T] { &[] }
 }
-
-impl<T> Default for ~[T] {
-    fn default() -> ~[T] { ~[] }
-}
index 997d3427122e8daf373b2b6660d231b70147c850..3a12aec39a18718c8537268e86b578afcb12fc59 100644 (file)
@@ -192,15 +192,14 @@ fn visit_char(&mut self) -> bool {
         true
     }
 
+    #[cfg(stage0)]
     fn visit_estr_box(&mut self) -> bool {
         true
     }
 
+    #[cfg(stage0)]
     fn visit_estr_uniq(&mut self) -> bool {
-        self.align_to::<~str>();
-        if ! self.inner.visit_estr_uniq() { return false; }
-        self.bump_past::<~str>();
-        true
+        false
     }
 
     fn visit_estr_slice(&mut self) -> bool {
@@ -247,15 +246,14 @@ fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         true
     }
 
+    #[cfg(stage0)]
     fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool {
         true
     }
 
-    fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<~[u8]>();
-        if ! self.inner.visit_evec_uniq(mtbl, inner) { return false; }
-        self.bump_past::<~[u8]>();
-        true
+    #[cfg(stage0)]
+    fn visit_evec_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool {
+        false
     }
 
     fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
index e6cc9785b44e72b4576b65028acd769aaaf85e94..86b71eb5b8d692610bd0b8048ac881ccd0040509 100644 (file)
@@ -203,10 +203,6 @@ pub fn write_vec_range(&mut self, ptr: *(), len: uint, inner: *TyDesc) -> bool {
         true
     }
 
-    pub fn write_unboxed_vec_repr(&mut self, _: uint, v: &raw::Vec<()>, inner: *TyDesc) -> bool {
-        self.write_vec_range(&v.data, v.fill, inner)
-    }
-
     fn write_escaped_char(&mut self, ch: char, is_str: bool) -> bool {
         try!(self, match ch {
             '\t' => self.writer.write("\\t".as_bytes()),
@@ -271,15 +267,14 @@ fn visit_char(&mut self) -> bool {
         })
     }
 
+    #[cfg(stage0)]
     fn visit_estr_box(&mut self) -> bool {
-        true
+        false
     }
 
+    #[cfg(stage0)]
     fn visit_estr_uniq(&mut self) -> bool {
-        self.get::<~str>(|this, s| {
-            try!(this, this.writer.write(['~' as u8]));
-            this.write_escaped_slice(*s)
-        })
+        false
     }
 
     fn visit_estr_slice(&mut self) -> bool {
@@ -323,19 +318,14 @@ fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         })
     }
 
-    fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.get::<&raw::Box<raw::Vec<()>>>(|this, b| {
-            try!(this, this.writer.write(['@' as u8]));
-            this.write_mut_qualifier(mtbl);
-            this.write_unboxed_vec_repr(mtbl, &b.data, inner)
-        })
+    #[cfg(stage0)]
+    fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool {
+        true
     }
 
-    fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.get::<&raw::Vec<()>>(|this, b| {
-            try!(this, this.writer.write("box ".as_bytes()));
-            this.write_unboxed_vec_repr(mtbl, *b, inner)
-        })
+    #[cfg(stage0)]
+    fn visit_evec_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool {
+        true
     }
 
     fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
index 8d8fe8ffe8cfe404c10aa577d9cd0f4207bc3cc3..955f697dce3bee0547853baa6f029a6853f4b205 100644 (file)
@@ -26,7 +26,6 @@
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/")]
 #![feature(phase)]
-#![deny(deprecated_owned_vector)]
 
 #[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
 #[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
@@ -114,7 +113,6 @@ mod tests {
     use std::rand::Rng;
 
     #[test]
-    #[allow(deprecated_owned_vector)]
     fn test_flate_round_trip() {
         let mut r = rand::task_rng();
         let mut words = vec!();
index 694fe7d0f48b08fa3e3fb9097f443c67e2379b50..3949bde3d52f7a6992575e5afc914ca31bf5bfa0 100644 (file)
@@ -47,7 +47,6 @@ fn main() {
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/")]
 
-#![deny(deprecated_owned_vector)]
 #![feature(plugin_registrar, managed_boxes)]
 
 extern crate syntax;
index eb9c86f00147980ba5f65ee8d420c21505575652..db6d940a7200e2a3d4022d54dfc2918f4b7692f8 100644 (file)
@@ -88,7 +88,6 @@
        html_playground_url = "http://play.rust-lang.org/")]
 #![feature(globs, phase)]
 #![deny(missing_doc)]
-#![deny(deprecated_owned_vector)]
 
 #[cfg(test)] extern crate debug;
 #[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
index 6d39a332ad9bd5a3549c7475a9dafa4d0aeb64b8..a2c2706b4c2f779585d55b1af8b1ecc1742431d2 100644 (file)
@@ -31,7 +31,6 @@
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/",
        html_playground_url = "http://play.rust-lang.org/")]
-#![deny(deprecated_owned_vector)]
 
 use std::cell::Cell;
 use std::{cmp, os, path};
index 3015b6f12ccd1795047a1024a0d9158ebcf36b38..a34791f470eaf9473a1a8dc0dc0a92e7948c4489 100644 (file)
 // of the contents of `Vec<T>`, since we anticipate that to be a
 // frequent way to dynamically construct a vector.
 
-/// MaybeOwnedVector<'a,T> abstracts over `Vec<T>`, `~[T]`, `&'a [T]`.
+/// MaybeOwnedVector<'a,T> abstracts over `Vec<T>`, `&'a [T]`.
 ///
 /// Some clients will have a pre-allocated vector ready to hand off in
 /// a slice; others will want to create the set on the fly and hand
-/// off ownership, via either `Growable` or `FixedLen` depending on
-/// which kind of vector they have constructed.  (The `FixedLen`
-/// variant is provided for interoperability with `std::slice` methods
-/// that return `~[T]`.)
+/// off ownership, via `Growable`.
 pub enum MaybeOwnedVector<'a,T> {
     Growable(Vec<T>),
-    FixedLen(~[T]),
     Borrowed(&'a [T]),
 }
 
@@ -51,11 +47,6 @@ impl<'a,T> IntoMaybeOwnedVector<'a,T> for Vec<T> {
     fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Growable(self) }
 }
 
-impl<'a,T> IntoMaybeOwnedVector<'a,T> for ~[T] {
-    #[inline]
-    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { FixedLen(self) }
-}
-
 impl<'a,T> IntoMaybeOwnedVector<'a,T> for &'a [T] {
     #[inline]
     fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Borrowed(self) }
@@ -65,7 +56,6 @@ impl<'a,T> MaybeOwnedVector<'a,T> {
     pub fn iter(&'a self) -> slice::Items<'a,T> {
         match self {
             &Growable(ref v) => v.iter(),
-            &FixedLen(ref v) => v.iter(),
             &Borrowed(ref v) => v.iter(),
         }
     }
@@ -84,7 +74,6 @@ impl<'b,T> slice::Vector<T> for MaybeOwnedVector<'b,T> {
     fn as_slice<'a>(&'a self) -> &'a [T] {
         match self {
             &Growable(ref v) => v.as_slice(),
-            &FixedLen(ref v) => v.as_slice(),
             &Borrowed(ref v) => v.as_slice(),
         }
     }
@@ -106,15 +95,14 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 impl<'a,T:Clone> CloneableVector<T> for MaybeOwnedVector<'a,T> {
     /// Returns a copy of `self`.
-    fn to_owned(&self) -> ~[T] {
+    fn to_owned(&self) -> Vec<T> {
         self.as_slice().to_owned()
     }
 
     /// Convert `self` into an owned slice, not making a copy if possible.
-    fn into_owned(self) -> ~[T] {
+    fn into_owned(self) -> Vec<T> {
         match self {
             Growable(v) => v.as_slice().to_owned(),
-            FixedLen(v) => v,
             Borrowed(v) => v.to_owned(),
         }
     }
@@ -125,7 +113,6 @@ impl<'a,T:Clone> MaybeOwnedVector<'a,T> {
     pub fn into_vec(self) -> Vec<T> {
         match self {
             Growable(v) => v,
-            FixedLen(v) => Vec::from_slice(v.as_slice()),
             Borrowed(v) => Vec::from_slice(v),
         }
     }
index 9071656f21334c896c60c0891977cf0f8196047a..e6915385a42d58f0d48bd7c934a15e490b15facf 100644 (file)
@@ -191,9 +191,9 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
 type Registers = [uint, ..22];
 
 #[cfg(windows, target_arch = "x86_64")]
-fn new_regs() -> Box<Registers> { box [0, .. 34] }
+fn new_regs() -> Box<Registers> { box() ([0, .. 34]) }
 #[cfg(not(windows), target_arch = "x86_64")]
-fn new_regs() -> Box<Registers> { box {let v = [0, .. 22]; v} }
+fn new_regs() -> Box<Registers> { box() ([0, .. 22]) }
 
 #[cfg(target_arch = "x86_64")]
 fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
index 9748dfbae33f0dc8f744797f43e695cea15f4068..e8de2b9bd9335cc99621b3d45cf147ac2cced253 100644 (file)
 // NB this does *not* include globs, please keep it that way.
 #![feature(macro_rules, phase)]
 #![allow(visible_private_types)]
-#![deny(deprecated_owned_vector)]
 
 #[cfg(test)] #[phase(plugin, link)] extern crate log;
 #[cfg(test)] extern crate rustuv;
index 54bc2802b09ac364cb92ab2b6f42d3dcc44abf62..b181b0ca8c977ae13e80c25a106de44d17d102ec 100644 (file)
@@ -43,8 +43,6 @@ fn main() {
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/")]
-
-#![deny(deprecated_owned_vector)]
 #![feature(plugin_registrar, managed_boxes)]
 
 extern crate syntax;
index 19f55c59491d814fc52658408063ee3c2cd7df24..2ecfef35308832b7d960e5e7a1bef52f81d889e7 100644 (file)
@@ -115,7 +115,7 @@ fn main() {
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(macro_rules)]
-#![deny(missing_doc, deprecated_owned_vector)]
+#![deny(missing_doc)]
 
 use std::fmt;
 use std::io::LineBufferedWriter;
index 709882c87cedb970b3be3f693517592507fefd77..27ccc528c940db36a84550f2f66257ea1b1bd8a4 100644 (file)
@@ -53,8 +53,6 @@
        html_root_url = "http://doc.rust-lang.org/",
        html_playground_url = "http://play.rust-lang.org/")]
 
-#![deny(deprecated_owned_vector)]
-
 extern crate rand;
 
 pub use bigint::{BigInt, BigUint};
index 61e62a0d1053e960bd905310144fb9fbfe8bbe7c..61b133c4e68abef23ecb275231bb1d1f1cc0863d 100644 (file)
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(macro_rules, phase)]
-#![deny(missing_doc, deprecated_owned_vector)]
+#![deny(missing_doc)]
 
 #[cfg(test)]
 extern crate stdtest = "test";
index 186db839e33d861e6f0f65c76f164de83ae45dec..3326b4e8304cec3246741b26056a2933bbd5fc3c 100644 (file)
@@ -172,7 +172,8 @@ macro_rules! debugging_opts(
         LTO,
         AST_JSON,
         AST_JSON_NOEXPAND,
-        LS
+        LS,
+        SAVE_ANALYSIS
     ]
     0
 )
@@ -206,7 +207,9 @@ pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
      ("lto", "Perform LLVM link-time optimizations", LTO),
      ("ast-json", "Print the AST as JSON and halt", AST_JSON),
      ("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND),
-     ("ls", "List the symbols defined by a library crate", LS))
+     ("ls", "List the symbols defined by a library crate", LS),
+     ("save-analysis", "Write syntax and type analysis information \
+                        in addition to normal output", SAVE_ANALYSIS))
 }
 
 /// Declare a macro that will define all CodegenOptions fields and parsers all
index d703ece307ffb7e412dfabe4773f2b2acc681cf5..880c1d6d5104d5290d015b440d874f52719f20c8 100644 (file)
@@ -87,6 +87,7 @@ pub fn compile_input(sess: Session,
         if stop_after_phase_2(&sess) { return; }
 
         let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
+        phase_save_analysis(&analysis.ty_cx.sess, &expanded_crate, &analysis, outdir);
         if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
         let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
                                                      analysis, &outputs);
@@ -370,6 +371,17 @@ pub fn phase_3_run_analysis_passes(sess: Session,
     }
 }
 
+pub fn phase_save_analysis(sess: &Session,
+                           krate: &ast::Crate,
+                           analysis: &CrateAnalysis,
+                           odir: &Option<Path>) {
+    if (sess.opts.debugging_opts & config::SAVE_ANALYSIS) == 0 {
+        return;
+    }
+    time(sess.time_passes(), "save analysis", krate, |krate|
+         middle::save::process_crate(sess, krate, analysis, odir));
+}
+
 pub struct CrateTranslation {
     pub context: ContextRef,
     pub module: ModuleRef,
index 59f53986af9fc8662cb1e25ed3942190d5408bd0..b6205d8d54e6799c474195fb8b2733eb39dd8c78 100644 (file)
@@ -37,7 +37,7 @@
 
 pub fn main_args(args: &[String]) -> int {
     let owned_args = args.to_owned();
-    monitor(proc() run_compiler(owned_args));
+    monitor(proc() run_compiler(owned_args.as_slice()));
     0
 }
 
index 773b9e6e0aac4022055e64b6cfea8afa95b38009..3efff5eac9e4d92ca0942997b533dc11f51b7a5d 100644 (file)
@@ -28,6 +28,7 @@
 use std::os;
 use std::cell::{Cell, RefCell};
 
+
 pub struct Session {
     pub targ_cfg: config::Config,
     pub opts: config::Options,
index 297d55edec8407430a9856675c82c9f60c5f7964..f79aaa40d213b98f77014a15fcb693702a616677 100644 (file)
@@ -84,6 +84,7 @@ pub mod middle {
     pub mod expr_use_visitor;
     pub mod dependency_format;
     pub mod weak_lang_items;
+    pub mod save;
 }
 
 pub mod front {
index 75445a317ecfb6c34fc41b2c8e7a1c5576528363..ac9cec84715264e1f483bedce9a22342f2525054 100644 (file)
@@ -1809,6 +1809,7 @@ pub fn LLVMRustArchiveReadSection(AR: ArchiveRef, name: *c_char,
         pub fn LLVMRustDestroyArchive(AR: ArchiveRef);
 
         pub fn LLVMRustSetDLLExportStorageClass(V: ValueRef);
+        pub fn LLVMVersionMajor() -> c_int;
         pub fn LLVMVersionMinor() -> c_int;
 
         pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
index b8db8e230b074c589e7ff646fcd7bcf394a6ee2d..bc5fad7f9343a871ea2d0f7b2f03db230c6b8a91 100644 (file)
@@ -418,10 +418,10 @@ fn walk_expr(&mut self,
                 self.walk_expr(&*cond, in_out, loop_scopes);
 
                 let mut then_bits = in_out.to_owned();
-                self.walk_block(&*then, then_bits, loop_scopes);
+                self.walk_block(&*then, then_bits.as_mut_slice(), loop_scopes);
 
                 self.walk_opt_expr(els, in_out, loop_scopes);
-                join_bits(&self.dfcx.oper, then_bits, in_out);
+                join_bits(&self.dfcx.oper, then_bits.as_slice(), in_out);
             }
 
             ast::ExprWhile(cond, blk) => {
@@ -444,8 +444,8 @@ fn walk_expr(&mut self,
                     loop_id: expr.id,
                     break_bits: Vec::from_slice(in_out)
                 });
-                self.walk_block(&*blk, body_bits, loop_scopes);
-                self.add_to_entry_set(expr.id, body_bits);
+                self.walk_block(&*blk, body_bits.as_mut_slice(), loop_scopes);
+                self.add_to_entry_set(expr.id, body_bits.as_slice());
                 let new_loop_scope = loop_scopes.pop().unwrap();
                 copy_bits(new_loop_scope.break_bits.as_slice(), in_out);
             }
@@ -468,8 +468,8 @@ fn walk_expr(&mut self,
                     loop_id: expr.id,
                     break_bits: Vec::from_slice(in_out)
                 });
-                self.walk_block(&**blk, body_bits, loop_scopes);
-                self.add_to_entry_set(expr.id, body_bits);
+                self.walk_block(&**blk, body_bits.as_mut_slice(), loop_scopes);
+                self.add_to_entry_set(expr.id, body_bits.as_slice());
 
                 let new_loop_scope = loop_scopes.pop().unwrap();
                 assert_eq!(new_loop_scope.loop_id, expr.id);
@@ -499,16 +499,17 @@ fn walk_expr(&mut self,
 
                 for arm in arms.iter() {
                     // in_out reflects the discr and all guards to date
-                    self.walk_opt_expr(arm.guard, guards, loop_scopes);
+                    self.walk_opt_expr(arm.guard, guards.as_mut_slice(),
+                                       loop_scopes);
 
                     // determine the bits for the body and then union
                     // them into `in_out`, which reflects all bodies to date
                     let mut body = guards.to_owned();
                     self.walk_pat_alternatives(arm.pats.as_slice(),
-                                               body,
+                                               body.as_mut_slice(),
                                                loop_scopes);
-                    self.walk_expr(&*arm.body, body, loop_scopes);
-                    join_bits(&self.dfcx.oper, body, in_out);
+                    self.walk_expr(&*arm.body, body.as_mut_slice(), loop_scopes);
+                    join_bits(&self.dfcx.oper, body.as_slice(), in_out);
                 }
             }
 
@@ -578,7 +579,7 @@ fn walk_expr(&mut self,
                 self.walk_expr(&**l, in_out, loop_scopes);
                 let temp = in_out.to_owned();
                 self.walk_expr(&**r, in_out, loop_scopes);
-                join_bits(&self.dfcx.oper, temp, in_out);
+                join_bits(&self.dfcx.oper, temp.as_slice(), in_out);
             }
 
             ast::ExprIndex(l, r) |
@@ -739,8 +740,8 @@ fn walk_pat_alternatives(&mut self,
         let initial_state = in_out.to_owned();
         for &pat in pats.iter() {
             let mut temp = initial_state.clone();
-            self.walk_pat(pat, temp, loop_scopes);
-            join_bits(&self.dfcx.oper, temp, in_out);
+            self.walk_pat(pat, temp.as_mut_slice(), loop_scopes);
+            join_bits(&self.dfcx.oper, temp.as_slice(), in_out);
         }
     }
 
index 3cf7602491ae0be8cae618259bf55e680d5b472f..b3b690c804d231282dff3eaebcf594adeaa1d52c 100644 (file)
@@ -121,8 +121,6 @@ pub enum Lint {
     UnusedMustUse,
     UnusedResult,
 
-    DeprecatedOwnedVector,
-
     Warnings,
 
     RawPointerDeriving,
@@ -433,13 +431,6 @@ pub enum LintSource {
         default: Allow,
     }),
 
-    ("deprecated_owned_vector",
-     LintSpec {
-        lint: DeprecatedOwnedVector,
-        desc: "use of a `~[T]` vector",
-        default: Allow,
-    }),
-
     ("raw_pointer_deriving",
      LintSpec {
         lint: RawPointerDeriving,
@@ -1235,20 +1226,6 @@ fn check_unused_result(cx: &Context, s: &ast::Stmt) {
     }
 }
 
-fn check_deprecated_owned_vector(cx: &Context, e: &ast::Expr) {
-    let t = ty::expr_ty(cx.tcx, e);
-    match ty::get(t).sty {
-        ty::ty_uniq(t) => match ty::get(t).sty {
-            ty::ty_vec(_, None) => {
-                cx.span_lint(DeprecatedOwnedVector, e.span,
-                             "use of deprecated `~[]` vector; replaced by `std::vec::Vec`")
-            }
-            _ => {}
-        },
-        _ => {}
-    }
-}
-
 fn check_item_non_camel_case_types(cx: &Context, it: &ast::Item) {
     fn is_camel_case(ident: ast::Ident) -> bool {
         let ident = token::get_ident(ident);
@@ -1861,7 +1838,6 @@ fn visit_expr(&mut self, e: &ast::Expr, _: ()) {
 
         check_type_limits(self, e);
         check_unused_casts(self, e);
-        check_deprecated_owned_vector(self, e);
 
         visit::walk_expr(self, e, ());
     }
index d1c7baf9f177d08028e4e4bd6ec22f13db5857fd..7fc31c974e939788a020438e0ff4431609990f1b 100644 (file)
@@ -3812,9 +3812,10 @@ fn resolve_function(&mut self,
                 }
                 Some(declaration) => {
                     for argument in declaration.inputs.iter() {
+                        let mut bindings_list = HashMap::new();
                         this.resolve_pattern(&*argument.pat,
                                              ArgumentIrrefutableMode,
-                                             None);
+                                             &mut bindings_list);
 
                         this.resolve_type(&*argument.ty);
 
@@ -4045,7 +4046,10 @@ fn resolve_local(&mut self, local: &Local) {
         }
 
         // Resolve the pattern.
-        self.resolve_pattern(&*local.pat, LocalIrrefutableMode, None);
+        let mut bindings_list = HashMap::new();
+        self.resolve_pattern(&*local.pat,
+                             LocalIrrefutableMode,
+                             &mut bindings_list);
     }
 
     // build a map from pattern identifiers to binding-info's.
@@ -4136,9 +4140,7 @@ fn resolve_arm(&mut self, arm: &Arm) {
 
         let mut bindings_list = HashMap::new();
         for pattern in arm.pats.iter() {
-            self.resolve_pattern(&**pattern,
-                                 RefutableMode,
-                                 Some(&mut bindings_list));
+            self.resolve_pattern(&**pattern, RefutableMode, &mut bindings_list);
         }
 
         // This has to happen *after* we determine which
@@ -4284,7 +4286,7 @@ fn resolve_pattern(&mut self,
                        mode: PatternBindingMode,
                        // Maps idents to the node ID for the (outermost)
                        // pattern that binds them
-                       mut bindings_list: Option<&mut HashMap<Name,NodeId>>) {
+                       bindings_list: &mut HashMap<Name,NodeId>) {
         let pat_id = pattern.id;
         walk_pat(pattern, |pattern| {
             match pattern.node {
@@ -4373,43 +4375,27 @@ struct or enum variant",
                             // because that breaks the assumptions later
                             // passes make about or-patterns.)
 
-                            match bindings_list {
-                                Some(ref mut bindings_list)
-                                if !bindings_list.contains_key(&renamed) => {
-                                    let this = &mut *self;
-                                    let value_ribs = this.value_ribs.borrow();
-                                    let length = value_ribs.len();
-                                    let last_rib = value_ribs.get(
-                                        length - 1);
-                                    last_rib.bindings.borrow_mut()
-                                            .insert(renamed, DlDef(def));
-                                    bindings_list.insert(renamed, pat_id);
-                                }
-                                Some(ref mut b) => {
-                                  if b.find(&renamed) == Some(&pat_id) {
-                                      // Then this is a duplicate variable
-                                      // in the same disjunct, which is an
-                                      // error
-                                     self.resolve_error(pattern.span,
-                                       format!("identifier `{}` is bound \
-                                                more than once in the same \
-                                                pattern",
-                                               path_to_str(path)).as_slice());
-                                  }
-                                  // Not bound in the same pattern: do nothing
-                                }
-                                None => {
-                                    let this = &mut *self;
-                                    {
-                                        let value_ribs = this.value_ribs.borrow();
-                                        let length = value_ribs.len();
-                                        let last_rib = value_ribs.get(
-                                                length - 1);
-                                        last_rib.bindings.borrow_mut()
-                                                .insert(renamed, DlDef(def));
-                                    }
-                                }
+                            if !bindings_list.contains_key(&renamed) {
+                                let this = &mut *self;
+                                let value_ribs = this.value_ribs.borrow();
+                                let length = value_ribs.len();
+                                let last_rib = value_ribs.get(
+                                    length - 1);
+                                last_rib.bindings.borrow_mut()
+                                        .insert(renamed, DlDef(def));
+                                bindings_list.insert(renamed, pat_id);
+                            } else if bindings_list.find(&renamed) ==
+                                    Some(&pat_id) {
+                                // Then this is a duplicate variable in the
+                                // same disjunction, which is an error.
+                                self.resolve_error(pattern.span,
+                                    format!("identifier `{}` is bound \
+                                             more than once in the same \
+                                             pattern",
+                                            path_to_str(path)).as_slice());
                             }
+                            // Else, not bound in the same pattern: do
+                            // nothing.
                         }
                     }
 
diff --git a/src/librustc/middle/save/mod.rs b/src/librustc/middle/save/mod.rs
new file mode 100644 (file)
index 0000000..2c73bc8
--- /dev/null
@@ -0,0 +1,1439 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Output a CSV file containing the output from rustc's analysis. The data is
+//! primarily designed to be used as input to the DXR tool, specifically its
+//! Rust plugin. It could also be used by IDEs or other code browsing, search, or
+//! cross-referencing tools.
+//!
+//! Dumping the analysis is implemented by walking the AST and getting a bunch of
+//! info out from all over the place. We use Def IDs to identify objects. The
+//! tricky part is getting syntactic (span, source text) and semantic (reference
+//! Def IDs) information for parts of expressions which the compiler has discarded.
+//! E.g., in a path `foo::bar::baz`, the compiler only keeps a span for the whole
+//! path and a reference to `baz`, but we want spans and references for all three
+//! idents.
+//!
+//! SpanUtils is used to manipulate spans. In particular, to extract sub-spans
+//! from spans (e.g., the span for `bar` from the above example path).
+//! Recorder is used for recording the output in csv format. FmtStrs separates
+//! the format of the output away from extracting it from the compiler.
+//! DxrVisitor walks the AST and processes it.
+
+use driver::driver::CrateAnalysis;
+use driver::session::Session;
+
+use middle::def;
+use middle::ty;
+use middle::typeck;
+
+use std::cell::Cell;
+use std::gc::Gc;
+use std::io;
+use std::io::File;
+use std::io::fs;
+use std::os;
+
+use syntax::ast;
+use syntax::ast_util;
+use syntax::ast::{NodeId,DefId};
+use syntax::ast_map::NodeItem;
+use syntax::attr;
+use syntax::codemap::*;
+use syntax::parse::token;
+use syntax::parse::token::{get_ident,keywords};
+use syntax::visit;
+use syntax::visit::Visitor;
+use syntax::print::pprust::{path_to_str,ty_to_str};
+
+use middle::save::span_utils::SpanUtils;
+use middle::save::recorder::Recorder;
+use middle::save::recorder::FmtStrs;
+
+use util::ppaux;
+
+mod span_utils;
+mod recorder;
+
+// Helper function to escape quotes in a string
+fn escape(s: String) -> String {
+    s.replace("\"", "\"\"")
+}
+
+// If the expression is a macro expansion or other generated code, run screaming and don't index.
+fn generated_code(span: Span) -> bool {
+    span.expn_info.is_some() || span  == DUMMY_SP
+}
+
+struct DxrVisitor<'l> {
+    sess: &'l Session,
+    analysis: &'l CrateAnalysis,
+
+    collected_paths: Vec<(NodeId, ast::Path, bool, recorder::Row)>,
+    collecting: bool,
+
+    span: SpanUtils<'l>,
+    fmt: FmtStrs<'l>,
+}
+
+impl <'l> DxrVisitor<'l> {
+    fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
+        // the current crate
+        self.fmt.crate_str(krate.span, name);
+
+        // dump info about all the external crates referenced from this crate
+        self.sess.cstore.iter_crate_data(|n, cmd| {
+            self.fmt.external_crate_str(krate.span, cmd.name.as_slice(), n);
+        });
+        self.fmt.recorder.record("end_external_crates\n");
+    }
+
+    // Return all non-empty prefixes of a path.
+    // For each prefix, we return the span for the last segment in the prefix and
+    // a str representation of the entire prefix.
+    fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
+        let spans = self.span.spans_for_path_segments(path);
+
+        // Paths to enums seem to not match their spans - the span includes all the
+        // variants too. But they seem to always be at the end, so I hope we can cope with
+        // always using the first ones. So, only error out if we don't have enough spans.
+        // What could go wrong...?
+        if spans.len() < path.segments.len() {
+            error!("Mis-calculated spans for path '{}'. \
+                    Found {} spans, expected {}. Found spans:",
+                   path_to_str(path), spans.len(), path.segments.len());
+            for s in spans.iter() {
+                let loc = self.sess.codemap().lookup_char_pos(s.lo);
+                error!("    '{}' in {}, line {}",
+                       self.span.snippet(*s), loc.file.name, loc.line);
+            }
+            return vec!();
+        }
+
+        let mut result: Vec<(Span, String)> = vec!();
+
+
+        let mut segs = vec!();
+        for (seg, span) in path.segments.iter().zip(spans.iter()) {
+            segs.push(seg.clone());
+            let sub_path = ast::Path{span: *span, // span for the last segment
+                                     global: path.global,
+                                     segments: segs};
+            let qualname = path_to_str(&sub_path);
+            result.push((*span, qualname));
+            segs = sub_path.segments;
+        }
+
+        result
+    }
+
+    fn write_sub_paths(&mut self, path: &ast::Path, scope_id: NodeId) {
+        let sub_paths = self.process_path_prefixes(path);
+        for &(ref span, ref qualname) in sub_paths.iter() {
+            self.fmt.sub_mod_ref_str(path.span,
+                                     *span,
+                                     qualname.as_slice(),
+                                     scope_id);
+        }
+    }
+
+    // As write_sub_paths, but does not process the last ident in the path (assuming it
+    // will be processed elsewhere).
+    fn write_sub_paths_truncated(&mut self, path: &ast::Path, scope_id: NodeId) {
+        let sub_paths = self.process_path_prefixes(path);
+        let len = sub_paths.len();
+        if len <= 1 {
+            return;
+        }
+
+        let sub_paths = sub_paths.slice(0, len-1);
+        for &(ref span, ref qualname) in sub_paths.iter() {
+            self.fmt.sub_mod_ref_str(path.span,
+                                     *span,
+                                     qualname.as_slice(),
+                                     scope_id);
+        }
+    }
+
+    // As write_sub_paths, but expects a path of the form module_path::trait::method
+    // Where trait could actually be a struct too.
+    fn write_sub_path_trait_truncated(&mut self, path: &ast::Path, scope_id: NodeId) {
+        let sub_paths = self.process_path_prefixes(path);
+        let len = sub_paths.len();
+        if len <= 1 {
+            return;
+        }
+        let sub_paths = sub_paths.slice_to(len-1);
+
+        // write the trait part of the sub-path
+        let (ref span, ref qualname) = sub_paths[len-2];
+        self.fmt.sub_type_ref_str(path.span,
+                                  *span,
+                                  qualname.as_slice());
+
+        // write the other sub-paths
+        if len <= 2 {
+            return;
+        }
+        let sub_paths = sub_paths.slice(0, len-2);
+        for &(ref span, ref qualname) in sub_paths.iter() {
+            self.fmt.sub_mod_ref_str(path.span,
+                                     *span,
+                                     qualname.as_slice(),
+                                     scope_id);
+        }
+    }
+
+    // looks up anything, not just a type
+    fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
+        if !self.analysis.ty_cx.def_map.borrow().contains_key(&ref_id) {
+            self.sess.bug(format!("def_map has no key for {} in lookup_type_ref",
+                                  ref_id).as_slice());
+        }
+        let def = *self.analysis.ty_cx.def_map.borrow().get(&ref_id);
+        match def {
+            def::DefPrimTy(_) => None,
+            _ => Some(def.def_id()),
+        }
+    }
+
+    fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
+        let def_map = self.analysis.ty_cx.def_map.borrow();
+        if !def_map.contains_key(&ref_id) {
+            self.sess.span_bug(span, format!("def_map has no key for {} in lookup_def_kind",
+                                             ref_id).as_slice());
+        }
+        let def = *def_map.get(&ref_id);
+        match def {
+            def::DefMod(_) |
+            def::DefForeignMod(_) => Some(recorder::ModRef),
+            def::DefStruct(_) => Some(recorder::StructRef),
+            def::DefTy(_) |
+            def::DefTrait(_) => Some(recorder::TypeRef),
+            def::DefStatic(_, _) |
+            def::DefBinding(_, _) |
+            def::DefArg(_, _) |
+            def::DefLocal(_, _) |
+            def::DefVariant(_, _, _) |
+            def::DefUpvar(_, _, _, _) => Some(recorder::VarRef),
+
+            def::DefFn(_, _) => Some(recorder::FnRef),
+
+            def::DefSelfTy(_) |
+            def::DefRegion(_) |
+            def::DefTyParamBinder(_) |
+            def::DefLabel(_) |
+            def::DefStaticMethod(_, _, _) |
+            def::DefTyParam(_, _) |
+            def::DefUse(_) |
+            def::DefMethod(_, _) |
+            def::DefPrimTy(_) => {
+                self.sess.span_bug(span, format!("lookup_def_kind for unexpected item: {:?}",
+                                                 def).as_slice());
+            },
+        }
+    }
+
+    fn process_formals(&mut self, formals: &Vec<ast::Arg>, qualname: &str, e:DxrVisitorEnv) {
+        for arg in formals.iter() {
+            assert!(self.collected_paths.len() == 0 && !self.collecting);
+            self.collecting = true;
+            self.visit_pat(&*arg.pat, e);
+            self.collecting = false;
+            let span_utils = self.span;
+            for &(id, ref p, _, _) in self.collected_paths.iter() {
+                let typ = ppaux::ty_to_str(&self.analysis.ty_cx,
+                    *self.analysis.ty_cx.node_types.borrow().get(&(id as uint)));
+                // get the span only for the name of the variable (I hope the path is only ever a
+                // variable name, but who knows?)
+                self.fmt.formal_str(p.span,
+                                    span_utils.span_for_last_ident(p.span),
+                                    id,
+                                    qualname,
+                                    path_to_str(p).as_slice(),
+                                    typ.as_slice());
+            }
+            self.collected_paths.clear();
+        }
+    }
+
+    fn process_method(&mut self, method: &ast::Method, e:DxrVisitorEnv) {
+        if generated_code(method.span) {
+            return;
+        }
+
+        let mut scope_id;
+        // The qualname for a method is the trait name or name of the struct in an impl in
+        // which the method is declared in followed by the method's name.
+        let mut qualname = match ty::impl_of_method(&self.analysis.ty_cx,
+                                                ast_util::local_def(method.id)) {
+            Some(impl_id) => match self.analysis.ty_cx.map.get(impl_id.node) {
+                NodeItem(item) => {
+                    scope_id = item.id;
+                    match item.node {
+                        ast::ItemImpl(_, _, ty, _) => {
+                            let mut result = String::from_str("<");
+                            result.push_str(ty_to_str(&*ty).as_slice());
+
+                            match ty::trait_of_method(&self.analysis.ty_cx,
+                                                      ast_util::local_def(method.id)) {
+                                Some(def_id) => {
+                                    result.push_str(" as ");
+                                    result.push_str(
+                                        ty::item_path_str(&self.analysis.ty_cx, def_id).as_slice());
+                                },
+                                None => {}
+                            }
+                            result.append(">::")
+                        }
+                        _ => {
+                            self.sess.span_bug(method.span,
+                                               format!("Container {} for method {} not an impl?",
+                                                       impl_id.node, method.id).as_slice());
+                        },
+                    }
+                },
+                _ => {
+                    self.sess.span_bug(method.span,
+                                       format!("Container {} for method {} is not a node item {:?}",
+                                               impl_id.node,
+                                               method.id,
+                                               self.analysis.ty_cx.map.get(impl_id.node)
+                                              ).as_slice());
+                },
+            },
+            None => match ty::trait_of_method(&self.analysis.ty_cx,
+                                              ast_util::local_def(method.id)) {
+                Some(def_id) => {
+                    scope_id = def_id.node;
+                    match self.analysis.ty_cx.map.get(def_id.node) {
+                        NodeItem(_) => {
+                            let result = ty::item_path_str(&self.analysis.ty_cx, def_id);
+                            result.append("::")
+                        }
+                        _ => {
+                            self.sess.span_bug(method.span,
+                                               format!("Could not find container {} for method {}",
+                                                       def_id.node, method.id).as_slice());
+                        }
+                    }
+                },
+                None => {
+                    self.sess.span_bug(method.span,
+                                       format!("Could not find container for method {}",
+                                               method.id).as_slice());
+                },
+            },
+        };
+
+        qualname.push_str(get_ident(method.ident).get());
+        let qualname = qualname.as_slice();
+
+        // record the decl for this def (if it has one)
+        let decl_id = ty::trait_method_of_method(&self.analysis.ty_cx,
+                                                 ast_util::local_def(method.id))
+            .filtered(|def_id| method.id != 0 && def_id.node == 0);
+
+        let sub_span = self.span.sub_span_after_keyword(method.span, keywords::Fn);
+        self.fmt.method_str(method.span,
+                            sub_span,
+                            method.id,
+                            qualname,
+                            decl_id,
+                            scope_id);
+
+        self.process_formals(&method.decl.inputs, qualname, e);
+
+        // walk arg and return types
+        for arg in method.decl.inputs.iter() {
+            self.visit_ty(&*arg.ty, e);
+        }
+        self.visit_ty(&*method.decl.output, e);
+        // walk the fn body
+        self.visit_block(&*method.body, DxrVisitorEnv::new_nested(method.id));
+
+        self.process_generic_params(&method.generics,
+                                    method.span,
+                                    qualname,
+                                    method.id,
+                                    e);
+    }
+
+    fn process_trait_ref(&mut self,
+                         trait_ref: &ast::TraitRef,
+                         e: DxrVisitorEnv,
+                         impl_id: Option<NodeId>) {
+        match self.lookup_type_ref(trait_ref.ref_id) {
+            Some(id) => {
+                let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
+                self.fmt.ref_str(recorder::TypeRef,
+                                 trait_ref.path.span,
+                                 sub_span,
+                                 id,
+                                 e.cur_scope);
+                match impl_id {
+                    Some(impl_id) => self.fmt.impl_str(trait_ref.path.span,
+                                                       sub_span,
+                                                       impl_id,
+                                                       id,
+                                                       e.cur_scope),
+                    None => (),
+                }
+                visit::walk_path(self, &trait_ref.path, e);
+            },
+            None => ()
+        }
+    }
+
+    fn process_struct_field_def(&mut self,
+                                field: &ast::StructField,
+                                qualname: &str,
+                                scope_id: NodeId) {
+        match field.node.kind {
+            ast::NamedField(ident, _) => {
+                let name = get_ident(ident);
+                let qualname = format!("{}::{}", qualname, name);
+                let typ = ppaux::ty_to_str(&self.analysis.ty_cx,
+                    *self.analysis.ty_cx.node_types.borrow().get(&(field.node.id as uint)));
+                match self.span.sub_span_before_token(field.span, token::COLON) {
+                    Some(sub_span) => self.fmt.field_str(field.span,
+                                                         Some(sub_span),
+                                                         field.node.id,
+                                                         name.get().as_slice(),
+                                                         qualname.as_slice(),
+                                                         typ.as_slice(),
+                                                         scope_id),
+                    None => self.sess.span_bug(field.span,
+                                               format!("Could not find sub-span for field {}",
+                                                       qualname).as_slice()),
+                }
+            },
+            _ => (),
+        }
+    }
+
+    // Dump generic params bindings, then visit_generics
+    fn process_generic_params(&mut self, generics:&ast::Generics,
+                              full_span: Span,
+                              prefix: &str,
+                              id: NodeId,
+                              e: DxrVisitorEnv) {
+        // We can't only use visit_generics since we don't have spans for param
+        // bindings, so we reparse the full_span to get those sub spans.
+        // However full span is the entire enum/fn/struct block, so we only want
+        // the first few to match the number of generics we're looking for.
+        let param_sub_spans = self.span.spans_for_ty_params(full_span,
+                                                           (generics.ty_params.len() as int));
+        for (param, param_ss) in generics.ty_params.iter().zip(param_sub_spans.iter()) {
+            // Append $id to name to make sure each one is unique
+            let name = format!("{}::{}${}",
+                               prefix,
+                               escape(self.span.snippet(*param_ss)),
+                               id);
+            self.fmt.typedef_str(full_span,
+                                 Some(*param_ss),
+                                 param.id,
+                                 name.as_slice(),
+                                 "");
+        }
+        self.visit_generics(generics, e);
+    }
+
+    fn process_fn(&mut self,
+                  item: &ast::Item,
+                  e: DxrVisitorEnv,
+                  decl: ast::P<ast::FnDecl>,
+                  ty_params: &ast::Generics,
+                  body: ast::P<ast::Block>) {
+        let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+
+        let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Fn);
+        self.fmt.fn_str(item.span,
+                        sub_span,
+                        item.id,
+                        qualname.as_slice(),
+                        e.cur_scope);
+
+        self.process_formals(&decl.inputs, qualname.as_slice(), e);
+
+        // walk arg and return types
+        for arg in decl.inputs.iter() {
+            self.visit_ty(&*arg.ty, e);
+        }
+        self.visit_ty(&*decl.output, e);
+
+        // walk the body
+        self.visit_block(&*body, DxrVisitorEnv::new_nested(item.id));
+
+        self.process_generic_params(ty_params, item.span, qualname.as_slice(), item.id, e);
+    }
+
+    fn process_static(&mut self,
+                      item: &ast::Item,
+                      e: DxrVisitorEnv,
+                      typ: ast::P<ast::Ty>,
+                      mt: ast::Mutability,
+                      expr: &ast::Expr)
+    {
+        let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+
+        // If the variable is immutable, save the initialising expresion.
+        let value = match mt {
+            ast::MutMutable => String::from_str("<mutable>"),
+            ast::MutImmutable => self.span.snippet(expr.span),
+        };
+
+        let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Static);
+        self.fmt.static_str(item.span,
+                            sub_span,
+                            item.id,
+                            get_ident(item.ident).get(),
+                            qualname.as_slice(),
+                            value.as_slice(),
+                            ty_to_str(&*typ).as_slice(),
+                            e.cur_scope);
+
+        // walk type and init value
+        self.visit_ty(&*typ, e);
+        self.visit_expr(expr, e);
+    }
+
+    fn process_struct(&mut self,
+                      item: &ast::Item,
+                      e: DxrVisitorEnv,
+                      def: &ast::StructDef,
+                      ty_params: &ast::Generics) {
+        let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+
+        let ctor_id = match def.ctor_id {
+            Some(node_id) => node_id,
+            None => -1,
+        };
+        let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct);
+        self.fmt.struct_str(item.span,
+                            sub_span,
+                            item.id,
+                            ctor_id,
+                            qualname.as_slice(),
+                            e.cur_scope);
+
+        // fields
+        for field in def.fields.iter() {
+            self.process_struct_field_def(field, qualname.as_slice(), item.id);
+            self.visit_ty(&*field.node.ty, e);
+        }
+
+        self.process_generic_params(ty_params, item.span, qualname.as_slice(), item.id, e);
+    }
+
+    fn process_enum(&mut self,
+                    item: &ast::Item,
+                    e: DxrVisitorEnv,
+                    enum_definition: &ast::EnumDef,
+                    ty_params: &ast::Generics) {
+        let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+        match self.span.sub_span_after_keyword(item.span, keywords::Enum) {
+            Some(sub_span) => self.fmt.enum_str(item.span,
+                                                Some(sub_span),
+                                                item.id,
+                                                qualname.as_slice(),
+                                                e.cur_scope),
+            None => self.sess.span_bug(item.span,
+                                       format!("Could not find subspan for enum {}",
+                                               qualname).as_slice()),
+        }
+        for variant in enum_definition.variants.iter() {
+            let name = get_ident(variant.node.name);
+            let name = name.get();
+            let qualname = qualname.clone().append("::").append(name);
+            let val = self.span.snippet(variant.span);
+            match variant.node.kind {
+                ast::TupleVariantKind(ref args) => {
+                    // first ident in span is the variant's name
+                    self.fmt.tuple_variant_str(variant.span,
+                                               self.span.span_for_first_ident(variant.span),
+                                               variant.node.id,
+                                               name,
+                                               qualname.as_slice(),
+                                               val.as_slice(),
+                                               item.id);
+                    for arg in args.iter() {
+                        self.visit_ty(&*arg.ty, e);
+                    }
+                }
+                ast::StructVariantKind(ref struct_def) => {
+                    let ctor_id = match struct_def.ctor_id {
+                        Some(node_id) => node_id,
+                        None => -1,
+                    };
+                    self.fmt.struct_variant_str(
+                        variant.span,
+                        self.span.span_for_first_ident(variant.span),
+                        variant.node.id,
+                        ctor_id,
+                        qualname.as_slice(),
+                        val.as_slice(),
+                        item.id);
+
+                    for field in struct_def.fields.iter() {
+                        self.process_struct_field_def(field, qualname.as_slice(), variant.node.id);
+                        self.visit_ty(&*field.node.ty, e);
+                    }
+                }
+            }
+        }
+
+        self.process_generic_params(ty_params, item.span, qualname.as_slice(), item.id, e);
+    }
+
+    fn process_impl(&mut self,
+                    item: &ast::Item,
+                    e: DxrVisitorEnv,
+                    type_parameters: &ast::Generics,
+                    trait_ref: &Option<ast::TraitRef>,
+                    typ: ast::P<ast::Ty>,
+                    methods: &Vec<Gc<ast::Method>>) {
+        match typ.node {
+            ast::TyPath(ref path, _, id) => {
+                match self.lookup_type_ref(id) {
+                    Some(id) => {
+                        let sub_span = self.span.sub_span_for_type_name(path.span);
+                        self.fmt.ref_str(recorder::TypeRef,
+                                         path.span,
+                                         sub_span,
+                                         id,
+                                         e.cur_scope);
+                        self.fmt.impl_str(path.span,
+                                          sub_span,
+                                          item.id,
+                                          id,
+                                          e.cur_scope);
+                    },
+                    None => ()
+                }
+            },
+            _ => self.visit_ty(&*typ, e),
+        }
+
+        match *trait_ref {
+            Some(ref trait_ref) => self.process_trait_ref(trait_ref, e, Some(item.id)),
+            None => (),
+        }
+
+        self.process_generic_params(type_parameters, item.span, "", item.id, e);
+        for method in methods.iter() {
+            visit::walk_method_helper(self, &**method, e)
+        }
+    }
+
+    fn process_trait(&mut self,
+                     item: &ast::Item,
+                     e: DxrVisitorEnv,
+                     generics: &ast::Generics,
+                     trait_refs: &Vec<ast::TraitRef>,
+                     methods: &Vec<ast::TraitMethod>) {
+        let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+
+        let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
+        self.fmt.trait_str(item.span,
+                           sub_span,
+                           item.id,
+                           qualname.as_slice(),
+                           e.cur_scope);
+
+        // super-traits
+        for trait_ref in trait_refs.iter() {
+            match self.lookup_type_ref(trait_ref.ref_id) {
+                Some(id) => {
+                    let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
+                    self.fmt.ref_str(recorder::TypeRef,
+                                     trait_ref.path.span,
+                                     sub_span,
+                                     id,
+                                     e.cur_scope);
+                    self.fmt.inherit_str(trait_ref.path.span,
+                                         sub_span,
+                                         id,
+                                         item.id);
+                },
+                None => ()
+            }
+        }
+
+        // walk generics and methods
+        self.process_generic_params(generics, item.span, qualname.as_slice(), item.id, e);
+        for method in methods.iter() {
+            self.visit_trait_method(method, e)
+        }
+    }
+
+    fn process_mod(&mut self,
+                   item: &ast::Item,  // The module in question, represented as an item.
+                   e: DxrVisitorEnv,
+                   m: &ast::Mod) {
+        let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+
+        let cm = self.sess.codemap();
+        let filename = cm.span_to_filename(m.inner);
+
+        let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Mod);
+        self.fmt.mod_str(item.span,
+                         sub_span,
+                         item.id,
+                         qualname.as_slice(),
+                         e.cur_scope,
+                         filename.as_slice());
+
+        visit::walk_mod(self, m, DxrVisitorEnv::new_nested(item.id));
+    }
+
+    fn process_path(&mut self,
+                    ex: &ast::Expr,
+                    e: DxrVisitorEnv,
+                    path: &ast::Path) {
+        if generated_code(path.span) {
+            return
+        }
+
+        let def_map = self.analysis.ty_cx.def_map.borrow();
+        if !def_map.contains_key(&ex.id) {
+            self.sess.span_bug(ex.span,
+                               format!("def_map has no key for {} in visit_expr",
+                                       ex.id).as_slice());
+        }
+        let def = def_map.get(&ex.id);
+        let sub_span = self.span.span_for_last_ident(ex.span);
+        match *def {
+            def::DefLocal(id, _) |
+            def::DefArg(id, _) |
+            def::DefUpvar(id, _, _, _) |
+            def::DefBinding(id, _) => self.fmt.ref_str(recorder::VarRef,
+                                                       ex.span,
+                                                       sub_span,
+                                                       ast_util::local_def(id),
+                                                       e.cur_scope),
+            def::DefStatic(def_id,_) |
+            def::DefVariant(_, def_id, _) => self.fmt.ref_str(recorder::VarRef,
+                                                              ex.span,
+                                                              sub_span,
+                                                              def_id,
+                                                              e.cur_scope),
+            def::DefStruct(def_id) => self.fmt.ref_str(recorder::StructRef,
+                                                       ex.span,
+                                                       sub_span,
+                                                       def_id,
+                                                        e.cur_scope),
+            def::DefStaticMethod(declid, provenence, _) => {
+                let sub_span = self.span.sub_span_for_meth_name(ex.span);
+                let defid = if declid.krate == ast::LOCAL_CRATE {
+                    let m = ty::method(&self.analysis.ty_cx, declid);
+                    match provenence {
+                        def::FromTrait(def_id) =>
+                            Some(ty::trait_methods(&self.analysis.ty_cx, def_id)
+                                .iter().find(|mr| mr.ident.name == m.ident.name).unwrap().def_id),
+                        def::FromImpl(def_id) => {
+                            let impl_methods = self.analysis.ty_cx.impl_methods.borrow();
+                            Some(*impl_methods.get(&def_id)
+                                .iter().find(|mr|
+                                    ty::method(
+                                        &self.analysis.ty_cx, **mr).ident.name == m.ident.name)
+                                .unwrap())
+                        }
+                    }
+                } else {
+                    None
+                };
+                self.fmt.meth_call_str(ex.span,
+                                       sub_span,
+                                       defid,
+                                       Some(declid),
+                                       e.cur_scope);
+            },
+            def::DefFn(def_id, _) => self.fmt.fn_call_str(ex.span,
+                                                          sub_span,
+                                                          def_id,
+                                                          e.cur_scope),
+            _ => self.sess.span_bug(ex.span,
+                                    format!("Unexpected def kind while looking up path in '{}'",
+                                            self.span.snippet(ex.span)).as_slice()),
+        }
+        // modules or types in the path prefix
+        match *def {
+            def::DefStaticMethod(_, _, _) => {
+                self.write_sub_path_trait_truncated(path, e.cur_scope);
+            },
+            def::DefLocal(_, _) |
+            def::DefArg(_, _) |
+            def::DefStatic(_,_) |
+            def::DefStruct(_) |
+            def::DefFn(_, _) => self.write_sub_paths_truncated(path, e.cur_scope),
+            _ => {},
+        }
+
+        visit::walk_path(self, path, e);
+    }
+
+    fn process_struct_lit(&mut self,
+                          ex: &ast::Expr,
+                          e: DxrVisitorEnv,
+                          path: &ast::Path,
+                          fields: &Vec<ast::Field>,
+                          base: Option<Gc<ast::Expr>>) {
+        if generated_code(path.span) {
+            return
+        }
+
+        let mut struct_def: Option<DefId> = None;
+        match self.lookup_type_ref(ex.id) {
+            Some(id) => {
+                struct_def = Some(id);
+                let sub_span = self.span.span_for_last_ident(path.span);
+                self.fmt.ref_str(recorder::StructRef,
+                                 path.span,
+                                 sub_span,
+                                 id,
+                                 e.cur_scope);
+            },
+            None => ()
+        }
+
+        self.write_sub_paths_truncated(path, e.cur_scope);
+
+        for field in fields.iter() {
+            match struct_def {
+                Some(struct_def) => {
+                    let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def);
+                    for f in fields.iter() {
+                        if generated_code(field.ident.span) {
+                            continue;
+                        }
+                        if f.name == field.ident.node.name {
+                            // We don't really need a sub-span here, but no harm done
+                            let sub_span = self.span.span_for_last_ident(field.ident.span);
+                            self.fmt.ref_str(recorder::VarRef,
+                                             field.ident.span,
+                                             sub_span,
+                                             f.id,
+                                             e.cur_scope);
+                        }
+                    }
+                }
+                None => {}
+            }
+
+            self.visit_expr(&*field.expr, e)
+        }
+        visit::walk_expr_opt(self, base, e)
+    }
+
+    fn process_method_call(&mut self,
+                           ex: &ast::Expr,
+                           e: DxrVisitorEnv,
+                           args: &Vec<Gc<ast::Expr>>) {
+        let method_map = self.analysis.ty_cx.method_map.borrow();
+        let method_callee = method_map.get(&typeck::MethodCall::expr(ex.id));
+        let (def_id, decl_id) = match method_callee.origin {
+            typeck::MethodStatic(def_id) => {
+                // method invoked on an object with a concrete type (not a static method)
+                let decl_id = ty::trait_method_of_method(&self.analysis.ty_cx, def_id);
+
+                // This incantation is required if the method referenced is a trait's
+                // defailt implementation.
+                let def_id = ty::method(&self.analysis.ty_cx, def_id).provided_source
+                                    .unwrap_or(def_id);
+                (Some(def_id), decl_id)
+            }
+            typeck::MethodParam(mp) => {
+                // method invoked on a type parameter
+                let method = ty::trait_method(&self.analysis.ty_cx,
+                                              mp.trait_id,
+                                              mp.method_num);
+                (None, Some(method.def_id))
+            },
+            typeck::MethodObject(mo) => {
+                // method invoked on a trait instance
+                let method = ty::trait_method(&self.analysis.ty_cx,
+                                              mo.trait_id,
+                                              mo.method_num);
+                (None, Some(method.def_id))
+            },
+        };
+        let sub_span = self.span.sub_span_for_meth_name(ex.span);
+        self.fmt.meth_call_str(ex.span,
+                               sub_span,
+                               def_id,
+                               decl_id,
+                               e.cur_scope);
+
+        // walk receiver and args
+        visit::walk_exprs(self, args.as_slice(), e);
+    }
+
+    fn process_pat(&mut self, p:&ast::Pat, e: DxrVisitorEnv) {
+        if generated_code(p.span) {
+            return
+        }
+
+        match p.node {
+            ast::PatStruct(ref path, ref fields, _) => {
+                self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef));
+                visit::walk_path(self, path, e);
+                let struct_def = match self.lookup_type_ref(p.id) {
+                    Some(sd) => sd,
+                    None => {
+                        self.sess.span_bug(p.span,
+                                           format!("Could not find struct_def for `{}`",
+                                                   self.span.snippet(p.span)).as_slice());
+                    }
+                };
+                // The AST doesn't give us a span for the struct field, so we have
+                // to figure out where it is by assuming it's the token before each colon.
+                let field_spans = self.span.sub_spans_before_tokens(p.span,
+                                                                    token::COMMA,
+                                                                    token::COLON);
+                if fields.len() != field_spans.len() {
+                    self.sess.span_bug(p.span,
+                        format!("Mismatched field count in '{}', found {}, expected {}",
+                                self.span.snippet(p.span), field_spans.len(), fields.len()
+                               ).as_slice());
+                }
+                for (field, &span) in fields.iter().zip(field_spans.iter()) {
+                    self.visit_pat(&*field.pat, e);
+                    if span.is_none() {
+                        continue;
+                    }
+                    let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def);
+                    for f in fields.iter() {
+                        if f.name == field.ident.name {
+                            self.fmt.ref_str(recorder::VarRef,
+                                             p.span,
+                                             span,
+                                             f.id,
+                                             e.cur_scope);
+                            break;
+                        }
+                    }
+                }
+            }
+            ast::PatEnum(ref path, _) => {
+                self.collected_paths.push((p.id, path.clone(), false, recorder::VarRef));
+                visit::walk_pat(self, p, e);
+            }
+            ast::PatIdent(bm, ref path, ref optional_subpattern) => {
+                let immut = match bm {
+                    // Even if the ref is mut, you can't change the ref, only
+                    // the data pointed at, so showing the initialising expression
+                    // is still worthwhile.
+                    ast::BindByRef(_) => true,
+                    ast::BindByValue(mt) => {
+                        match mt {
+                            ast::MutMutable => false,
+                            ast::MutImmutable => true,
+                        }
+                    }
+                };
+                // collect path for either visit_local or visit_arm
+                self.collected_paths.push((p.id, path.clone(), immut, recorder::VarRef));
+                match *optional_subpattern {
+                    None => {}
+                    Some(subpattern) => self.visit_pat(&*subpattern, e),
+                }
+            }
+            _ => visit::walk_pat(self, p, e)
+        }
+    }
+}
+
+impl<'l> Visitor<DxrVisitorEnv> for DxrVisitor<'l> {
+    fn visit_item(&mut self, item:&ast::Item, e: DxrVisitorEnv) {
+        if generated_code(item.span) {
+            return
+        }
+
+        match item.node {
+            ast::ItemFn(decl, _, _, ref ty_params, body) =>
+                self.process_fn(item, e, decl, ty_params, body),
+            ast::ItemStatic(typ, mt, expr) =>
+                self.process_static(item, e, typ, mt, &*expr),
+            ast::ItemStruct(def, ref ty_params) => self.process_struct(item, e, &*def, ty_params),
+            ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, e, def, ty_params),
+            ast::ItemImpl(ref ty_params, ref trait_ref, typ, ref methods) =>
+                self.process_impl(item, e, ty_params, trait_ref, typ, methods),
+            ast::ItemTrait(ref generics, _, ref trait_refs, ref methods) =>
+                self.process_trait(item, e, generics, trait_refs, methods),
+            ast::ItemMod(ref m) => self.process_mod(item, e, m),
+            ast::ItemTy(ty, ref ty_params) => {
+                let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+                let value = ty_to_str(&*ty);
+                let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type);
+                self.fmt.typedef_str(item.span,
+                                     sub_span,
+                                     item.id,
+                                     qualname.as_slice(),
+                                     value.as_slice());
+
+                self.visit_ty(&*ty, e);
+                self.process_generic_params(ty_params, item.span, qualname.as_slice(), item.id, e);
+            },
+            ast::ItemMac(_) => (),
+            _ => visit::walk_item(self, item, e),
+        }
+    }
+
+    fn visit_generics(&mut self, generics: &ast::Generics, e: DxrVisitorEnv) {
+        for param in generics.ty_params.iter() {
+            for bound in param.bounds.iter() {
+                match *bound {
+                    ast::TraitTyParamBound(ref trait_ref) => {
+                        self.process_trait_ref(trait_ref, e, None);
+                    }
+                    _ => {}
+                }
+            }
+            match param.default {
+                Some(ty) => self.visit_ty(&*ty, e),
+                None => (),
+            }
+        }
+    }
+
+    // We don't actually index functions here, that is done in visit_item/ItemFn.
+    // Here we just visit methods.
+    fn visit_fn(&mut self,
+                fk: &visit::FnKind,
+                fd: &ast::FnDecl,
+                b: &ast::Block,
+                s: Span,
+                _: NodeId,
+                e: DxrVisitorEnv) {
+        if generated_code(s) {
+            return;
+        }
+
+        match *fk {
+            visit::FkMethod(_, _, method) => self.process_method(method, e),
+            _ => visit::walk_fn(self, fk, fd, b, s, e),
+        }
+    }
+
+    fn visit_trait_method(&mut self, tm: &ast::TraitMethod, e: DxrVisitorEnv) {
+        match *tm {
+            ast::Required(ref method_type) => {
+                if generated_code(method_type.span) {
+                    return;
+                }
+
+                let mut scope_id ;
+                let mut qualname = match ty::trait_of_method(&self.analysis.ty_cx,
+                                                             ast_util::local_def(method_type.id)) {
+                    Some(def_id) => {
+                        scope_id = def_id.node;
+                        ty::item_path_str(&self.analysis.ty_cx, def_id).append("::")
+                    },
+                    None => {
+                        self.sess.span_bug(method_type.span,
+                                           format!("Could not find trait for method {}",
+                                                   method_type.id).as_slice());
+                    },
+                };
+
+                qualname.push_str(get_ident(method_type.ident).get());
+                let qualname = qualname.as_slice();
+
+                let sub_span = self.span.sub_span_after_keyword(method_type.span, keywords::Fn);
+                self.fmt.method_decl_str(method_type.span,
+                                         sub_span,
+                                         method_type.id,
+                                         qualname,
+                                         scope_id);
+
+                // walk arg and return types
+                for arg in method_type.decl.inputs.iter() {
+                    self.visit_ty(&*arg.ty, e);
+                }
+                self.visit_ty(&*method_type.decl.output, e);
+
+                self.process_generic_params(&method_type.generics,
+                                            method_type.span,
+                                            qualname,
+                                            method_type.id,
+                                            e);
+            }
+            ast::Provided(method) => self.process_method(&*method, e),
+        }
+    }
+
+    fn visit_view_item(&mut self, i:&ast::ViewItem, e:DxrVisitorEnv) {
+        if generated_code(i.span) {
+            return
+        }
+
+        match i.node {
+            ast::ViewItemUse(ref path) => {
+                match path.node {
+                    ast::ViewPathSimple(ident, ref path, id) => {
+                        let sub_span = self.span.span_for_last_ident(path.span);
+                        let mod_id = match self.lookup_type_ref(id) {
+                            Some(def_id) => {
+                                match self.lookup_def_kind(id, path.span) {
+                                    Some(kind) => self.fmt.ref_str(kind,
+                                                                   path.span,
+                                                                   sub_span,
+                                                                   def_id,
+                                                                   e.cur_scope),
+                                    None => {},
+                                }
+                                Some(def_id)
+                            },
+                            None => None,
+                        };
+
+                        // 'use' always introduces an alias, if there is not an explicit
+                        // one, there is an implicit one.
+                        let sub_span =
+                            match self.span.sub_span_before_token(path.span, token::EQ) {
+                                Some(sub_span) => Some(sub_span),
+                                None => sub_span,
+                            };
+
+                        self.fmt.use_alias_str(path.span,
+                                               sub_span,
+                                               id,
+                                               mod_id,
+                                               get_ident(ident).get(),
+                                               e.cur_scope);
+                        self.write_sub_paths_truncated(path, e.cur_scope);
+                    }
+                    ast::ViewPathGlob(ref path, _) => {
+                        self.write_sub_paths(path, e.cur_scope);
+                    }
+                    ast::ViewPathList(ref path, ref list, _) => {
+                        for plid in list.iter() {
+                            match self.lookup_type_ref(plid.node.id) {
+                                Some(id) => match self.lookup_def_kind(plid.node.id, plid.span) {
+                                    Some(kind) => self.fmt.ref_str(kind,
+                                                                   plid.span,
+                                                                   Some(plid.span),
+                                                                   id,
+                                                                   e.cur_scope),
+                                    None => (),
+                                },
+                                None => ()
+                            }
+                        }
+
+                        self.write_sub_paths(path, e.cur_scope);
+                    }
+                }
+            },
+            ast::ViewItemExternCrate(ident, ref s, id) => {
+                let name = get_ident(ident).get().to_owned();
+                let s = match *s {
+                    Some((ref s, _)) => s.get().to_owned(),
+                    None => name.to_owned(),
+                };
+                let sub_span = self.span.sub_span_after_keyword(i.span, keywords::Crate);
+                let cnum = match self.sess.cstore.find_extern_mod_stmt_cnum(id) {
+                    Some(cnum) => cnum,
+                    None => 0,
+                };
+                self.fmt.extern_crate_str(i.span,
+                                          sub_span,
+                                          id,
+                                          cnum,
+                                          name.as_slice(),
+                                          s.as_slice(),
+                                          e.cur_scope);
+            },
+        }
+    }
+
+    fn visit_ty(&mut self, t: &ast::Ty, e: DxrVisitorEnv) {
+        if generated_code(t.span) {
+            return
+        }
+
+        match t.node {
+            ast::TyPath(ref path, _, id) => {
+                match self.lookup_type_ref(id) {
+                    Some(id) => {
+                        let sub_span = self.span.sub_span_for_type_name(t.span);
+                        self.fmt.ref_str(recorder::TypeRef,
+                                         t.span,
+                                         sub_span,
+                                         id,
+                                         e.cur_scope);
+                    },
+                    None => ()
+                }
+
+                self.write_sub_paths_truncated(path, e.cur_scope);
+
+                visit::walk_path(self, path, e);
+            },
+            _ => visit::walk_ty(self, t, e),
+        }
+    }
+
+    fn visit_expr(&mut self, ex: &ast::Expr, e: DxrVisitorEnv) {
+        if generated_code(ex.span) {
+            return
+        }
+
+        match ex.node {
+            ast::ExprCall(_f, ref _args) => {
+                // Don't need to do anything for function calls,
+                // because just walking the callee path does what we want.
+                visit::walk_expr(self, ex, e);
+            },
+            ast::ExprPath(ref path) => self.process_path(ex, e, path),
+            ast::ExprStruct(ref path, ref fields, base) =>
+                self.process_struct_lit(ex, e, path, fields, base),
+            ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, e, args),
+            ast::ExprField(sub_ex, ident, _) => {
+                if generated_code(sub_ex.span) {
+                    return
+                }
+
+                self.visit_expr(&*sub_ex, e);
+
+                let t = ty::expr_ty_adjusted(&self.analysis.ty_cx, &*sub_ex);
+                let t_box = ty::get(t);
+                match t_box.sty {
+                    ty::ty_struct(def_id, _) => {
+                        let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, def_id);
+                        for f in fields.iter() {
+                            if f.name == ident.name {
+                                let sub_span = self.span.span_for_last_ident(ex.span);
+                                self.fmt.ref_str(recorder::VarRef,
+                                                 ex.span,
+                                                 sub_span,
+                                                 f.id,
+                                                 e.cur_scope);
+                                break;
+                            }
+                        }
+                    },
+                    _ => self.sess.span_bug(ex.span,
+                                            "Expected struct type, but not ty_struct"),
+                }
+            },
+            ast::ExprFnBlock(decl, body) => {
+                if generated_code(body.span) {
+                    return
+                }
+
+                let id = String::from_str("$").append(ex.id.to_str().as_slice());
+                self.process_formals(&decl.inputs, id.as_slice(), e);
+
+                // walk arg and return types
+                for arg in decl.inputs.iter() {
+                    self.visit_ty(&*arg.ty, e);
+                }
+                self.visit_ty(&*decl.output, e);
+
+                // walk the body
+                self.visit_block(&*body, DxrVisitorEnv::new_nested(ex.id));
+            },
+            _ => {
+                visit::walk_expr(self, ex, e)
+            },
+        }
+    }
+
+    fn visit_mac(&mut self, _: &ast::Mac, _: DxrVisitorEnv) {
+        // Just stop, macros are poison to us.
+    }
+
+    fn visit_pat(&mut self, p: &ast::Pat, e: DxrVisitorEnv) {
+        self.process_pat(p, e);
+        if !self.collecting {
+            self.collected_paths.clear();
+        }
+    }
+
+    fn visit_arm(&mut self, arm: &ast::Arm, e: DxrVisitorEnv) {
+        assert!(self.collected_paths.len() == 0 && !self.collecting);
+        self.collecting = true;
+
+        for pattern in arm.pats.iter() {
+            // collect paths from the arm's patterns
+            self.visit_pat(&**pattern, e);
+        }
+        self.collecting = false;
+        // process collected paths
+        for &(id, ref p, ref immut, ref_kind) in self.collected_paths.iter() {
+            let value = if *immut {
+                self.span.snippet(p.span).into_owned()
+            } else {
+                "<mutable>".to_owned()
+            };
+            let sub_span = self.span.span_for_first_ident(p.span);
+            let def_map = self.analysis.ty_cx.def_map.borrow();
+            if !def_map.contains_key(&id) {
+                self.sess.span_bug(p.span,
+                                   format!("def_map has no key for {} in visit_arm",
+                                           id).as_slice());
+            }
+            let def = def_map.get(&id);
+            match *def {
+                def::DefBinding(id, _)  => self.fmt.variable_str(p.span,
+                                                                 sub_span,
+                                                                 id,
+                                                                 path_to_str(p).as_slice(),
+                                                                 value.as_slice(),
+                                                                 ""),
+                def::DefVariant(_,id,_) => self.fmt.ref_str(ref_kind,
+                                                            p.span,
+                                                            sub_span,
+                                                            id,
+                                                            e.cur_scope),
+                // FIXME(nrc) what is this doing here?
+                def::DefStatic(_, _) => {}
+                _ => error!("unexpected defintion kind when processing collected paths: {:?}", *def)
+            }
+        }
+        self.collected_paths.clear();
+        visit::walk_expr_opt(self, arm.guard, e);
+        self.visit_expr(&*arm.body, e);
+    }
+
+    fn visit_stmt(&mut self, s:&ast::Stmt, e:DxrVisitorEnv) {
+        if generated_code(s.span) {
+            return
+        }
+
+        visit::walk_stmt(self, s, e)
+    }
+
+    fn visit_local(&mut self, l:&ast::Local, e: DxrVisitorEnv) {
+        if generated_code(l.span) {
+            return
+        }
+
+        // The local could declare multiple new vars, we must walk the
+        // pattern and collect them all.
+        assert!(self.collected_paths.len() == 0 && !self.collecting);
+        self.collecting = true;
+        self.visit_pat(&*l.pat, e);
+        self.collecting = false;
+
+        let value = self.span.snippet(l.span);
+
+        for &(id, ref p, ref immut, _) in self.collected_paths.iter() {
+            let value = if *immut { value.to_owned() } else { "<mutable>".to_owned() };
+            let types = self.analysis.ty_cx.node_types.borrow();
+            let typ = ppaux::ty_to_str(&self.analysis.ty_cx, *types.get(&(id as uint)));
+            // Get the span only for the name of the variable (I hope the path
+            // is only ever a variable name, but who knows?).
+            let sub_span = self.span.span_for_last_ident(p.span);
+            // Rust uses the id of the pattern for var lookups, so we'll use it too.
+            self.fmt.variable_str(p.span,
+                                  sub_span,
+                                  id,
+                                  path_to_str(p).as_slice(),
+                                  value.as_slice(),
+                                  typ.as_slice());
+        }
+        self.collected_paths.clear();
+
+        // Just walk the initialiser and type (don't want to walk the pattern again).
+        self.visit_ty(&*l.ty, e);
+        visit::walk_expr_opt(self, l.init, e);
+    }
+}
+
+#[deriving(Clone)]
+struct DxrVisitorEnv {
+    cur_scope: NodeId,
+}
+
+impl DxrVisitorEnv {
+    fn new() -> DxrVisitorEnv {
+        DxrVisitorEnv{cur_scope: 0}
+    }
+    fn new_nested(new_mod: NodeId) -> DxrVisitorEnv {
+        DxrVisitorEnv{cur_scope: new_mod}
+    }
+}
+
+pub fn process_crate(sess: &Session,
+                     krate: &ast::Crate,
+                     analysis: &CrateAnalysis,
+                     odir: &Option<Path>) {
+    if generated_code(krate.span) {
+        return;
+    }
+
+    let (cratename, crateid) = match attr::find_crateid(krate.attrs.as_slice()) {
+        Some(crateid) => (crateid.name.clone(), crateid.to_str()),
+        None => {
+            info!("Could not find crate name, using 'unknown_crate'");
+            (String::from_str("unknown_crate"),"unknown_crate".to_owned())
+        },
+    };
+
+    info!("Dumping crate {} ({})", cratename, crateid);
+
+    // find a path to dump our data to
+    let mut root_path = match os::getenv("DXR_RUST_TEMP_FOLDER") {
+        Some(val) => Path::new(val),
+        None => match *odir {
+            Some(ref val) => val.join("dxr"),
+            None => Path::new("dxr-temp"),
+        },
+    };
+
+    match fs::mkdir_recursive(&root_path, io::UserRWX) {
+        Err(e) => sess.err(format!("Could not create directory {}: {}",
+                           root_path.display(), e).as_slice()),
+        _ => (),
+    }
+
+    {
+        let disp = root_path.display();
+        info!("Writing output to {}", disp);
+    }
+
+    // Create ouput file.
+    let mut out_name = cratename.clone();
+    out_name.push_str(".csv");
+    root_path.push(out_name);
+    let output_file = match File::create(&root_path) {
+        Ok(f) => box f,
+        Err(e) => {
+            let disp = root_path.display();
+            sess.fatal(format!("Could not open {}: {}", disp, e).as_slice());
+        }
+    };
+    root_path.pop();
+
+    let mut visitor = DxrVisitor{ sess: sess,
+                                  analysis: analysis,
+                                  collected_paths: vec!(),
+                                  collecting: false,
+                                  fmt: FmtStrs::new(box Recorder {
+                                                        out: output_file as Box<Writer>,
+                                                        dump_spans: false,
+                                                    },
+                                                    SpanUtils {
+                                                        sess: sess,
+                                                        err_count: Cell::new(0)
+                                                    },
+                                                    cratename.clone()),
+                                  span: SpanUtils {
+                                      sess: sess,
+                                      err_count: Cell::new(0)
+                                  }};
+
+    visitor.dump_crate_info(cratename.as_slice(), krate);
+
+    visit::walk_crate(&mut visitor, krate, DxrVisitorEnv::new());
+}
diff --git a/src/librustc/middle/save/recorder.rs b/src/librustc/middle/save/recorder.rs
new file mode 100644 (file)
index 0000000..428f97d
--- /dev/null
@@ -0,0 +1,575 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use middle::save::escape;
+use middle::save::span_utils::SpanUtils;
+
+use std::vec::Vec;
+
+use syntax::ast;
+use syntax::ast::{NodeId,DefId};
+use syntax::codemap::*;
+
+pub struct Recorder {
+    // output file
+    pub out: Box<Writer>,
+    pub dump_spans: bool,
+}
+
+impl Recorder {
+    pub fn record(&mut self, info: &str) {
+        match write!(self.out, "{}", info) {
+            Err(_) => error!("Error writing output '{}'", info),
+            _ => (),
+        }
+    }
+
+    pub fn dump_span(&mut self,
+                     su: SpanUtils,
+                     kind: &str,
+                     span: Span,
+                     _sub_span: Option<Span>) {
+        assert!(self.dump_spans);
+        let result = format!("span,kind,{},{},text,\"{}\"\n",
+                             kind, su.extent_str(span), escape(su.snippet(span)));
+        self.record(result.as_slice());
+    }
+}
+
+pub struct FmtStrs<'a> {
+    pub recorder: Box<Recorder>,
+    span: SpanUtils<'a>,
+    krate: String,
+}
+
+macro_rules! s { ($e:expr) => { format!("{}", $e) }}
+macro_rules! svec {
+    ($($e:expr),*) => ({
+        // leading _ to allow empty construction without a warning.
+        let mut _temp = ::std::vec::Vec::new();
+        $(_temp.push(s!($e));)*
+        _temp
+    })
+}
+
+pub enum Row {
+    Variable,
+    Enum,
+    Variant,
+    VariantStruct,
+    Function,
+    MethodDecl,
+    Struct,
+    Trait,
+    Impl,
+    Module,
+    UseAlias,
+    ExternCrate,
+    Inheritance,
+    MethodCall,
+    Typedef,
+    ExternalCrate,
+    Crate,
+    FnCall,
+    ModRef,
+    VarRef,
+    TypeRef,
+    StructRef,
+    FnRef,
+}
+
+impl<'a> FmtStrs<'a> {
+    pub fn new(rec: Box<Recorder>, span: SpanUtils<'a>, krate: String) -> FmtStrs<'a> {
+        FmtStrs {
+            recorder: rec,
+            span: span,
+            krate: krate,
+        }
+    }
+
+    // A map from kind of item to a tuple of
+    //   a string representation of the name
+    //   a vector of field names
+    //   whether this kind requires a span
+    //   whether dump_spans should dump for this kind
+    fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
+        match r {
+            Variable => ("variable",
+                         vec!("id","name","qualname","value","type","scopeid"),
+                         true, true),
+            Enum => ("enum", vec!("id","qualname","scopeid"), true, true),
+            Variant => ("variant", vec!("id","name","qualname","value","scopeid"), true, true),
+            VariantStruct => ("variant_struct",
+                              vec!("id","ctor_id","qualname","value","scopeid"), true, true),
+            Function => ("function", vec!("id","qualname","declid","declidcrate","scopeid"),
+                         true, true),
+            MethodDecl => ("method_decl", vec!("id","qualname","scopeid"), true, true),
+            Struct => ("struct", vec!("id","ctor_id","qualname","scopeid"), true, true),
+            Trait => ("trait", vec!("id","qualname","scopeid"), true, true),
+            Impl => ("impl", vec!("id","refid","refidcrate","scopeid"), true, true),
+            Module => ("module", vec!("id","qualname","scopeid","def_file"), true, false),
+            UseAlias => ("use_alias",
+                         vec!("id","refid","refidcrate","name","scopeid"),
+                         true, true),
+            ExternCrate => ("extern_crate",
+                            vec!("id","name","location","crate","scopeid"),
+                            true, true),
+            Inheritance => ("inheritance",
+                            vec!("base","basecrate","derived","derivedcrate"),
+                            true, false),
+            MethodCall => ("method_call",
+                           vec!("refid","refidcrate","declid","declidcrate","scopeid"),
+                            true, true),
+            Typedef => ("typedef", vec!("id","qualname","value"), true, true),
+            ExternalCrate => ("external_crate", vec!("name","crate","file_name"), false, false),
+            Crate => ("crate", vec!("name"), true, false),
+            FnCall => ("fn_call", vec!("refid","refidcrate","qualname","scopeid"), true, true),
+            ModRef => ("mod_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
+            VarRef => ("var_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
+            TypeRef => ("type_ref",
+                        vec!("refid","refidcrate","qualname","scopeid"),
+                        true, true),
+            StructRef => ("struct_ref",
+                          vec!("refid","refidcrate","qualname","scopeid"),
+                           true, true),
+            FnRef => ("fn_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true)
+        }
+    }
+
+    pub fn make_values_str(&self,
+                           kind: &'static str,
+                           fields: &Vec<&'static str>,
+                           values: Vec<String>,
+                           span: Span) -> Option<String> {
+        if values.len() != fields.len() {
+            self.span.sess.span_bug(span, format!(
+                "Mismatch between length of fields for '{}', expected '{}', found '{}'",
+                kind, fields.len(), values.len()).as_slice());
+        }
+
+        let values = values.iter().map(|s| {
+            if s.len() > 1020 {
+                s.as_slice().slice_to(1020)
+            } else {
+                s.as_slice()
+            }
+        });
+
+        let pairs = fields.iter().zip(values);
+        let mut strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(
+            if *f == "qualname" {
+                self.krate.clone().append("::").append(v)
+            } else {
+                String::from_str(v)
+            }
+        )));
+        Some(strs.fold(String::new(), |s, ss| s.append(ss.as_slice()))).map(|s| s.into_owned())
+    }
+
+    pub fn record_without_span(&mut self,
+                               kind: Row,
+                               values: Vec<String>,
+                               span: Span) {
+        let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
+
+        if needs_span {
+            self.span.sess.span_bug(span, format!(
+                "Called record_without_span for '{}' which does requires a span",
+                label).as_slice());
+        }
+        assert!(!dump_spans);
+
+        if self.recorder.dump_spans {
+            return;
+        }
+
+        let values_str = match self.make_values_str(label, fields, values, span) {
+            Some(vs) => vs,
+            None => return,
+        };
+
+        let result = String::from_str(label);
+        self.recorder.record(result.append(values_str.as_slice()).append("\n").as_slice());
+    }
+
+    pub fn record_with_span(&mut self,
+                            kind: Row,
+                            span: Span,
+                            sub_span: Span,
+                            values: Vec<String>) {
+        let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
+
+        if self.recorder.dump_spans {
+            if dump_spans {
+                self.recorder.dump_span(self.span, label, span, Some(sub_span));
+            }
+            return;
+        }
+
+        if !needs_span {
+            self.span.sess.span_bug(span,
+                                    format!("Called record_with_span for '{}' \
+                                             which does not require a span", label).as_slice());
+        }
+
+        let values_str = match self.make_values_str(label, fields, values, span) {
+            Some(vs) => vs,
+            None => return,
+        };
+        let result = format!("{},{}{}\n", label, self.span.extent_str(sub_span), values_str);
+        self.recorder.record(result.as_slice());
+    }
+
+    pub fn check_and_record(&mut self,
+                            kind: Row,
+                            span: Span,
+                            sub_span: Option<Span>,
+                            values: Vec<String>) {
+        match sub_span {
+            Some(sub_span) => self.record_with_span(kind, span, sub_span, values),
+            None => {
+                let (label, _, _, _) = FmtStrs::lookup_row(kind);
+                self.span.report_span_err(label, span);
+            }
+        }
+    }
+
+    pub fn variable_str(&mut self,
+                        span: Span,
+                        sub_span: Option<Span>,
+                        id: NodeId,
+                        name: &str,
+                        value: &str,
+                        typ: &str) {
+        // Getting a fully qualified name for a variable is hard because in
+        // the local case they can be overridden in one block and there is no nice way
+        // to refer to such a scope in english, so we just hack it by appending the
+        // variable def's node id
+        let qualname = String::from_str(name).append("$").append(id.to_str().as_slice());
+        self.check_and_record(Variable,
+                              span,
+                              sub_span,
+                              svec!(id, name, qualname, value, typ, 0));
+    }
+
+    // formal parameters
+    pub fn formal_str(&mut self,
+                      span: Span,
+                      sub_span: Option<Span>,
+                      id: NodeId,
+                      fn_name: &str,
+                      name: &str,
+                      typ: &str) {
+        let qualname = String::from_str(fn_name).append("::").append(name);
+        self.check_and_record(Variable,
+                              span,
+                              sub_span,
+                              svec!(id, name, qualname, "", typ, 0));
+    }
+
+    // value is the initialising expression of the static if it is not mut, otherwise "".
+    pub fn static_str(&mut self,
+                      span: Span,
+                      sub_span: Option<Span>,
+                      id: NodeId,
+                      name: &str,
+                      qualname: &str,
+                      value: &str,
+                      typ: &str,
+                      scope_id: NodeId) {
+        self.check_and_record(Variable,
+                              span,
+                              sub_span,
+                              svec!(id, name, qualname, value, typ, scope_id));
+    }
+
+    pub fn field_str(&mut self,
+                     span: Span,
+                     sub_span: Option<Span>,
+                     id: NodeId,
+                     name: &str,
+                     qualname: &str,
+                     typ: &str,
+                     scope_id: NodeId) {
+        self.check_and_record(Variable,
+                              span,
+                              sub_span,
+                              svec!(id, name, qualname, "", typ, scope_id));
+    }
+
+    pub fn enum_str(&mut self,
+                    span: Span,
+                    sub_span: Option<Span>,
+                    id: NodeId,
+                    name: &str,
+                    scope_id: NodeId) {
+        self.check_and_record(Enum,
+                              span,
+                              sub_span,
+                              svec!(id, name, scope_id));
+    }
+
+    pub fn tuple_variant_str(&mut self,
+                             span: Span,
+                             sub_span: Option<Span>,
+                             id: NodeId,
+                             name: &str,
+                             qualname: &str,
+                             val: &str,
+                             scope_id: NodeId) {
+        self.check_and_record(Variant,
+                              span,
+                              sub_span,
+                              svec!(id, name, qualname, val, scope_id));
+    }
+
+    pub fn struct_variant_str(&mut self,
+                              span: Span,
+                              sub_span: Option<Span>,
+                              id: NodeId,
+                              ctor_id: NodeId,
+                              name: &str,
+                              val: &str,
+                              scope_id: NodeId) {
+        self.check_and_record(VariantStruct,
+                              span,
+                              sub_span,
+                              svec!(id, ctor_id, name, val, scope_id));
+    }
+
+    pub fn fn_str(&mut self,
+                  span: Span,
+                  sub_span: Option<Span>,
+                  id: NodeId,
+                  name: &str,
+                  scope_id: NodeId) {
+        self.check_and_record(Function,
+                              span,
+                              sub_span,
+                              svec!(id, name, "", "", scope_id));
+    }
+
+    pub fn method_str(&mut self,
+                      span: Span,
+                      sub_span: Option<Span>,
+                      id: NodeId,
+                      name: &str,
+                      decl_id: Option<DefId>,
+                      scope_id: NodeId) {
+        let values = match decl_id {
+            Some(decl_id) => svec!(id, name, decl_id.node, decl_id.krate, scope_id),
+            None => svec!(id, name, "", "", scope_id)
+        };
+        self.check_and_record(Function,
+                              span,
+                              sub_span,
+                              values);
+    }
+
+    pub fn method_decl_str(&mut self,
+                           span: Span,
+                           sub_span: Option<Span>,
+                           id: NodeId,
+                           name: &str,
+                           scope_id: NodeId) {
+        self.check_and_record(MethodDecl,
+                              span,
+                              sub_span,
+                              svec!(id, name, scope_id));
+    }
+
+    pub fn struct_str(&mut self,
+                      span: Span,
+                      sub_span: Option<Span>,
+                      id: NodeId,
+                      ctor_id: NodeId,
+                      name: &str,
+                      scope_id: NodeId) {
+        self.check_and_record(Struct,
+                              span,
+                              sub_span,
+                              svec!(id, ctor_id, name, scope_id));
+    }
+
+    pub fn trait_str(&mut self,
+                     span: Span,
+                     sub_span: Option<Span>,
+                     id: NodeId,
+                     name: &str,
+                     scope_id: NodeId) {
+        self.check_and_record(Trait,
+                              span,
+                              sub_span,
+                              svec!(id, name, scope_id));
+    }
+
+    pub fn impl_str(&mut self,
+                    span: Span,
+                    sub_span: Option<Span>,
+                    id: NodeId,
+                    ref_id: DefId,
+                    scope_id: NodeId) {
+        self.check_and_record(Impl,
+                              span,
+                              sub_span,
+                              svec!(id, ref_id.node, ref_id.krate, scope_id));
+    }
+
+    pub fn mod_str(&mut self,
+                   span: Span,
+                   sub_span: Option<Span>,
+                   id: NodeId,
+                   name: &str,
+                   parent: NodeId,
+                   filename: &str) {
+        self.check_and_record(Module,
+                              span,
+                              sub_span,
+                              svec!(id, name, parent, filename));
+    }
+
+    pub fn use_alias_str(&mut self,
+                         span: Span,
+                         sub_span: Option<Span>,
+                         id: NodeId,
+                         mod_id: Option<DefId>,
+                         name: &str,
+                         parent: NodeId) {
+        let (mod_node, mod_crate) = match mod_id {
+            Some(mod_id) => (mod_id.node, mod_id.krate),
+            None => (0, 0)
+        };
+        self.check_and_record(UseAlias,
+                              span,
+                              sub_span,
+                              svec!(id, mod_node, mod_crate, name, parent));
+    }
+
+    pub fn extern_crate_str(&mut self,
+                          span: Span,
+                          sub_span: Option<Span>,
+                          id: NodeId,
+                          cnum: ast::CrateNum,
+                          name: &str,
+                          loc: &str,
+                          parent: NodeId) {
+        self.check_and_record(ExternCrate,
+                              span,
+                              sub_span,
+                              svec!(id, name, loc, cnum, parent));
+    }
+
+    pub fn inherit_str(&mut self,
+                       span: Span,
+                       sub_span: Option<Span>,
+                       base_id: DefId,
+                       deriv_id: NodeId) {
+        self.check_and_record(Inheritance,
+                              span,
+                              sub_span,
+                              svec!(base_id.node, base_id.krate, deriv_id, 0));
+    }
+
+    pub fn fn_call_str(&mut self,
+                       span: Span,
+                       sub_span: Option<Span>,
+                       id: DefId,
+                       scope_id:NodeId) {
+        self.check_and_record(FnCall,
+                              span,
+                              sub_span,
+                              svec!(id.node, id.krate, "", scope_id));
+    }
+
+    pub fn meth_call_str(&mut self,
+                         span: Span,
+                         sub_span: Option<Span>,
+                         defid: Option<DefId>,
+                         declid: Option<DefId>,
+                         scope_id: NodeId) {
+        let (dfn, dfk) = match defid {
+            Some(defid) => (defid.node, defid.krate),
+            None => (0, 0)
+        };
+        let (dcn, dck) = match declid {
+            Some(declid) => (s!(declid.node), s!(declid.krate)),
+            None => ("".to_owned(), "".to_owned())
+        };
+        self.check_and_record(MethodCall,
+                              span,
+                              sub_span,
+                              svec!(dfn, dfk, dcn, dck, scope_id));
+    }
+
+    pub fn sub_mod_ref_str(&mut self,
+                           span: Span,
+                           sub_span: Span,
+                           qualname: &str,
+                           parent:NodeId) {
+        self.record_with_span(ModRef,
+                              span,
+                              sub_span,
+                              svec!(0, 0, qualname, parent));
+    }
+
+    pub fn typedef_str(&mut self,
+                       span: Span,
+                       sub_span: Option<Span>,
+                       id: NodeId,
+                       qualname: &str,
+                       value: &str) {
+        self.check_and_record(Typedef,
+                              span,
+                              sub_span,
+                              svec!(id, qualname, value));
+    }
+
+    pub fn crate_str(&mut self,
+                     span: Span,
+                     name: &str) {
+        self.record_with_span(Crate,
+                              span,
+                              span,
+                              svec!(name));
+    }
+
+    pub fn external_crate_str(&mut self,
+                              span: Span,
+                              name: &str,
+                              num: ast::CrateNum) {
+        let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
+        self.record_without_span(ExternalCrate,
+                                 svec!(name, num, lo_loc.file.name),
+                                 span);
+    }
+
+    pub fn sub_type_ref_str(&mut self,
+                            span: Span,
+                            sub_span: Span,
+                            qualname: &str) {
+        self.record_with_span(TypeRef,
+                              span,
+                              sub_span,
+                              svec!(0, 0, qualname, 0));
+    }
+
+    // A slightly generic function for a reference to an item of any kind.
+    pub fn ref_str(&mut self,
+                   kind: Row,
+                   span: Span,
+                   sub_span: Option<Span>,
+                   id: DefId,
+                   scope_id: NodeId) {
+        self.check_and_record(kind,
+                              span,
+                              sub_span,
+                              svec!(id.node, id.krate, "", scope_id));
+    }
+}
diff --git a/src/librustc/middle/save/span_utils.rs b/src/librustc/middle/save/span_utils.rs
new file mode 100644 (file)
index 0000000..e646827
--- /dev/null
@@ -0,0 +1,381 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use driver::session::Session;
+
+use middle::save::generated_code;
+
+use std::cell::Cell;
+
+use syntax::ast;
+use syntax::codemap::*;
+use syntax::parse::lexer;
+use syntax::parse::lexer::{Reader,StringReader};
+use syntax::parse::token;
+use syntax::parse::token::{is_keyword,keywords,is_ident,Token};
+
+pub struct SpanUtils<'a> {
+    pub sess: &'a Session,
+    pub err_count: Cell<int>,
+}
+
+impl<'a> SpanUtils<'a> {
+    // Standard string for extents/location.
+    pub fn extent_str(&self, span: Span) -> String {
+        let lo_loc = self.sess.codemap().lookup_char_pos(span.lo);
+        let hi_loc = self.sess.codemap().lookup_char_pos(span.hi);
+        let lo_pos = self.sess.codemap().lookup_byte_offset(span.lo).pos;
+        let hi_pos = self.sess.codemap().lookup_byte_offset(span.hi).pos;
+
+        format!("file_name,{},file_line,{},file_col,{},extent_start,{},\
+                 file_line_end,{},file_col_end,{},extent_end,{}",
+                lo_loc.file.name, lo_loc.line, lo_loc.col.to_uint(), lo_pos.to_uint(),
+                hi_loc.line, hi_loc.col.to_uint(), hi_pos.to_uint())
+    }
+
+    // sub_span starts at span.lo, so we need to adjust the positions etc.
+    // If sub_span is None, we don't need to adjust.
+    pub fn make_sub_span(&self, span: Span, sub_span: Option<Span>) -> Option<Span> {
+        let loc = self.sess.codemap().lookup_char_pos(span.lo);
+        assert!(!generated_code(span),
+                "generated code; we should not be processing this `{}` in {}, line {}",
+                 self.snippet(span), loc.file.name, loc.line);
+
+        match sub_span {
+            None => None,
+            Some(sub) => {
+                let FileMapAndBytePos {fm, pos} =
+                    self.sess.codemap().lookup_byte_offset(span.lo);
+                let base = pos + fm.start_pos;
+                Some(Span {
+                    lo: base + self.sess.codemap().lookup_byte_offset(sub.lo).pos,
+                    hi: base + self.sess.codemap().lookup_byte_offset(sub.hi).pos,
+                    expn_info: None,
+                })
+            }
+        }
+    }
+
+    pub fn snippet(&self, span: Span) -> String {
+        match self.sess.codemap().span_to_snippet(span) {
+            Some(s) => s,
+            None => String::new(),
+        }
+    }
+
+    pub fn retokenise_span(&self, span: Span) -> StringReader<'a> {
+        // sadness - we don't have spans for sub-expressions nor access to the tokens
+        // so in order to get extents for the function name itself (which dxr expects)
+        // we need to re-tokenise the fn definition
+
+        // Note: this is a bit awful - it adds the contents of span to the end of
+        // the codemap as a new filemap. This is mostly OK, but means we should
+        // not iterate over the codemap. Also, any spans over the new filemap
+        // are incompatible with spans over other filemaps.
+        let filemap = self.sess.codemap().new_filemap(String::from_str("<anon-dxr>"),
+                                                      self.snippet(span));
+        let s = self.sess;
+        lexer::StringReader::new(s.diagnostic(), filemap)
+    }
+
+    // Re-parses a path and returns the span for the last identifier in the path
+    pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
+        let mut result = None;
+
+        let mut toks = self.retokenise_span(span);
+        let mut bracket_count = 0;
+        loop {
+            let ts = toks.next_token();
+            if ts.tok == token::EOF {
+                return self.make_sub_span(span, result)
+            }
+            if bracket_count == 0 &&
+               (is_ident(&ts.tok) || is_keyword(keywords::Self, &ts.tok)) {
+                result = Some(ts.sp);
+            }
+
+            bracket_count += match ts.tok {
+                token::LT => 1,
+                token::GT => -1,
+                token::BINOP(token::SHR) => -2,
+                _ => 0
+            }
+        }
+    }
+
+    // Return the span for the first identifier in the path.
+    pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
+        let mut toks = self.retokenise_span(span);
+        let mut bracket_count = 0;
+        loop {
+            let ts = toks.next_token();
+            if ts.tok == token::EOF {
+                return None;
+            }
+            if bracket_count == 0 &&
+               (is_ident(&ts.tok) || is_keyword(keywords::Self, &ts.tok)) {
+                return self.make_sub_span(span, Some(ts.sp));
+            }
+
+            bracket_count += match ts.tok {
+                token::LT => 1,
+                token::GT => -1,
+                token::BINOP(token::SHR) => -2,
+                _ => 0
+            }
+        }
+    }
+
+    // Return the span for the last ident before a `(` or `<` or '::<' and outside any
+    // any brackets, or the last span.
+    pub fn sub_span_for_meth_name(&self, span: Span) -> Option<Span> {
+        let mut toks = self.retokenise_span(span);
+        let mut prev = toks.next_token();
+        let mut result = None;
+        let mut bracket_count = 0;
+        let mut last_span = None;
+        while prev.tok != token::EOF {
+            last_span = None;
+            let mut next = toks.next_token();
+
+            if (next.tok == token::LPAREN ||
+                next.tok == token::LT) &&
+               bracket_count == 0 &&
+               is_ident(&prev.tok) {
+                result = Some(prev.sp);
+            }
+
+            if bracket_count == 0 &&
+                next.tok == token::MOD_SEP {
+                let old = prev;
+                prev = next;
+                next = toks.next_token();
+                if next.tok == token::LT &&
+                   is_ident(&old.tok) {
+                    result = Some(old.sp);
+                }
+            }
+
+            bracket_count += match prev.tok {
+                token::LPAREN | token::LT => 1,
+                token::RPAREN | token::GT => -1,
+                token::BINOP(token::SHR) => -2,
+                _ => 0
+            };
+
+            if is_ident(&prev.tok) && bracket_count == 0 {
+                last_span = Some(prev.sp);
+            }
+            prev = next;
+        }
+        if result.is_none() && last_span.is_some() {
+            return self.make_sub_span(span, last_span);
+        }
+        return self.make_sub_span(span, result);
+    }
+
+    // Return the span for the last ident before a `<` and outside any
+    // brackets, or the last span.
+    pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
+        let mut toks = self.retokenise_span(span);
+        let mut prev = toks.next_token();
+        let mut result = None;
+        let mut bracket_count = 0;
+        loop {
+            let next = toks.next_token();
+
+            if (next.tok == token::LT ||
+                next.tok == token::COLON) &&
+               bracket_count == 0 &&
+               is_ident(&prev.tok) {
+                result = Some(prev.sp);
+            }
+
+            bracket_count += match prev.tok {
+                token::LT => 1,
+                token::GT => -1,
+                token::BINOP(token::SHR) => -2,
+                _ => 0
+            };
+
+            if next.tok == token::EOF {
+                break;
+            }
+            prev = next;
+        }
+        if bracket_count != 0 {
+            let loc = self.sess.codemap().lookup_char_pos(span.lo);
+            self.sess.span_bug(span,
+                format!("Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
+                        self.snippet(span), loc.file.name, loc.line).as_slice());
+        }
+        if result.is_none() && is_ident(&prev.tok) && bracket_count == 0 {
+            return self.make_sub_span(span, Some(prev.sp));
+        }
+        self.make_sub_span(span, result)
+    }
+
+    // Reparse span and return an owned vector of sub spans of the first limit
+    // identifier tokens in the given nesting level.
+    // example with Foo<Bar<T,V>, Bar<T,V>>
+    // Nesting = 0: all idents outside of brackets: ~[Foo]
+    // Nesting = 1: idents within one level of brackets: ~[Bar, Bar]
+    pub fn spans_with_brackets(&self, span: Span, nesting: int, limit: int) -> Vec<Span> {
+        let mut result: Vec<Span> = vec!();
+
+        let mut toks = self.retokenise_span(span);
+        // We keep track of how many brackets we're nested in
+        let mut bracket_count = 0;
+        loop {
+            let ts = toks.next_token();
+            if ts.tok == token::EOF {
+                if bracket_count != 0 {
+                    let loc = self.sess.codemap().lookup_char_pos(span.lo);
+                    self.sess.span_bug(span, format!(
+                        "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
+                         self.snippet(span), loc.file.name, loc.line).as_slice());
+                }
+                return result
+            }
+            if (result.len() as int) == limit {
+                return result;
+            }
+            bracket_count += match ts.tok {
+                token::LT => 1,
+                token::GT => -1,
+                token::BINOP(token::SHL) => 2,
+                token::BINOP(token::SHR) => -2,
+                _ => 0
+            };
+            if is_ident(&ts.tok) &&
+               bracket_count == nesting {
+                result.push(self.make_sub_span(span, Some(ts.sp)).unwrap());
+            }
+        }
+    }
+
+    pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
+        let mut toks = self.retokenise_span(span);
+        let mut prev = toks.next_token();
+        loop {
+            if prev.tok == token::EOF {
+                return None;
+            }
+            let next = toks.next_token();
+            if next.tok == tok {
+                return self.make_sub_span(span, Some(prev.sp));
+            }
+            prev = next;
+        }
+    }
+
+    // Return an owned vector of the subspans of the tokens that come before tok2
+    // which is before tok1. If there is no instance of tok2 before tok1, then that
+    // place in the result is None.
+    // Everything returned must be inside a set of (non-angle) brackets, but no
+    // more deeply nested than that.
+    pub fn sub_spans_before_tokens(&self,
+                               span: Span,
+                               tok1: Token,
+                               tok2: Token) -> Vec<Option<Span>> {
+        let mut sub_spans : Vec<Option<Span>> = vec!();
+        let mut toks = self.retokenise_span(span);
+        let mut prev = toks.next_token();
+        let mut next = toks.next_token();
+        let mut stored_val = false;
+        let mut found_val = false;
+        let mut bracket_count = 0;
+        while next.tok != token::EOF {
+            if bracket_count == 1 {
+                if next.tok == tok2 {
+                    sub_spans.push(self.make_sub_span(span, Some(prev.sp)));
+                    stored_val = true;
+                    found_val = false;
+                }
+                if next.tok == tok1 {
+                    if !stored_val {
+                        sub_spans.push(None);
+                    } else {
+                        stored_val = false;
+                    }
+                    found_val = false;
+                }
+                if !stored_val &&
+                   is_ident(&next.tok) {
+                    found_val = true;
+                }
+            }
+
+            bracket_count += match next.tok {
+                token::LPAREN | token::LBRACE => 1,
+                token::RPAREN | token::RBRACE => -1,
+                _ => 0
+            };
+
+            prev = next;
+            next = toks.next_token();
+        }
+        if found_val {
+            sub_spans.push(None);
+        }
+        return sub_spans;
+    }
+
+    pub fn sub_span_after_keyword(&self,
+                              span: Span,
+                              keyword: keywords::Keyword) -> Option<Span> {
+        let mut toks = self.retokenise_span(span);
+        loop {
+            let ts = toks.next_token();
+            if ts.tok == token::EOF {
+                return None;
+            }
+            if is_keyword(keyword, &ts.tok) {
+                let ts = toks.next_token();
+                if ts.tok == token::EOF {
+                    return None
+                } else {
+                    return self.make_sub_span(span, Some(ts.sp));
+                }
+            }
+        }
+    }
+
+    // Returns a list of the spans of idents in a patch.
+    // E.g., For foo::bar<x,t>::baz, we return [foo, bar, baz] (well, their spans)
+    pub fn spans_for_path_segments(&self, path: &ast::Path) -> Vec<Span> {
+        if generated_code(path.span) {
+            return vec!();
+        }
+
+        self.spans_with_brackets(path.span, 0, -1)
+    }
+
+    // Return an owned vector of the subspans of the param identifier
+    // tokens found in span.
+    pub fn spans_for_ty_params(&self, span: Span, number: int) -> Vec<Span> {
+        if generated_code(span) {
+            return vec!();
+        }
+        // Type params are nested within one level of brackets:
+        // i.e. we want ~[A, B] from Foo<A, B<T,U>>
+        self.spans_with_brackets(span, 1, number)
+    }
+
+    pub fn report_span_err(&self, kind: &str, span: Span) {
+        let loc = self.sess.codemap().lookup_char_pos(span.lo);
+        info!("({}) Could not find sub_span in `{}` in {}, line {}",
+              kind, self.snippet(span), loc.file.name, loc.line);
+        self.err_count.set(self.err_count.get()+1);
+        if self.err_count.get() > 1000 {
+            self.sess.bug("span errors reached 1000, giving up");
+        }
+    }
+}
index db17000abb32b188c26477794b18e29de05e22d4..0b10db56cc42696eae3b5e68b52f50274e324c32 100644 (file)
@@ -122,9 +122,37 @@ struct List {
 `llvm.dbg.declare` instructions to the correct source locations even while source location emission
 is still disabled, so there is no need to do anything special with source location handling here.
 
+## Unique Type Identification
+In order for link-time optimization to work properly, LLVM needs a unique type identifier that tells
+it across compilation units which types are the same as others. This type identifier is created by
+TypeMap::get_unique_type_id_of_type() using the following algorithm:
+
+(1) Primitive types have their name as ID
+(2) Structs, enums and traits have a multipart identifier
+    (1) The first part is the SVH (strict version hash) of the crate they were originally defined in
+    (2) The second part is the ast::NodeId of the definition in their original crate
+    (3) The final part is a concatenation of the type IDs of their concrete type arguments if they
+        are generic types.
+(3) Tuple-, pointer and function types are structurally identified, which means that they are
+    equivalent if their component types are equivalent (i.e. (int, int) is the same regardless in
+    which crate it is used).
+
+This algorithm also provides a stable ID for types that are defined in one crate but instantiated
+from metadata within another crate. We just have to take care to always map crate and node IDs back
+to the original crate context.
+
+As a side-effect these unique type IDs also help to solve a problem arising from lifetime
+parameters. Since lifetime parameters are completely omitted in debuginfo, more than one `ty::t`
+instance may map to the same debuginfo type metadata, that is, some struct `Struct<'a>` may have N
+instantiations with different concrete substitutions for `'a`, and thus there will be N `ty::t`
+instances for the type `Struct<'a>` even though it is not generic otherwise. Unfortunately this
+means that we cannot use `ty::type_id()` as cheap identifier for type metadata---we have done this
+in the past, but it led to unnecessary metadata duplication in the best case and LLVM assertions in
+the worst. However, the unique type ID as described above *can* be used as identifier. Since it is
+comparatively expensive to construct, though, `ty::type_id()` is still used additionally as an
+optimization for cases where the exact same type has been seen before (which is most of the time).
 */
 
-
 use driver::config;
 use driver::config::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
 use lib::llvm::llvm;
@@ -151,7 +179,7 @@ struct List {
 use std::gc::Gc;
 use std::ptr;
 use std::rc::{Rc, Weak};
-use std::sync::atomics;
+use syntax::util::interner::Interner;
 use syntax::codemap::{Span, Pos};
 use syntax::{abi, ast, codemap, ast_util, ast_map};
 use syntax::owned_slice::OwnedSlice;
@@ -166,7 +194,6 @@ struct List {
 static DW_ATE_boolean: c_uint = 0x02;
 static DW_ATE_float: c_uint = 0x04;
 static DW_ATE_signed: c_uint = 0x05;
-// static DW_ATE_signed_char: c_uint = 0x06;
 static DW_ATE_unsigned: c_uint = 0x07;
 static DW_ATE_unsigned_char: c_uint = 0x08;
 
@@ -174,15 +201,370 @@ struct List {
 //  Public Interface of debuginfo module
 //=-------------------------------------------------------------------------------------------------
 
+#[deriving(Copy, Show, Hash, Eq, PartialEq, Clone)]
+struct UniqueTypeId(ast::Name);
+
+// The TypeMap is where the CrateDebugContext holds the type metadata nodes created so far. The
+// metadata nodes are indexed by UniqueTypeId, and, for faster lookup, also by ty::t. The
+// TypeMap is responsible for creating UniqueTypeIds.
+struct TypeMap {
+    // The UniqueTypeIds created so far
+    unique_id_interner: Interner<Rc<String>>,
+    // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping.
+    unique_id_to_metadata: HashMap<UniqueTypeId, DIType>,
+    // A map from ty::type_id() to debuginfo metadata. This is a N:1 mapping.
+    type_to_metadata: HashMap<uint, DIType>,
+    // A map from ty::type_id() to UniqueTypeId. This is a N:1 mapping.
+    type_to_unique_id: HashMap<uint, UniqueTypeId>
+}
+
+impl TypeMap {
+
+    fn new() -> TypeMap {
+        TypeMap {
+            unique_id_interner: Interner::new(),
+            type_to_metadata: HashMap::new(),
+            unique_id_to_metadata: HashMap::new(),
+            type_to_unique_id: HashMap::new(),
+        }
+    }
+
+    // Adds a ty::t to metadata mapping to the TypeMap. The method will fail if the mapping already
+    // exists.
+    fn register_type_with_metadata(&mut self,
+                                   cx: &CrateContext,
+                                   type_: ty::t,
+                                   metadata: DIType) {
+        if !self.type_to_metadata.insert(ty::type_id(type_), metadata) {
+            cx.sess().bug(format!("Type metadata for ty::t '{}' is already in the TypeMap!",
+                                  ppaux::ty_to_str(cx.tcx(), type_)).as_slice());
+        }
+    }
+
+    // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will fail if the mapping
+    // already exists.
+    fn register_unique_id_with_metadata(&mut self,
+                                        cx: &CrateContext,
+                                        unique_type_id: UniqueTypeId,
+                                        metadata: DIType) {
+        if !self.unique_id_to_metadata.insert(unique_type_id, metadata) {
+            let unique_type_id_str = self.get_unique_type_id_as_string(unique_type_id);
+            cx.sess().bug(format!("Type metadata for unique id '{}' is already in the TypeMap!",
+                                  unique_type_id_str.as_slice()).as_slice());
+        }
+    }
+
+    fn find_metadata_for_type(&self, type_: ty::t) -> Option<DIType> {
+        self.type_to_metadata.find_copy(&ty::type_id(type_))
+    }
+
+    fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<DIType> {
+        self.unique_id_to_metadata.find_copy(&unique_type_id)
+    }
+
+    // Get the string representation of a UniqueTypeId. This method will fail if the id is unknown.
+    fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> Rc<String> {
+        let UniqueTypeId(interner_key) = unique_type_id;
+        self.unique_id_interner.get(interner_key)
+    }
+
+    // Get the UniqueTypeId for the given type. If the UniqueTypeId for the given type has been
+    // requested before, this is just a table lookup. Otherwise an ID will be generated and stored
+    // for later lookup.
+    fn get_unique_type_id_of_type(&mut self, cx: &CrateContext, type_: ty::t) -> UniqueTypeId {
+
+        // basic type           -> {:name of the type:}
+        // tuple                -> {tuple_(:param-uid:)*}
+        // struct               -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
+        // enum                 -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
+        // enum variant         -> {variant_:variant-name:_:enum-uid:}
+        // reference (&)        -> {& :pointee-uid:}
+        // mut reference (&mut) -> {&mut :pointee-uid:}
+        // ptr (*)              -> {* :pointee-uid:}
+        // mut ptr (*mut)       -> {*mut :pointee-uid:}
+        // unique ptr (~)       -> {~ :pointee-uid:}
+        // @-ptr (@)            -> {@ :pointee-uid:}
+        // sized vec ([T, ..x]) -> {[:size:] :element-uid:}
+        // vec slice (&[T])     -> {&<mut> [] :element-uid:}
+        // trait (~ | &[mut] T) -> {:sigil: trait_:svh: / :node-id:_<(:param-uid:),*> }
+        // closure              -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
+        //                             :return-type-uid: : (:bounds:)*}
+        // function             -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
+        //                             :return-type-uid:}
+
+        match self.type_to_unique_id.find_copy(&ty::type_id(type_)) {
+            Some(unique_type_id) => return unique_type_id,
+            None => { /* generate one */}
+        };
+
+        let mut unique_type_id = String::with_capacity(256);
+        unique_type_id.push_char('{');
+
+        match ty::get(type_).sty {
+            ty::ty_nil                |
+            ty::ty_bot                |
+            ty::ty_bool               |
+            ty::ty_char               |
+            ty::ty_str                |
+            ty::ty_int(_)             |
+            ty::ty_uint(_)            |
+            ty::ty_float(_) => {
+                unique_type_id.push_str(ppaux::ty_to_str(cx.tcx(), type_).as_slice());
+            },
+            ty::ty_enum(def_id, ref substs) => {
+                unique_type_id.push_str("enum ");
+                from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
+            },
+            ty::ty_struct(def_id, ref substs) => {
+                unique_type_id.push_str("struct ");
+                from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
+            },
+            ty::ty_tup(ref component_types) => {
+                unique_type_id.push_str("tuple ");
+                for &component_type in component_types.iter() {
+                    let component_type_id = self.get_unique_type_id_of_type(cx, component_type);
+                    let component_type_id = self.get_unique_type_id_as_string(component_type_id);
+                    unique_type_id.push_str(component_type_id.as_slice());
+                }
+            },
+            ty::ty_box(inner_type) => {
+                unique_type_id.push_char('@');
+                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
+                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
+                unique_type_id.push_str(inner_type_id.as_slice());
+            },
+            ty::ty_uniq(inner_type) => {
+                unique_type_id.push_char('~');
+                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
+                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
+                unique_type_id.push_str(inner_type_id.as_slice());
+            },
+            ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
+                unique_type_id.push_char('*');
+                if mutbl == ast::MutMutable {
+                    unique_type_id.push_str("mut");
+                }
+
+                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
+                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
+                unique_type_id.push_str(inner_type_id.as_slice());
+            },
+            ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => {
+                unique_type_id.push_char('&');
+                if mutbl == ast::MutMutable {
+                    unique_type_id.push_str("mut");
+                }
+
+                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
+                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
+                unique_type_id.push_str(inner_type_id.as_slice());
+            },
+            ty::ty_vec(ty::mt { ty: inner_type, mutbl }, optional_length) => {
+                match optional_length {
+                    Some(len) => {
+                        unique_type_id.push_str(format!("[{}]", len).as_slice());
+                    }
+                    None => {
+                        unique_type_id.push_char('&');
+
+                        if mutbl == ast::MutMutable {
+                           unique_type_id.push_str("mut");
+                        }
+
+                        unique_type_id.push_str("[]");
+                    }
+                };
+
+                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
+                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
+                unique_type_id.push_str(inner_type_id.as_slice());
+            },
+            ty::ty_trait(ref trait_data) => {
+                match trait_data.store {
+                    ty::UniqTraitStore => unique_type_id.push_char('~'),
+                    ty::RegionTraitStore(_, ast::MutMutable) => unique_type_id.push_str("&mut"),
+                    ty::RegionTraitStore(_, ast::MutImmutable) => unique_type_id.push_char('&'),
+                };
+
+                unique_type_id.push_str("trait ");
+
+                from_def_id_and_substs(self,
+                                       cx,
+                                       trait_data.def_id,
+                                       &trait_data.substs,
+                                       &mut unique_type_id);
+            },
+            ty::ty_bare_fn(ty::BareFnTy{ fn_style, abi, ref sig } ) => {
+                if fn_style == ast::UnsafeFn {
+                    unique_type_id.push_str("unsafe ");
+                }
+
+                unique_type_id.push_str(abi.name());
+
+                unique_type_id.push_str(" fn(");
+
+                for &parameter_type in sig.inputs.iter() {
+                    let parameter_type_id = self.get_unique_type_id_of_type(cx, parameter_type);
+                    let parameter_type_id = self.get_unique_type_id_as_string(parameter_type_id);
+                    unique_type_id.push_str(parameter_type_id.as_slice());
+                    unique_type_id.push_char(',');
+                }
+
+                if sig.variadic {
+                    unique_type_id.push_str("...");
+                }
+
+                unique_type_id.push_str(")->");
+                let return_type_id = self.get_unique_type_id_of_type(cx, sig.output);
+                let return_type_id = self.get_unique_type_id_as_string(return_type_id);
+                unique_type_id.push_str(return_type_id.as_slice());
+            },
+            ty::ty_closure(box ty::ClosureTy { fn_style,
+                                               onceness,
+                                               store,
+                                               ref bounds,
+                                               ref sig }) => {
+                if fn_style == ast::UnsafeFn {
+                    unique_type_id.push_str("unsafe ");
+                }
+
+                if onceness == ast::Once {
+                    unique_type_id.push_str("once ");
+                }
+
+                match store {
+                    ty::UniqTraitStore => unique_type_id.push_str("~|"),
+                    ty::RegionTraitStore(_, ast::MutMutable) => unique_type_id.push_str("&mut|"),
+                    ty::RegionTraitStore(_, ast::MutImmutable) => unique_type_id.push_str("&|"),
+                };
+
+                for &parameter_type in sig.inputs.iter() {
+                    let parameter_type_id = self.get_unique_type_id_of_type(cx, parameter_type);
+                    let parameter_type_id = self.get_unique_type_id_as_string(parameter_type_id);
+                    unique_type_id.push_str(parameter_type_id.as_slice());
+                    unique_type_id.push_char(',');
+                }
+
+                if sig.variadic {
+                    unique_type_id.push_str("...");
+                }
+
+                unique_type_id.push_str("|->");
+
+                let return_type_id = self.get_unique_type_id_of_type(cx, sig.output);
+                let return_type_id = self.get_unique_type_id_as_string(return_type_id);
+                unique_type_id.push_str(return_type_id.as_slice());
+
+                unique_type_id.push_char(':');
+
+                for bound in bounds.iter() {
+                    match bound {
+                        ty::BoundStatic => unique_type_id.push_str("'static"),
+                        ty::BoundSend => unique_type_id.push_str("Send"),
+                        ty::BoundSized => unique_type_id.push_str("Sized"),
+                        ty::BoundCopy => unique_type_id.push_str("Copy"),
+                        ty::BoundShare => unique_type_id.push_str("Share"),
+                    };
+                    unique_type_id.push_char('+');
+                }
+            },
+            _ => {
+                cx.sess().bug(format!("get_unique_type_id_of_type() - unexpected type: {}, {:?}",
+                                      ppaux::ty_to_str(cx.tcx(), type_).as_slice(),
+                                      ty::get(type_).sty).as_slice())
+            }
+        };
+
+        unique_type_id.push_char('}');
+
+        // Trim to size before storing permanently
+        unique_type_id.shrink_to_fit();
+
+        let key = self.unique_id_interner.intern(Rc::new(unique_type_id));
+        self.type_to_unique_id.insert(ty::type_id(type_), UniqueTypeId(key));
+
+        return UniqueTypeId(key);
+
+        fn from_def_id_and_substs(type_map: &mut TypeMap,
+                                  cx: &CrateContext,
+                                  def_id: ast::DefId,
+                                  substs: &subst::Substs,
+                                  output: &mut String) {
+            use std::num::ToStrRadix;
+
+            // First, find out the 'real' def_id of the type. Items inlined from other crates have
+            // to be mapped back to their source.
+            let source_def_id = if def_id.krate == ast::LOCAL_CRATE {
+                match cx.external_srcs.borrow().find_copy(&def_id.node) {
+                    Some(source_def_id) => {
+                        // The given def_id identifies the inlined copy of a type definition,
+                        // let's take the source of the copy
+                        source_def_id
+                    }
+                    None => def_id
+                }
+            } else {
+                def_id
+            };
+
+            // Get the crate hash as first part of the identifier
+            let crate_hash = if source_def_id.krate == ast::LOCAL_CRATE {
+                cx.link_meta.crate_hash.clone()
+            } else {
+                cx.sess().cstore.get_crate_hash(source_def_id.krate)
+            };
+
+            output.push_str(crate_hash.as_str());
+            output.push_str("/");
+            output.push_str(def_id.node.to_str_radix(16).as_slice());
+
+            // Maybe check that there is no self type here
+
+            if substs.tps.len() > 0 {
+                output.push_char('<');
+
+                for &type_parameter in substs.tps.iter() {
+                    let param_type_id = type_map.get_unique_type_id_of_type(cx, type_parameter);
+                    let param_type_id = type_map.get_unique_type_id_as_string(param_type_id);
+                    output.push_str(param_type_id.as_slice());
+                    output.push_char(',');
+                }
+
+                output.push_char('>');
+            }
+        }
+    }
+
+    // Get the UniqueTypeId for an enum variant. Enum variants are not really types of their own,
+    // so they need special handling. We still need a UniqueTypeId for them, since to debuginfo they
+    // *are* real types.
+    fn get_unique_type_id_of_enum_variant(&mut self,
+                                          cx: &CrateContext,
+                                          enum_type: ty::t,
+                                          variant_name: &str)
+                                       -> UniqueTypeId {
+        let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type);
+        let enum_variant_type_id = format!("{}::{}",
+                                           self.get_unique_type_id_as_string(enum_type_id)
+                                               .as_slice(),
+                                           variant_name);
+        let interner_key = self.unique_id_interner.intern(Rc::new(enum_variant_type_id));
+        UniqueTypeId(interner_key)
+    }
+}
+
+
 /// A context object for maintaining all state needed by the debuginfo module.
 pub struct CrateDebugContext {
     llcontext: ContextRef,
     builder: DIBuilderRef,
     current_debug_location: Cell<DebugLocation>,
     created_files: RefCell<HashMap<String, DIFile>>,
-    created_types: RefCell<HashMap<uint, DIType>>,
     created_enum_disr_types: RefCell<HashMap<ast::DefId, DIType>>,
+
+    type_map: RefCell<TypeMap>,
     namespace_map: RefCell<HashMap<Vec<ast::Name>, Rc<NamespaceTreeNode>>>,
+
     // This collection is used to assert that composite types (structs, enums, ...) have their
     // members only set once:
     composite_types_completed: RefCell<HashSet<DIType>>,
@@ -199,8 +581,8 @@ pub fn new(llmod: ModuleRef) -> CrateDebugContext {
             builder: builder,
             current_debug_location: Cell::new(UnknownLocation),
             created_files: RefCell::new(HashMap::new()),
-            created_types: RefCell::new(HashMap::new()),
             created_enum_disr_types: RefCell::new(HashMap::new()),
+            type_map: RefCell::new(TypeMap::new()),
             namespace_map: RefCell::new(HashMap::new()),
             composite_types_completed: RefCell::new(HashSet::new()),
         };
@@ -1255,7 +1637,8 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
 // more information.
 enum RecursiveTypeDescription {
     UnfinishedMetadata {
-        cache_id: uint,
+        unfinished_type: ty::t,
+        unique_type_id: UniqueTypeId,
         metadata_stub: DICompositeType,
         llvm_type: Type,
         file_metadata: DIFile,
@@ -1264,6 +1647,31 @@ enum RecursiveTypeDescription {
     FinalMetadata(DICompositeType)
 }
 
+fn create_and_register_recursive_type_forward_declaration(
+    cx: &CrateContext,
+    unfinished_type: ty::t,
+    unique_type_id: UniqueTypeId,
+    metadata_stub: DICompositeType,
+    llvm_type: Type,
+    file_metadata: DIFile,
+    member_description_factory: MemberDescriptionFactory)
+ -> RecursiveTypeDescription {
+
+    // Insert the stub into the TypeMap in order to allow for recursive references
+    let mut type_map = debug_context(cx).type_map.borrow_mut();
+    type_map.register_unique_id_with_metadata(cx, unique_type_id, metadata_stub);
+    type_map.register_type_with_metadata(cx, unfinished_type, metadata_stub);
+
+    UnfinishedMetadata {
+        unfinished_type: unfinished_type,
+        unique_type_id: unique_type_id,
+        metadata_stub: metadata_stub,
+        llvm_type: llvm_type,
+        file_metadata: file_metadata,
+        member_description_factory: member_description_factory,
+    }
+}
+
 impl RecursiveTypeDescription {
     // Finishes up the description of the type in question (mostly by providing descriptions of the
     // fields of the given type) and returns the final type metadata.
@@ -1271,15 +1679,27 @@ fn finalize(&self, cx: &CrateContext) -> DICompositeType {
         match *self {
             FinalMetadata(metadata) => metadata,
             UnfinishedMetadata {
-                cache_id,
+                unfinished_type,
+                unique_type_id,
                 metadata_stub,
                 llvm_type,
                 file_metadata,
                 ref member_description_factory
             } => {
-                // Insert the stub into the cache in order to allow recursive references ...
-                debug_context(cx).created_types.borrow_mut()
-                                 .insert(cache_id, metadata_stub);
+                // Make sure that we have a forward declaration of the type in the TypeMap so that
+                // recursive references are possible. This will always be the case if the
+                // RecursiveTypeDescription has been properly created through the
+                // create_and_register_recursive_type_forward_declaration() function.
+                {
+                    let type_map = debug_context(cx).type_map.borrow();
+                    if type_map.find_metadata_for_unique_id(unique_type_id).is_none() ||
+                       type_map.find_metadata_for_type(unfinished_type).is_none() {
+                        cx.sess().bug(format!("Forward declaration of potentially recursive type \
+                                              '{}' was not found in TypeMap!",
+                                              ppaux::ty_to_str(cx.tcx(), unfinished_type))
+                                      .as_slice());
+                    }
+                }
 
                 // ... then create the member descriptions ...
                 let member_descriptions = member_description_factory.create_member_descriptions(cx);
@@ -1349,6 +1769,7 @@ fn prepare_struct_metadata(cx: &CrateContext,
                            struct_type: ty::t,
                            def_id: ast::DefId,
                            substs: &subst::Substs,
+                           unique_type_id: UniqueTypeId,
                            span: Span)
                         -> RecursiveTypeDescription {
     let struct_name = ppaux::ty_to_str(cx.tcx(), struct_type);
@@ -1362,23 +1783,26 @@ fn prepare_struct_metadata(cx: &CrateContext,
     let struct_metadata_stub = create_struct_stub(cx,
                                                   struct_llvm_type,
                                                   struct_name.as_slice(),
+                                                  unique_type_id,
                                                   containing_scope,
                                                   file_metadata,
                                                   definition_span);
 
     let fields = ty::struct_fields(cx.tcx(), def_id, substs);
 
-    UnfinishedMetadata {
-        cache_id: cache_id_for_type(struct_type),
-        metadata_stub: struct_metadata_stub,
-        llvm_type: struct_llvm_type,
-        file_metadata: file_metadata,
-        member_description_factory: StructMDF(StructMemberDescriptionFactory {
+    create_and_register_recursive_type_forward_declaration(
+        cx,
+        struct_type,
+        unique_type_id,
+        struct_metadata_stub,
+        struct_llvm_type,
+        file_metadata,
+        StructMDF(StructMemberDescriptionFactory {
             fields: fields,
             is_simd: ty::type_is_simd(cx.tcx(), struct_type),
             span: span,
-        }),
-    }
+        })
+    )
 }
 
 
@@ -1409,6 +1833,7 @@ fn create_member_descriptions(&self, cx: &CrateContext)
 fn prepare_tuple_metadata(cx: &CrateContext,
                           tuple_type: ty::t,
                           component_types: &[ty::t],
+                          unique_type_id: UniqueTypeId,
                           span: Span)
                        -> RecursiveTypeDescription {
     let tuple_name = ppaux::ty_to_str(cx.tcx(), tuple_type);
@@ -1417,21 +1842,24 @@ fn prepare_tuple_metadata(cx: &CrateContext,
     let loc = span_start(cx, span);
     let file_metadata = file_metadata(cx, loc.file.name.as_slice());
 
-    UnfinishedMetadata {
-        cache_id: cache_id_for_type(tuple_type),
-        metadata_stub: create_struct_stub(cx,
-                                          tuple_llvm_type,
-                                          tuple_name.as_slice(),
-                                          file_metadata,
-                                          file_metadata,
-                                          span),
-        llvm_type: tuple_llvm_type,
-        file_metadata: file_metadata,
-        member_description_factory: TupleMDF(TupleMemberDescriptionFactory {
+    create_and_register_recursive_type_forward_declaration(
+        cx,
+        tuple_type,
+        unique_type_id,
+        create_struct_stub(cx,
+                           tuple_llvm_type,
+                           tuple_name.as_slice(),
+                           unique_type_id,
+                           file_metadata,
+                           file_metadata,
+                           span),
+        tuple_llvm_type,
+        file_metadata,
+        TupleMDF(TupleMemberDescriptionFactory {
             component_types: Vec::from_slice(component_types),
             span: span,
         })
-    }
+    )
 }
 
 
@@ -1444,6 +1872,7 @@ fn prepare_tuple_metadata(cx: &CrateContext,
 // variant of the given enum, this factory will produce one MemberDescription (all with no name and
 // a fixed offset of zero bytes).
 struct EnumMemberDescriptionFactory {
+    enum_type: ty::t,
     type_rep: Rc<adt::Repr>,
     variants: Rc<Vec<Rc<ty::VariantInfo>>>,
     discriminant_type_metadata: Option<DIType>,
@@ -1465,6 +1894,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                     .map(|(i, struct_def)| {
                         let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
                             describe_enum_variant(cx,
+                                                  self.enum_type,
                                                   struct_def,
                                                   &**self.variants.get(i),
                                                   discriminant_info,
@@ -1497,6 +1927,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                 } else {
                     let (variant_type_metadata, variant_llvm_type, member_description_factory) =
                         describe_enum_variant(cx,
+                                              self.enum_type,
                                               struct_def,
                                               &**self.variants.get(0),
                                               NoDiscriminant,
@@ -1551,11 +1982,19 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                     offset: FixedMemberOffset { bytes: 0 },
                 };
 
+                let unique_type_id = debug_context(cx).type_map
+                                                      .borrow_mut()
+                                                      .get_unique_type_id_of_enum_variant(
+                                                          cx,
+                                                          self.enum_type,
+                                                          non_null_variant_name.get());
+
                 // Now we can create the metadata of the artificial struct
                 let artificial_struct_metadata =
                     composite_type_metadata(cx,
                                             artificial_struct_llvm_type,
                                             non_null_variant_name.get(),
+                                            unique_type_id,
                                             &[sole_struct_member_description],
                                             self.containing_scope,
                                             self.file_metadata,
@@ -1581,6 +2020,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                 // Create a description of the non-null variant
                 let (variant_type_metadata, variant_llvm_type, member_description_factory) =
                     describe_enum_variant(cx,
+                                          self.enum_type,
                                           struct_def,
                                           &**self.variants.get(nndiscr as uint),
                                           OptimizedDiscriminant(ptrfield),
@@ -1654,6 +2094,7 @@ enum EnumDiscriminantInfo {
 // (3) a MemberDescriptionFactory for producing the descriptions of the fields of the variant. This
 // is a rudimentary version of a full RecursiveTypeDescription.
 fn describe_enum_variant(cx: &CrateContext,
+                         enum_type: ty::t,
                          struct_def: &adt::Struct,
                          variant_info: &ty::VariantInfo,
                          discriminant_info: EnumDiscriminantInfo,
@@ -1678,9 +2119,19 @@ fn describe_enum_variant(cx: &CrateContext,
         codemap::DUMMY_SP
     };
 
+    let variant_name = token::get_ident(variant_info.name);
+    let variant_name = variant_name.get();
+    let unique_type_id = debug_context(cx).type_map
+                                          .borrow_mut()
+                                          .get_unique_type_id_of_enum_variant(
+                                              cx,
+                                              enum_type,
+                                              variant_name);
+
     let metadata_stub = create_struct_stub(cx,
                                            variant_llvm_type,
-                                           token::get_ident(variant_info.name).get(),
+                                           variant_name,
+                                           unique_type_id,
                                            containing_scope,
                                            file_metadata,
                                            variant_definition_span);
@@ -1724,6 +2175,7 @@ fn describe_enum_variant(cx: &CrateContext,
 fn prepare_enum_metadata(cx: &CrateContext,
                          enum_type: ty::t,
                          enum_def_id: ast::DefId,
+                         unique_type_id: UniqueTypeId,
                          span: Span)
                       -> RecursiveTypeDescription {
     let enum_name = ppaux::ty_to_str(cx.tcx(), enum_type);
@@ -1804,10 +2256,14 @@ fn prepare_enum_metadata(cx: &CrateContext,
 
     let enum_llvm_type = type_of::type_of(cx, enum_type);
     let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
-    let unique_id = generate_unique_type_id("DI_ENUM_");
+
+    let unique_type_id_str = debug_context(cx)
+                             .type_map
+                             .borrow()
+                             .get_unique_type_id_as_string(unique_type_id);
 
     let enum_metadata = enum_name.as_slice().with_c_str(|enum_name| {
-        unique_id.as_slice().with_c_str(|unique_id| {
+        unique_type_id_str.as_slice().with_c_str(|unique_type_id_str| {
             unsafe {
                 llvm::LLVMDIBuilderCreateUnionType(
                 DIB(cx),
@@ -1820,17 +2276,20 @@ fn prepare_enum_metadata(cx: &CrateContext,
                 0, // Flags
                 ptr::null(),
                 0, // RuntimeLang
-                unique_id)
+                unique_type_id_str)
             }
         })
     });
 
-    return UnfinishedMetadata {
-        cache_id: cache_id_for_type(enum_type),
-        metadata_stub: enum_metadata,
-        llvm_type: enum_llvm_type,
-        file_metadata: file_metadata,
-        member_description_factory: EnumMDF(EnumMemberDescriptionFactory {
+    return create_and_register_recursive_type_forward_declaration(
+        cx,
+        enum_type,
+        unique_type_id,
+        enum_metadata,
+        enum_llvm_type,
+        file_metadata,
+        EnumMDF(EnumMemberDescriptionFactory {
+            enum_type: enum_type,
             type_rep: type_rep.clone(),
             variants: variants,
             discriminant_type_metadata: discriminant_type_metadata,
@@ -1838,7 +2297,7 @@ fn prepare_enum_metadata(cx: &CrateContext,
             file_metadata: file_metadata,
             span: span,
         }),
-    };
+    );
 
     fn get_enum_discriminant_name(cx: &CrateContext, def_id: ast::DefId) -> token::InternedString {
         let name = if def_id.krate == ast::LOCAL_CRATE {
@@ -1857,6 +2316,7 @@ fn get_enum_discriminant_name(cx: &CrateContext, def_id: ast::DefId) -> token::I
 fn composite_type_metadata(cx: &CrateContext,
                            composite_llvm_type: Type,
                            composite_type_name: &str,
+                           composite_type_unique_id: UniqueTypeId,
                            member_descriptions: &[MemberDescription],
                            containing_scope: DIScope,
                            file_metadata: DIFile,
@@ -1866,10 +2326,10 @@ fn composite_type_metadata(cx: &CrateContext,
     let composite_type_metadata = create_struct_stub(cx,
                                                      composite_llvm_type,
                                                      composite_type_name,
+                                                     composite_type_unique_id,
                                                      containing_scope,
                                                      file_metadata,
                                                      definition_span);
-
     // ... and immediately create and add the member descriptions.
     set_members_of_composite_type(cx,
                                   composite_type_metadata,
@@ -1895,9 +2355,22 @@ fn set_members_of_composite_type(cx: &CrateContext,
         let mut composite_types_completed =
             debug_context(cx).composite_types_completed.borrow_mut();
         if composite_types_completed.contains(&composite_type_metadata) {
-            cx.sess().span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
-                                                 Already completed forward declaration \
-                                                 re-encountered.");
+            let (llvm_version_major, llvm_version_minor) = unsafe {
+                (llvm::LLVMVersionMajor(), llvm::LLVMVersionMinor())
+            };
+
+            let actual_llvm_version = llvm_version_major * 1000000 + llvm_version_minor * 1000;
+            let min_supported_llvm_version = 3 * 1000000 + 4 * 1000;
+
+            if actual_llvm_version < min_supported_llvm_version {
+                cx.sess().warn(format!("This version of rustc was built with LLVM {}.{}. \
+                    Rustc just ran into a known debuginfo corruption problem that \
+                    often occurs with LLVM versions below 3.4. Please use a rustc built with a \
+                    newer version of LLVM.", llvm_version_major, llvm_version_minor).as_slice());
+            } else {
+                cx.sess().bug("debuginfo::set_members_of_composite_type() - \
+                               Already completed forward declaration re-encountered.");
+            }
         } else {
             composite_types_completed.insert(composite_type_metadata);
         }
@@ -1944,6 +2417,7 @@ fn set_members_of_composite_type(cx: &CrateContext,
 fn create_struct_stub(cx: &CrateContext,
                       struct_llvm_type: Type,
                       struct_type_name: &str,
+                      unique_type_id: UniqueTypeId,
                       containing_scope: DIScope,
                       file_metadata: DIFile,
                       definition_span: Span)
@@ -1951,13 +2425,12 @@ fn create_struct_stub(cx: &CrateContext,
     let loc = span_start(cx, definition_span);
     let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
 
-    // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
-    // where we don't want it.
-    let unique_id = generate_unique_type_id("DI_STRUCT_");
-
-    return unsafe {
+    let unique_type_id_str = debug_context(cx).type_map
+                                              .borrow()
+                                              .get_unique_type_id_as_string(unique_type_id);
+    let metadata_stub = unsafe {
         struct_type_name.with_c_str(|name| {
-            unique_id.as_slice().with_c_str(|unique_id| {
+            unique_type_id_str.as_slice().with_c_str(|unique_type_id| {
                 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
                 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
                 let empty_array = create_DIArray(DIB(cx), []);
@@ -1975,23 +2448,23 @@ fn create_struct_stub(cx: &CrateContext,
                     empty_array,
                     0,
                     ptr::null(),
-                    unique_id)
+                    unique_type_id)
             })
         })
     };
+
+    return metadata_stub;
 }
 
-fn boxed_type_metadata(cx: &CrateContext,
-                       content_type_name: Option<&str>,
-                       content_llvm_type: Type,
-                       content_type_metadata: DIType,
-                       span: Span)
-                    -> DICompositeType {
-    let box_type_name = match content_type_name {
-        Some(content_type_name) => format!("Boxed<{}>", content_type_name),
-        None                    => "BoxedType".to_string()
-    };
+fn at_box_metadata(cx: &CrateContext,
+                   content_type: ty::t,
+                   unique_type_id: UniqueTypeId) -> DIType {
+    let content_type_name = ppaux::ty_to_str(cx.tcx(), content_type);
+    let content_type_name = content_type_name.as_slice();
+    let content_llvm_type = type_of::type_of(cx, content_type);
+    let content_type_metadata = type_metadata(cx, content_type, codemap::DUMMY_SP);
 
+    let box_type_name = format!("Boxed<{}>", content_type_name);
     let box_llvm_type = Type::at_box(cx, content_llvm_type);
     let member_llvm_types = box_llvm_type.field_types();
     assert!(box_layout_is_correct(cx,
@@ -2035,17 +2508,18 @@ fn boxed_type_metadata(cx: &CrateContext,
         }
     ];
 
-    let loc = span_start(cx, span);
+    let loc = span_start(cx, codemap::DUMMY_SP);
     let file_metadata = file_metadata(cx, loc.file.name.as_slice());
 
     return composite_type_metadata(
         cx,
         box_llvm_type,
         box_type_name.as_slice(),
+        unique_type_id,
         member_descriptions,
         file_metadata,
         file_metadata,
-        span);
+        codemap::DUMMY_SP);
 
     // Unfortunately, we cannot assert anything but the correct types here---and not whether the
     // 'next' and 'prev' pointers are in the correct order.
@@ -2062,6 +2536,7 @@ fn box_layout_is_correct(cx: &CrateContext,
     }
 }
 
+
 fn fixed_vec_metadata(cx: &CrateContext,
                       element_type: ty::t,
                       len: uint,
@@ -2089,18 +2564,19 @@ fn fixed_vec_metadata(cx: &CrateContext,
     };
 }
 
-fn vec_metadata(cx: &CrateContext,
-                element_type: ty::t,
-                span: Span)
-             -> DICompositeType {
+fn heap_vec_metadata(cx: &CrateContext,
+                     vec_type: ty::t,
+                     element_type: ty::t,
+                     unique_type_id: UniqueTypeId,
+                     span: Span)
+                  -> DICompositeType {
 
     let element_type_metadata = type_metadata(cx, element_type, span);
     let element_llvm_type = type_of::type_of(cx, element_type);
     let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
 
     let vec_llvm_type = Type::vec(cx, &element_llvm_type);
-    let vec_type_name = format!("[{}]",
-                                ppaux::ty_to_str(cx.tcx(), element_type));
+    let vec_type_name = ppaux::ty_to_str(cx.tcx(), vec_type);
     let vec_type_name = vec_type_name.as_slice();
 
     let member_llvm_types = vec_llvm_type.field_types();
@@ -2145,6 +2621,7 @@ fn vec_metadata(cx: &CrateContext,
         cx,
         vec_llvm_type,
         vec_type_name,
+        unique_type_id,
         member_descriptions,
         file_metadata,
         file_metadata,
@@ -2154,6 +2631,7 @@ fn vec_metadata(cx: &CrateContext,
 fn vec_slice_metadata(cx: &CrateContext,
                       vec_type: ty::t,
                       element_type: ty::t,
+                      unique_type_id: UniqueTypeId,
                       span: Span)
                    -> DICompositeType {
 
@@ -2196,6 +2674,7 @@ fn vec_slice_metadata(cx: &CrateContext,
         cx,
         slice_llvm_type,
         slice_type_name.as_slice(),
+        unique_type_id,
         member_descriptions,
         file_metadata,
         file_metadata,
@@ -2218,8 +2697,7 @@ fn subroutine_type_metadata(cx: &CrateContext,
     let loc = span_start(cx, span);
     let file_metadata = file_metadata(cx, loc.file.name.as_slice());
 
-    let mut signature_metadata: Vec<DIType> =
-        Vec::with_capacity(signature.inputs.len() + 1);
+    let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs.len() + 1);
 
     // return type
     signature_metadata.push(match ty::get(signature.output).sty {
@@ -2245,7 +2723,8 @@ fn trait_metadata(cx: &CrateContext,
                   trait_type: ty::t,
                   substs: &subst::Substs,
                   trait_store: ty::TraitStore,
-                  _: &ty::BuiltinBounds)
+                  _: &ty::BuiltinBounds,
+                  unique_type_id: UniqueTypeId)
                -> DIType {
     // The implementation provided here is a stub. It makes sure that the trait type is
     // assigned the correct name, size, namespace, and source location. But it does not describe
@@ -2272,49 +2751,55 @@ fn trait_metadata(cx: &CrateContext,
     composite_type_metadata(cx,
                             trait_llvm_type,
                             name.as_slice(),
+                            unique_type_id,
                             [],
                             containing_scope,
                             file_metadata,
                             definition_span)
 }
 
+
 fn type_metadata(cx: &CrateContext,
                  t: ty::t,
                  usage_site_span: Span)
               -> DIType {
-    let cache_id = cache_id_for_type(t);
-
-    match debug_context(cx).created_types.borrow().find(&cache_id) {
-        Some(type_metadata) => return *type_metadata,
-        None => ()
-    }
-
-    fn create_pointer_to_box_metadata(cx: &CrateContext,
-                                      pointer_type: ty::t,
-                                      type_in_box: ty::t)
-                                   -> DIType {
-        let content_type_name = ppaux::ty_to_str(cx.tcx(), type_in_box);
-        let content_type_name = content_type_name.as_slice();
-        let content_llvm_type = type_of::type_of(cx, type_in_box);
-        let content_type_metadata = type_metadata(
-            cx,
-            type_in_box,
-            codemap::DUMMY_SP);
-
-        let box_metadata = boxed_type_metadata(
-            cx,
-            Some(content_type_name),
-            content_llvm_type,
-            content_type_metadata,
-            codemap::DUMMY_SP);
-
-        pointer_type_metadata(cx, pointer_type, box_metadata)
-    }
+    // Get the unique type id of this type.
+    let unique_type_id = {
+        let mut type_map = debug_context(cx).type_map.borrow_mut();
+        match type_map.find_metadata_for_type(t) {
+            Some(metadata) => {
+                return metadata;
+            },
+            None => {
+                let unique_type_id = type_map.get_unique_type_id_of_type(cx, t);
+                match type_map.find_metadata_for_unique_id(unique_type_id) {
+                    Some(metadata) => {
+                        type_map.register_type_with_metadata(cx, t, metadata);
+                        return metadata;
+                    },
+                    None => {
+                        // There really is no type metadata for this type, so proceed by creating
+                        // it
+                        unique_type_id
+                    }
+                }
+            }
+        }
+    };
 
     debug!("type_metadata: {:?}", ty::get(t));
 
+    macro_rules! return_if_created_in_meantime(
+        () => (
+            match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) {
+                Some(metadata) => return metadata,
+                None => { /* proceed normally */ }
+            };
+        )
+    )
+
     let sty = &ty::get(t).sty;
-    let type_metadata = match *sty {
+    let (type_metadata, should_already_be_stored_in_typemap) = match *sty {
         ty::ty_nil      |
         ty::ty_bot      |
         ty::ty_bool     |
@@ -2322,50 +2807,73 @@ fn create_pointer_to_box_metadata(cx: &CrateContext,
         ty::ty_int(_)   |
         ty::ty_uint(_)  |
         ty::ty_float(_) => {
-            basic_type_metadata(cx, t)
+            (basic_type_metadata(cx, t), false)
         }
         ty::ty_enum(def_id, _) => {
-            prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
+            let is_c_style_enum = match *adt::represent_type(cx, t) {
+                adt::CEnum(..) => true,
+                _ => false
+            };
+
+            (prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx),
+             !is_c_style_enum)
+        }
+        ty::ty_box(pointee_type) => {
+            let box_content_metadata = at_box_metadata(cx, pointee_type, unique_type_id);
+            return_if_created_in_meantime!();
+            (pointer_type_metadata(cx, t, box_content_metadata), false)
         }
-        ty::ty_box(typ) => {
-            create_pointer_to_box_metadata(cx, t, typ)
+        ty::ty_vec(ref mt, Some(len)) => {
+            (fixed_vec_metadata(cx, mt.ty, len, usage_site_span), false)
         }
-        ty::ty_vec(ref mt, Some(len)) => fixed_vec_metadata(cx, mt.ty, len, usage_site_span),
-        ty::ty_uniq(typ) => {
-            match ty::get(typ).sty {
+        ty::ty_uniq(pointee_type) => {
+            (match ty::get(pointee_type).sty {
                 ty::ty_vec(ref mt, None) => {
-                    let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
+                    let vec_metadata = heap_vec_metadata(cx,
+                                                         pointee_type,
+                                                         mt.ty,
+                                                         unique_type_id,
+                                                         usage_site_span);
+                    return_if_created_in_meantime!();
                     pointer_type_metadata(cx, t, vec_metadata)
                 }
                 ty::ty_str => {
                     let i8_t = ty::mk_i8();
-                    let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
+                    let vec_metadata = heap_vec_metadata(cx,
+                                                         pointee_type,
+                                                         i8_t,
+                                                         unique_type_id,
+                                                         usage_site_span);
                     pointer_type_metadata(cx, t, vec_metadata)
                 }
                 _ => {
-                    let pointee = type_metadata(cx, typ, usage_site_span);
-                    pointer_type_metadata(cx, t, pointee)
+                    let pointee_metadata = type_metadata(cx, pointee_type, usage_site_span);
+                    return_if_created_in_meantime!();
+                    pointer_type_metadata(cx, t, pointee_metadata)
                 }
-            }
+            }, false)
         }
         ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
-            match ty::get(mt.ty).sty {
-                ty::ty_vec(ref mt, None) => vec_slice_metadata(cx, t, mt.ty, usage_site_span),
+            (match ty::get(mt.ty).sty {
+                ty::ty_vec(ref mt, None) => {
+                    vec_slice_metadata(cx, t, mt.ty, unique_type_id, usage_site_span)
+                }
                 ty::ty_str => {
                     let i8_t = ty::mk_i8();
-                    vec_slice_metadata(cx, t, i8_t, usage_site_span)
+                    vec_slice_metadata(cx, t, i8_t, unique_type_id, usage_site_span)
                 }
                 _ => {
                     let pointee = type_metadata(cx, mt.ty, usage_site_span);
+                    return_if_created_in_meantime!();
                     pointer_type_metadata(cx, t, pointee)
                 }
-            }
+            }, false)
         }
         ty::ty_bare_fn(ref barefnty) => {
-            subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
+            (subroutine_type_metadata(cx, &barefnty.sig, usage_site_span), false)
         }
         ty::ty_closure(ref closurety) => {
-            subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
+            (subroutine_type_metadata(cx, &closurety.sig, usage_site_span), false)
         }
         ty::ty_trait(box ty::TyTrait {
                 def_id,
@@ -2373,25 +2881,60 @@ fn create_pointer_to_box_metadata(cx: &CrateContext,
                 store,
                 ref bounds
             }) => {
-            trait_metadata(cx, def_id, t, substs, store, bounds)
+            (trait_metadata(cx, def_id, t, substs, store, bounds, unique_type_id), false)
         }
         ty::ty_struct(def_id, ref substs) => {
-            prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
+            let struct_metadata = prepare_struct_metadata(cx,
+                                                          t,
+                                                          def_id,
+                                                          substs,
+                                                          unique_type_id,
+                                                          usage_site_span).finalize(cx);
+            (struct_metadata, true)
         }
         ty::ty_tup(ref elements) => {
-            prepare_tuple_metadata(cx,
-                                   t,
-                                   elements.as_slice(),
-                                   usage_site_span).finalize(cx)
+            let tuple_metadata = prepare_tuple_metadata(cx,
+                                                        t,
+                                                        elements.as_slice(),
+                                                        unique_type_id,
+                                                        usage_site_span).finalize(cx);
+            (tuple_metadata, true)
         }
         _ => {
-            cx.sess().bug(format!("debuginfo: unexpected type in \
-                                   type_metadata: {:?}",
+            cx.sess().bug(format!("debuginfo: unexpected type in type_metadata: {:?}",
                                   sty).as_slice())
         }
     };
 
-    debug_context(cx).created_types.borrow_mut().insert(cache_id, type_metadata);
+    {
+        let mut type_map = debug_context(cx).type_map.borrow_mut();
+
+        if should_already_be_stored_in_typemap {
+            // Make sure that we already have a TypeMap entry entry for the ty::t.
+            if type_map.find_metadata_for_type(t).is_none() {
+                let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
+                let error_message = format!("Expected type metadata for ty::t '{}' to already be in
+                                            the TypeMap but it was not (unique type id = {})",
+                                            ppaux::ty_to_str(cx.tcx(), t),
+                                            unique_type_id_str.as_slice());
+                cx.sess().span_bug(usage_site_span, error_message.as_slice());
+            }
+
+            // Also make sure that we already have a TypeMap entry entry for the unique type id.
+            if type_map.find_metadata_for_unique_id(unique_type_id).is_none() {
+                let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
+                let error_message = format!("Expected type metadata for unique type id '{}' to
+                                            already be in the TypeMap but it was not. (ty::t = {})",
+                                            unique_type_id_str.as_slice(),
+                                            ppaux::ty_to_str(cx.tcx(), t));
+                cx.sess().span_bug(usage_site_span, error_message.as_slice());
+            }
+        } else {
+            type_map.register_type_with_metadata(cx, t, type_metadata);
+            type_map.register_unique_id_with_metadata(cx, unique_type_id, type_metadata);
+        }
+    }
+
     type_metadata
 }
 
@@ -2446,20 +2989,6 @@ fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
 //  Utility Functions
 //=-------------------------------------------------------------------------------------------------
 
-fn cache_id_for_type(t: ty::t) -> uint {
-    ty::type_id(t)
-}
-
-// Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
-// `prepare_enum_metadata()`.
-fn generate_unique_type_id(prefix: &'static str) -> String {
-    unsafe {
-        static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
-        format!("{}{}", prefix,
-                unique_id_counter.fetch_add(1, atomics::SeqCst))
-    }
-}
-
 /// Return codemap::Loc corresponding to the beginning of the span
 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
     cx.sess().codemap().lookup_char_pos(span.lo)
index c2c71ba32f312acda994b18ec029534f64b77616..2a0873e327bc258125f8ab6f981e6c99fd22e2b6 100644 (file)
@@ -4390,6 +4390,27 @@ pub fn trait_id_of_impl(tcx: &ctxt,
     }
 }
 
+/// If the given def ID describes a method belonging to an impl, return the
+/// ID of the impl that the method belongs to. Otherwise, return `None`.
+pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId)
+                       -> Option<ast::DefId> {
+    if def_id.krate != LOCAL_CRATE {
+        return match csearch::get_method(tcx, def_id).container {
+            TraitContainer(_) => None,
+            ImplContainer(def_id) => Some(def_id),
+        };
+    }
+    match tcx.methods.borrow().find_copy(&def_id) {
+        Some(method) => {
+            match method.container {
+                TraitContainer(_) => None,
+                ImplContainer(def_id) => Some(def_id),
+            }
+        }
+        None => None
+    }
+}
+
 /// If the given def ID describes a method belonging to a trait (either a
 /// default method or an implementation of a trait method), return the ID of
 /// the trait that the method belongs to. Otherwise, return `None`.
index 6b468bd0827c6144ba0c63eec06c10a922f7bf67..1a7f0cdfc507ef7db918eab273073ec346a81776 100644 (file)
 
 ```rust
 local_data_key!(key_int: int)
-local_data_key!(key_vector: ~[int])
+local_data_key!(key_vector: Vec<int>)
 
 key_int.replace(Some(3));
 assert_eq!(*key_int.get().unwrap(), 3);
 
-key_vector.replace(Some(~[4]));
-assert_eq!(*key_vector.get().unwrap(), ~[4]);
+key_vector.replace(Some(vec![4]));
+assert_eq!(*key_vector.get().unwrap(), vec![4]);
 ```
 
 */
index dbde1a7486d09c9fef49838e71ddabc05f61da07..2ad69dad8d2c9c75d44526ae227a2655d71226e7 100644 (file)
@@ -35,7 +35,6 @@
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/")]
-#![deny(deprecated_owned_vector)]
 
 use std::char;
 use std::cmp;
index f8b2bd3ff9ff4cbacb9fa36c9f3027cc505b67bb..8dfd4e778c2a8f8ac9f9c25db06257af55823dc1 100644 (file)
@@ -81,7 +81,7 @@ fn main() {
 ```
 
 Two wrapper functions are provided to encode a Encodable object
-into a string (String) or buffer (~[u8]): `str_encode(&m)` and `buffer_encode(&m)`.
+into a string (String) or buffer (vec![u8]): `str_encode(&m)` and `buffer_encode(&m)`.
 
 ```rust
 use serialize::json;
@@ -2293,10 +2293,6 @@ impl<'a, A:ToJson> ToJson for &'a [A] {
     fn to_json(&self) -> Json { List(self.iter().map(|elt| elt.to_json()).collect()) }
 }
 
-impl<A:ToJson> ToJson for ~[A] {
-    fn to_json(&self) -> Json { List(self.iter().map(|elt| elt.to_json()).collect()) }
-}
-
 impl<A:ToJson> ToJson for Vec<A> {
     fn to_json(&self) -> Json { List(self.iter().map(|elt| elt.to_json()).collect()) }
 }
@@ -3116,7 +3112,8 @@ fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() {
         let _hm: HashMap<uint, bool> = Decodable::decode(&mut decoder).unwrap();
     }
 
-    fn assert_stream_equal(src: &str, expected: ~[(JsonEvent, ~[StackElement])]) {
+    fn assert_stream_equal(src: &str,
+                           expected: Vec<(JsonEvent, Vec<StackElement>)>) {
         let mut parser = Parser::new(src.chars());
         let mut i = 0;
         loop {
@@ -3124,7 +3121,7 @@ fn assert_stream_equal(src: &str, expected: ~[(JsonEvent, ~[StackElement])]) {
                 Some(e) => e,
                 None => { break; }
             };
-            let (ref expected_evt, ref expected_stack) = expected[i];
+            let (ref expected_evt, ref expected_stack) = *expected.get(i);
             if !parser.stack().is_equal_to(expected_stack.as_slice()) {
                 fail!("Parser stack is not equal to {}", expected_stack);
             }
@@ -3133,26 +3130,27 @@ fn assert_stream_equal(src: &str, expected: ~[(JsonEvent, ~[StackElement])]) {
         }
     }
     #[test]
+    #[ignore(cfg(target_word_size = "32"))] // FIXME(#14064)
     fn test_streaming_parser() {
         assert_stream_equal(
             r#"{ "foo":"bar", "array" : [0, 1, 2,3 ,4,5], "idents":[null,true,false]}"#,
-            ~[
-                (ObjectStart,             ~[]),
-                  (StringValue("bar".to_string()),   ~[Key("foo")]),
-                  (ListStart,             ~[Key("array")]),
-                    (NumberValue(0.0),    ~[Key("array"), Index(0)]),
-                    (NumberValue(1.0),    ~[Key("array"), Index(1)]),
-                    (NumberValue(2.0),    ~[Key("array"), Index(2)]),
-                    (NumberValue(3.0),    ~[Key("array"), Index(3)]),
-                    (NumberValue(4.0),    ~[Key("array"), Index(4)]),
-                    (NumberValue(5.0),    ~[Key("array"), Index(5)]),
-                  (ListEnd,               ~[Key("array")]),
-                  (ListStart,             ~[Key("idents")]),
-                    (NullValue,           ~[Key("idents"), Index(0)]),
-                    (BooleanValue(true),  ~[Key("idents"), Index(1)]),
-                    (BooleanValue(false), ~[Key("idents"), Index(2)]),
-                  (ListEnd,               ~[Key("idents")]),
-                (ObjectEnd,               ~[]),
+            vec![
+                (ObjectStart,             vec![]),
+                  (StringValue("bar".to_string()),   vec![Key("foo")]),
+                  (ListStart,             vec![Key("array")]),
+                    (NumberValue(0.0),    vec![Key("array"), Index(0)]),
+                    (NumberValue(1.0),    vec![Key("array"), Index(1)]),
+                    (NumberValue(2.0),    vec![Key("array"), Index(2)]),
+                    (NumberValue(3.0),    vec![Key("array"), Index(3)]),
+                    (NumberValue(4.0),    vec![Key("array"), Index(4)]),
+                    (NumberValue(5.0),    vec![Key("array"), Index(5)]),
+                  (ListEnd,               vec![Key("array")]),
+                  (ListStart,             vec![Key("idents")]),
+                    (NullValue,           vec![Key("idents"), Index(0)]),
+                    (BooleanValue(true),  vec![Key("idents"), Index(1)]),
+                    (BooleanValue(false), vec![Key("idents"), Index(2)]),
+                  (ListEnd,               vec![Key("idents")]),
+                (ObjectEnd,               vec![]),
             ]
         );
     }
@@ -3183,34 +3181,34 @@ fn test_read_object_streaming() {
 
         assert_stream_equal(
             "{}",
-            box [(ObjectStart, box []), (ObjectEnd, box [])]
+            vec![(ObjectStart, vec![]), (ObjectEnd, vec![])]
         );
         assert_stream_equal(
             "{\"a\": 3}",
-            box [
-                (ObjectStart,        box []),
-                  (NumberValue(3.0), box [Key("a")]),
-                (ObjectEnd,          box []),
+            vec![
+                (ObjectStart,        vec![]),
+                  (NumberValue(3.0), vec![Key("a")]),
+                (ObjectEnd,          vec![]),
             ]
         );
         assert_stream_equal(
             "{ \"a\": null, \"b\" : true }",
-            box [
-                (ObjectStart,           box []),
-                  (NullValue,           box [Key("a")]),
-                  (BooleanValue(true),  box [Key("b")]),
-                (ObjectEnd,             box []),
+            vec![
+                (ObjectStart,           vec![]),
+                  (NullValue,           vec![Key("a")]),
+                  (BooleanValue(true),  vec![Key("b")]),
+                (ObjectEnd,             vec![]),
             ]
         );
         assert_stream_equal(
             "{\"a\" : 1.0 ,\"b\": [ true ]}",
-            box [
-                (ObjectStart,           box []),
-                  (NumberValue(1.0),    box [Key("a")]),
-                  (ListStart,           box [Key("b")]),
-                    (BooleanValue(true),box [Key("b"), Index(0)]),
-                  (ListEnd,             box [Key("b")]),
-                (ObjectEnd,             box []),
+            vec![
+                (ObjectStart,           vec![]),
+                  (NumberValue(1.0),    vec![Key("a")]),
+                  (ListStart,           vec![Key("b")]),
+                    (BooleanValue(true),vec![Key("b"), Index(0)]),
+                  (ListEnd,             vec![Key("b")]),
+                (ObjectEnd,             vec![]),
             ]
         );
         assert_stream_equal(
@@ -3222,19 +3220,19 @@ fn test_read_object_streaming() {
                     { "c": {"d": null} }
                 ]
             }"#,
-            ~[
-                (ObjectStart,                   ~[]),
-                  (NumberValue(1.0),            ~[Key("a")]),
-                  (ListStart,                   ~[Key("b")]),
-                    (BooleanValue(true),        ~[Key("b"), Index(0)]),
-                    (StringValue("foo\nbar".to_string()),  ~[Key("b"), Index(1)]),
-                    (ObjectStart,               ~[Key("b"), Index(2)]),
-                      (ObjectStart,             ~[Key("b"), Index(2), Key("c")]),
-                        (NullValue,             ~[Key("b"), Index(2), Key("c"), Key("d")]),
-                      (ObjectEnd,               ~[Key("b"), Index(2), Key("c")]),
-                    (ObjectEnd,                 ~[Key("b"), Index(2)]),
-                  (ListEnd,                     ~[Key("b")]),
-                (ObjectEnd,                     ~[]),
+            vec![
+                (ObjectStart,                   vec![]),
+                  (NumberValue(1.0),            vec![Key("a")]),
+                  (ListStart,                   vec![Key("b")]),
+                    (BooleanValue(true),        vec![Key("b"), Index(0)]),
+                    (StringValue("foo\nbar".to_string()),  vec![Key("b"), Index(1)]),
+                    (ObjectStart,               vec![Key("b"), Index(2)]),
+                      (ObjectStart,             vec![Key("b"), Index(2), Key("c")]),
+                        (NullValue,             vec![Key("b"), Index(2), Key("c"), Key("d")]),
+                      (ObjectEnd,               vec![Key("b"), Index(2), Key("c")]),
+                    (ObjectEnd,                 vec![Key("b"), Index(2)]),
+                  (ListEnd,                     vec![Key("b")]),
+                (ObjectEnd,                     vec![]),
             ]
         );
     }
@@ -3243,70 +3241,70 @@ fn test_read_object_streaming() {
     fn test_read_list_streaming() {
         assert_stream_equal(
             "[]",
-            box [
-                (ListStart, box []),
-                (ListEnd,   box []),
+            vec![
+                (ListStart, vec![]),
+                (ListEnd,   vec![]),
             ]
         );
         assert_stream_equal(
             "[ ]",
-            box [
-                (ListStart, box []),
-                (ListEnd,   box []),
+            vec![
+                (ListStart, vec![]),
+                (ListEnd,   vec![]),
             ]
         );
         assert_stream_equal(
             "[true]",
-            box [
-                (ListStart,              box []),
-                    (BooleanValue(true), box [Index(0)]),
-                (ListEnd,                box []),
+            vec![
+                (ListStart,              vec![]),
+                    (BooleanValue(true), vec![Index(0)]),
+                (ListEnd,                vec![]),
             ]
         );
         assert_stream_equal(
             "[ false ]",
-            box [
-                (ListStart,               box []),
-                    (BooleanValue(false), box [Index(0)]),
-                (ListEnd,                 box []),
+            vec![
+                (ListStart,               vec![]),
+                    (BooleanValue(false), vec![Index(0)]),
+                (ListEnd,                 vec![]),
             ]
         );
         assert_stream_equal(
             "[null]",
-            box [
-                (ListStart,     box []),
-                    (NullValue, box [Index(0)]),
-                (ListEnd,       box []),
+            vec![
+                (ListStart,     vec![]),
+                    (NullValue, vec![Index(0)]),
+                (ListEnd,       vec![]),
             ]
         );
         assert_stream_equal(
             "[3, 1]",
-            box [
-                (ListStart,     box []),
-                    (NumberValue(3.0), box [Index(0)]),
-                    (NumberValue(1.0), box [Index(1)]),
-                (ListEnd,       box []),
+            vec![
+                (ListStart,     vec![]),
+                    (NumberValue(3.0), vec![Index(0)]),
+                    (NumberValue(1.0), vec![Index(1)]),
+                (ListEnd,       vec![]),
             ]
         );
         assert_stream_equal(
             "\n[3, 2]\n",
-            box [
-                (ListStart,     box []),
-                    (NumberValue(3.0), box [Index(0)]),
-                    (NumberValue(2.0), box [Index(1)]),
-                (ListEnd,       box []),
+            vec![
+                (ListStart,     vec![]),
+                    (NumberValue(3.0), vec![Index(0)]),
+                    (NumberValue(2.0), vec![Index(1)]),
+                (ListEnd,       vec![]),
             ]
         );
         assert_stream_equal(
             "[2, [4, 1]]",
-            box [
-                (ListStart,                 box []),
-                    (NumberValue(2.0),      box [Index(0)]),
-                    (ListStart,             box [Index(1)]),
-                        (NumberValue(4.0),  box [Index(1), Index(0)]),
-                        (NumberValue(1.0),  box [Index(1), Index(1)]),
-                    (ListEnd,               box [Index(1)]),
-                (ListEnd,                   box []),
+            vec![
+                (ListStart,                 vec![]),
+                    (NumberValue(2.0),      vec![Index(0)]),
+                    (ListStart,             vec![Index(1)]),
+                        (NumberValue(4.0),  vec![Index(1), Index(0)]),
+                        (NumberValue(1.0),  vec![Index(1), Index(1)]),
+                    (ListEnd,               vec![Index(1)]),
+                (ListEnd,                   vec![]),
             ]
         );
 
@@ -3436,7 +3434,7 @@ fn test_to_json() {
         assert_eq!((1, 2, 3).to_json(), list3);
         assert_eq!([1, 2].to_json(), list2);
         assert_eq!((&[1, 2, 3]).to_json(), list3);
-        assert_eq!((~[1, 2]).to_json(), list2);
+        assert_eq!((vec![1, 2]).to_json(), list2);
         assert_eq!(vec!(1, 2, 3).to_json(), list3);
         let mut tree_map = TreeMap::new();
         tree_map.insert("a".to_string(), 1);
index d4987bd0afe0bb362911c9b31ee8c6efe8a8fb8c..40092a477b3967257b645a986e25d7246da0d1cf 100644 (file)
@@ -425,32 +425,6 @@ fn encode(&self, s: &mut S) -> Result<(), E> {
     }
 }
 
-impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for ~[T] {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
-        s.emit_seq(self.len(), |s| {
-            for (i, e) in self.iter().enumerate() {
-                try!(s.emit_seq_elt(i, |s| e.encode(s)))
-            }
-            Ok(())
-        })
-    }
-}
-
-impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for ~[T] {
-    fn decode(d: &mut D) -> Result<~[T], E> {
-        use std::vec::FromVec;
-
-        d.read_seq(|d, len| {
-            let mut v: Vec<T> = Vec::with_capacity(len);
-            for i in range(0, len) {
-                v.push(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
-            }
-            let k: ~[T] = FromVec::from_vec(v);
-            Ok(k)
-        })
-    }
-}
-
 impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Vec<T> {
     fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_seq(self.len(), |s| {
index b9edc9a811e43486af96ba81ebc99df56c73a4de..2730d90f05fc121b6acccad4eb3bd89d466bf468 100644 (file)
@@ -278,18 +278,6 @@ fn into_ascii_opt(self) -> Option<Vec<Ascii>> {
     unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
 }
 
-impl OwnedAsciiCast for ~[u8] {
-    #[inline]
-    fn is_ascii(&self) -> bool {
-        self.as_slice().is_ascii()
-    }
-
-    #[inline]
-    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
-        mem::transmute(Vec::from_slice(self.as_slice()))
-    }
-}
-
 impl OwnedAsciiCast for String {
     #[inline]
     fn is_ascii(&self) -> bool {
@@ -353,14 +341,6 @@ fn eq_ignore_case(self, other: &[Ascii]) -> bool {
     }
 }
 
-impl IntoStr for ~[Ascii] {
-    #[inline]
-    fn into_str(self) -> String {
-        let vector: Vec<Ascii> = self.as_slice().iter().map(|x| *x).collect();
-        vector.into_str()
-    }
-}
-
 impl IntoStr for Vec<Ascii> {
     #[inline]
     fn into_str(self) -> String {
@@ -592,8 +572,8 @@ fn test_ascii_vec() {
         let test = &[40u8, 32u8, 59u8];
         assert_eq!(test.to_ascii(), v2ascii!([40, 32, 59]));
         assert_eq!("( ;".to_ascii(), v2ascii!([40, 32, 59]));
-        let v = box [40u8, 32u8, 59u8];
-        assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
+        let v = vec![40u8, 32u8, 59u8];
+        assert_eq!(v.as_slice().to_ascii(), v2ascii!([40, 32, 59]));
         assert_eq!("( ;".to_string().as_slice().to_ascii(), v2ascii!([40, 32, 59]));
 
         assert_eq!("abCDef&?#".to_ascii().to_lower().into_str(), "abcdef&?#".to_string());
@@ -623,7 +603,7 @@ fn test_ascii_vec_ng() {
     #[test]
     fn test_owned_ascii_vec() {
         assert_eq!(("( ;".to_string()).into_ascii(), vec2ascii![40, 32, 59]);
-        assert_eq!((box [40u8, 32u8, 59u8]).into_ascii(), vec2ascii![40, 32, 59]);
+        assert_eq!((vec![40u8, 32u8, 59u8]).into_ascii(), vec2ascii![40, 32, 59]);
     }
 
     #[test]
index 529536b0a0da78317bae8db7fedef77408c70f4f..c03fbf302d75419a4ab2f5676d8904640c7817f7 100644 (file)
@@ -15,9 +15,9 @@
 use io;
 use option::{None, Option, Some};
 use result::{Ok, Err};
-use super::{Reader, Writer, IoResult};
-use str::StrSlice;
 use slice::{bytes, MutableVector, ImmutableVector};
+use str::StrSlice;
+use super::{Reader, Writer, IoResult};
 use vec::Vec;
 
 /// Allows reading from a rx.
@@ -162,14 +162,14 @@ fn test_rx_reader() {
         assert_eq!(Ok(2), reader.read(buf));
         assert_eq!(&[7,8,6], buf.as_slice());
 
-        match reader.read(buf) {
+        match reader.read(buf.as_mut_slice()) {
             Ok(..) => fail!(),
             Err(e) => assert_eq!(e.kind, io::EndOfFile),
         }
         assert_eq!(&[7,8,6], buf.as_slice());
 
         // Ensure it continues to fail in the same way.
-        match reader.read(buf) {
+        match reader.read(buf.as_mut_slice()) {
             Ok(..) => fail!(),
             Err(e) => assert_eq!(e.kind, io::EndOfFile),
         }
index d61518d4ee76f9aa36db766b634eebdf4c3a8402..84a1253e5b4ae50a60fa1de3a4a17be09991f465 100644 (file)
@@ -447,10 +447,10 @@ fn test_read_be_int_n() {
     #[test]
     fn test_read_f32() {
         //big-endian floating-point 8.1250
-        let buf = box [0x41, 0x02, 0x00, 0x00];
+        let buf = vec![0x41, 0x02, 0x00, 0x00];
 
         let mut writer = MemWriter::new();
-        writer.write(buf).unwrap();
+        writer.write(buf.as_slice()).unwrap();
 
         let mut reader = MemReader::new(writer.unwrap());
         let f = reader.read_be_f32().unwrap();
index 5259200133ae1974e1af84e02146849f8a2110ed..c29c82ab2e9b443085be829f7fa7e378d081db9f 100644 (file)
@@ -52,6 +52,9 @@
 use c_str::ToCStr;
 use clone::Clone;
 use collections::Collection;
+use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
+use io::{IoResult, IoError, FileStat, SeekStyle, Seek, Writer, Reader};
+use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
 use io;
 use iter::Iterator;
 use kinds::Send;
 use owned::Box;
 use path::{Path, GenericPath};
 use path;
-use result::{Ok, Err};
-use rt::rtio::{RtioFileStream, IoFactory, LocalIo};
+use result::{Err, Ok};
+use rt::rtio::LocalIo;
 use rt::rtio;
-use slice::{OwnedVector, ImmutableVector};
-use super::UnstableFileStat;
-use super::{FileMode, FileAccess, FileStat, IoResult, FilePermission};
-use super::{Reader, Writer, Seek, Append, SeekCur, SeekEnd, SeekSet};
-use super::{SeekStyle, Read, Write, ReadWrite, Open, IoError, Truncate};
+use slice::ImmutableVector;
 use vec::Vec;
 
 /// Unconstrained file access type that exposes read and write operations
@@ -82,7 +81,7 @@
 /// configured at creation time, via the `FileAccess` parameter to
 /// `File::open_mode()`.
 pub struct File {
-    fd: Box<RtioFileStream:Send>,
+    fd: Box<rtio::RtioFileStream:Send>,
     path: Path,
     last_nread: int,
 }
@@ -846,7 +845,7 @@ pub fn tmpdir() -> TempDir {
             let mut read_buf = [0, .. 1028];
             let read_str = match check!(read_stream.read(read_buf)) {
                 -1|0 => fail!("shouldn't happen"),
-                n => str::from_utf8(read_buf.slice_to(n).to_owned()).unwrap().to_owned()
+                n => str::from_utf8(read_buf.slice_to(n)).unwrap().to_owned()
             };
             assert_eq!(read_str, message.to_owned());
         }
index f0fbe4529b0e959c3b6aeb88155400332cf2fdd8..71a967bb8dc5f41037fc64910f756fa1bb274e70 100644 (file)
@@ -450,8 +450,8 @@ fn test_mem_reader() {
 
     #[test]
     fn test_buf_reader() {
-        let in_buf = box [0, 1, 2, 3, 4, 5, 6, 7];
-        let mut reader = BufReader::new(in_buf);
+        let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
+        let mut reader = BufReader::new(in_buf.as_slice());
         let mut buf = [];
         assert_eq!(reader.read(buf), Ok(0));
         assert_eq!(reader.tell(), Ok(0));
@@ -466,7 +466,7 @@ fn test_buf_reader() {
         assert_eq!(reader.read(buf), Ok(3));
         assert_eq!(buf.slice(0, 3), &[5, 6, 7]);
         assert!(reader.read(buf).is_err());
-        let mut reader = BufReader::new(in_buf);
+        let mut reader = BufReader::new(in_buf.as_slice());
         assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
         assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
         assert!(reader.read(buf).is_err());
index 3cb2fe1c8f1b3bc35a446b05ceafe465f628a2ef..a626d1f3a6c08660b413f289e1d662d32a6350f7 100644 (file)
@@ -856,8 +856,8 @@ pub fn env_cmd() -> Command {
     })
 
     iotest!(fn test_add_to_env() {
-        let new_env = box [("RUN_TEST_NEW_ENV", "123")];
-        let prog = env_cmd().env(new_env).spawn().unwrap();
+        let new_env = vec![("RUN_TEST_NEW_ENV", "123")];
+        let prog = env_cmd().env(new_env.as_slice()).spawn().unwrap();
         let result = prog.wait_with_output().unwrap();
         let output = str::from_utf8_lossy(result.output.as_slice()).into_string();
 
index 59c42f111d0faed566ec0bb5b9c85b0f9a423565..83a01feee9017865f0c13878ca2282b28f805be2 100644 (file)
@@ -300,24 +300,24 @@ fn test_limit_reader_limit() {
     #[test]
     fn test_null_writer() {
         let mut s = NullWriter;
-        let buf = box [0, 0, 0];
-        s.write(buf).unwrap();
+        let buf = vec![0, 0, 0];
+        s.write(buf.as_slice()).unwrap();
         s.flush().unwrap();
     }
 
     #[test]
     fn test_zero_reader() {
         let mut s = ZeroReader;
-        let mut buf = box [1, 2, 3];
-        assert_eq!(s.read(buf), Ok(3));
-        assert_eq!(box [0, 0, 0], buf);
+        let mut buf = vec![1, 2, 3];
+        assert_eq!(s.read(buf.as_mut_slice()), Ok(3));
+        assert_eq!(vec![0, 0, 0], buf);
     }
 
     #[test]
     fn test_null_reader() {
         let mut r = NullReader;
-        let mut buf = box [0];
-        assert!(r.read(buf).is_err());
+        let mut buf = vec![0];
+        assert!(r.read(buf.as_mut_slice()).is_err());
     }
 
     #[test]
index fa882e7d016fe21783efe91b2ed1cebd09c62af4..cc76cde7baffc6ec1007d102e6c8756ac2ff0e12 100644 (file)
@@ -42,7 +42,7 @@
 use ptr::RawPtr;
 use ptr;
 use result::{Err, Ok, Result};
-use slice::{Vector, ImmutableVector, MutableVector, OwnedVector};
+use slice::{Vector, ImmutableVector, MutableVector};
 use str::{Str, StrSlice, StrAllocating};
 use str;
 use string::String;
 /// # Example
 ///
 /// ```rust
+/// use std::os;
+///
 /// // We assume that we are in a valid directory like "/home".
-/// let current_working_directory = std::os::getcwd();
+/// let current_working_directory = os::getcwd();
 /// println!("The current directory is {}", current_working_directory.display());
 /// // /home
 /// ```
@@ -104,8 +106,10 @@ pub fn getcwd() -> Path {
 /// # Example
 ///
 /// ```rust
+/// use std::os;
+///
 /// // We assume that we are in a valid directory like "C:\\Windows".
-/// let current_working_directory = std::os::getcwd();
+/// let current_working_directory = os::getcwd();
 /// println!("The current directory is {}", current_working_directory.display());
 /// // C:\\Windows
 /// ```
@@ -188,8 +192,8 @@ fn with_env_lock<T>(f: || -> T) -> T {
     }
 }
 
-/// Returns a vector of (variable, value) pairs as a Vec<(String, String)>,
-/// for all the environment variables of the current process.
+/// Returns a vector of (variable, value) pairs, for all the environment
+/// variables of the current process.
 ///
 /// Invalid UTF-8 bytes are replaced with \uFFFD. See `str::from_utf8_lossy()`
 /// for details.
@@ -197,8 +201,10 @@ fn with_env_lock<T>(f: || -> T) -> T {
 /// # Example
 ///
 /// ```rust
-/// // We will iterate through the references to the element returned by std::os::env();
-/// for &(ref key, ref value) in std::os::env().iter() {
+/// use std::os;
+///
+/// // We will iterate through the references to the element returned by os::env();
+/// for &(ref key, ref value) in os::env().iter() {
 ///     println!("'{}': '{}'", key, value );
 /// }
 /// ```
@@ -306,8 +312,10 @@ fn env_convert(input: Vec<Vec<u8>>) -> Vec<(Vec<u8>, Vec<u8>)> {
 /// # Example
 ///
 /// ```rust
+/// use std::os;
+///
 /// let key = "HOME";
-/// match std::os::getenv(key) {
+/// match os::getenv(key) {
 ///     Some(val) => println!("{}: {}", key, val),
 ///     None => println!("{} is not defined in the environment.", key)
 /// }
@@ -361,45 +369,49 @@ pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
     getenv(n).map(|s| s.into_bytes())
 }
 
-
-#[cfg(unix)]
 /// Sets the environment variable `n` to the value `v` for the currently running
-/// process
+/// process.
 ///
-/// # Failure
+/// # Example
 ///
-/// Fails if `n` or `v` have any interior NULs.
+/// ```rust
+/// use std::os;
+///
+/// let key = "KEY";
+/// os::setenv(key, "VALUE");
+/// match os::getenv(key) {
+///     Some(ref val) => println!("{}: {}", key, val),
+///     None => println!("{} is not defined in the environment.", key)
+/// }
+/// ```
 pub fn setenv(n: &str, v: &str) {
-    unsafe {
-        with_env_lock(|| {
-            n.with_c_str(|nbuf| {
-                v.with_c_str(|vbuf| {
-                    libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1);
+    #[cfg(unix)]
+    fn _setenv(n: &str, v: &str) {
+        unsafe {
+            with_env_lock(|| {
+                n.with_c_str(|nbuf| {
+                    v.with_c_str(|vbuf| {
+                        libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1);
+                    })
                 })
             })
-        })
+        }
     }
-}
-
 
-#[cfg(windows)]
-/// Sets the environment variable `n` to the value `v` for the currently running
-/// process
-pub fn setenv(n: &str, v: &str) {
-    let n = n.to_utf16().append_one(0);
-    let v = v.to_utf16().append_one(0);
-    unsafe {
-        with_env_lock(|| {
-            libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr());
-        })
+    #[cfg(windows)]
+    fn _setenv(n: &str, v: &str) {
+        let n = n.to_utf16().append_one(0);
+        let v = v.to_utf16().append_one(0);
+        unsafe {
+            with_env_lock(|| {
+                libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr());
+            })
+        }
     }
+    _setenv(n, v)
 }
 
-/// Remove a variable from the environment entirely
-///
-/// # Failure
-///
-/// Fails (on unix) if `n` has any interior NULs.
+/// Remove a variable from the environment entirely.
 pub fn unsetenv(n: &str) {
     #[cfg(unix)]
     fn _unsetenv(n: &str) {
@@ -411,6 +423,7 @@ fn _unsetenv(n: &str) {
             })
         }
     }
+
     #[cfg(windows)]
     fn _unsetenv(n: &str) {
         let n = n.to_utf16().append_one(0);
@@ -420,13 +433,28 @@ fn _unsetenv(n: &str) {
             })
         }
     }
-
     _unsetenv(n);
 }
 
 #[cfg(unix)]
 /// Parse a string or vector according to the platform's conventions
-/// for the `PATH` environment variable. Drops empty paths.
+/// for the `PATH` environment variable and return a Vec<Path>.
+/// Drops empty paths.
+///
+/// # Example
+/// ```rust
+/// use std::os;
+///
+/// let key = "PATH";
+/// match os::getenv(key) {
+///     Some(paths) => {
+///         for path in os::split_paths(paths).iter() {
+///             println!("'{}'", path.display());
+///         }
+///     }
+///     None => println!("{} is not defined in the environnement.", key)
+/// }
+/// ```
 pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
     unparsed.container_as_bytes()
             .split(|b| *b == ':' as u8)
@@ -491,7 +519,7 @@ pub struct Pipe {
     pub out: c_int,
 }
 
-/// Creates a new low-level OS in-memory pipe.
+/// Creates a new low-level OS in-memory pipe represented as a Pipe struct.
 #[cfg(unix)]
 pub fn pipe() -> Pipe {
     unsafe {
@@ -502,7 +530,7 @@ pub fn pipe() -> Pipe {
     }
 }
 
-/// Creates a new low-level OS in-memory pipe.
+/// Creates a new low-level OS in-memory pipe represented as a Pipe struct.
 #[cfg(windows)]
 pub fn pipe() -> Pipe {
     unsafe {
@@ -522,13 +550,25 @@ pub fn pipe() -> Pipe {
     }
 }
 
-/// Returns the proper dll filename for the given basename of a file.
+/// Returns the proper dll filename for the given basename of a file
+/// as a String.
 pub fn dll_filename(base: &str) -> String {
     format!("{}{}{}", consts::DLL_PREFIX, base, consts::DLL_SUFFIX)
 }
 
-/// Optionally returns the filesystem path of the current executable which is
-/// running. If any failure occurs, None is returned.
+/// Optionally returns the filesystem path to the current executable which is
+/// running but with the executable name.
+///
+/// # Examples
+///
+/// ```rust
+/// use std::os;
+///
+/// match os::self_exe_name() {
+///     Some(exe_path) => println!("Path of this executable is: {}", exe_path.display()),
+///     None => println!("Unable to get the path of this executable!")
+/// };
+/// ```
 pub fn self_exe_name() -> Option<Path> {
 
     #[cfg(target_os = "freebsd")]
@@ -536,7 +576,7 @@ fn load_self() -> Option<Vec<u8>> {
         unsafe {
             use libc::funcs::bsd44::*;
             use libc::consts::os::extra::*;
-            let mib = box [CTL_KERN as c_int,
+            let mib = vec![CTL_KERN as c_int,
                         KERN_PROC as c_int,
                         KERN_PROC_PATHNAME as c_int, -1 as c_int];
             let mut sz: libc::size_t = 0;
@@ -598,47 +638,71 @@ fn load_self() -> Option<Vec<u8>> {
 }
 
 /// Optionally returns the filesystem path to the current executable which is
-/// running. Like self_exe_name() but without the binary's name.
-/// If any failure occurs, None is returned.
+/// running.
+///
+/// Like self_exe_name() but without the binary's name.
+///
+/// # Example
+///
+/// ```rust
+/// use std::os;
+///
+/// match os::self_exe_path() {
+///     Some(exe_path) => println!("Executable's Path is: {}", exe_path.display()),
+///     None => println!("Impossible to fetch the path of this executable.")
+/// };
+/// ```
 pub fn self_exe_path() -> Option<Path> {
     self_exe_name().map(|mut p| { p.pop(); p })
 }
 
-/**
- * Returns the path to the user's home directory, if known.
- *
- * On Unix, returns the value of the 'HOME' environment variable if it is set
- * and not equal to the empty string.
- *
- * On Windows, returns the value of the 'HOME' environment variable if it is
- * set and not equal to the empty string. Otherwise, returns the value of the
- * 'USERPROFILE' environment variable if it is set and not equal to the empty
- * string.
- *
- * Otherwise, homedir returns option::none.
- */
+/// Optionally returns the path to the current user's home directory if known.
+///
+/// # Unix
+///
+/// Returns the value of the 'HOME' environment variable if it is set
+/// and not equal to the empty string.
+///
+/// # Windows
+///
+/// Returns the value of the 'HOME' environment variable if it is
+/// set and not equal to the empty string. Otherwise, returns the value of the
+/// 'USERPROFILE' environment variable if it is set and not equal to the empty
+/// string.
+///
+/// # Example
+///
+/// ```rust
+/// use std::os;
+///
+/// match os::homedir() {
+///     Some(ref p) => println!("{}", p.display()),
+///     None => println!("Impossible to get your home dir!")
+/// }
+/// ```
 pub fn homedir() -> Option<Path> {
-    // FIXME (#7188): getenv needs a Vec<u8> variant
-    return match getenv("HOME") {
-        Some(ref p) if !p.is_empty() => Path::new_opt(p.as_slice()),
-        _ => secondary()
-    };
-
+    #[inline]
     #[cfg(unix)]
-    fn secondary() -> Option<Path> {
-        None
+    fn _homedir() -> Option<Path> {
+        aux_homedir("HOME")
     }
 
+    #[inline]
     #[cfg(windows)]
-    fn secondary() -> Option<Path> {
-        getenv("USERPROFILE").and_then(|p| {
-            if !p.is_empty() {
-                Path::new_opt(p)
-            } else {
-                None
-            }
-        })
+    fn _homedir() -> Option<Path> {
+        aux_homedir("HOME").or(aux_homedir("USERPROFILE"))
+    }
+
+    #[inline]
+    fn aux_homedir(home_name: &str) -> Option<Path> {
+        match getenv_as_bytes(home_name) {
+            Some(p)  => {
+                if p.is_empty() { None } else { Path::new_opt(p) }
+            },
+            _ => None
+        }
     }
+    _homedir()
 }
 
 /**
@@ -1732,7 +1796,7 @@ fn homedir() {
         assert!(os::homedir().is_none());
 
         for s in oldhome.iter() {
-            setenv("HOME", s.as_slice())
+            setenv("HOME", s.as_slice());
         }
     }
 
@@ -1761,10 +1825,10 @@ fn homedir() {
         assert!(os::homedir() == Some(Path::new("/home/MountainView")));
 
         for s in oldhome.iter() {
-            setenv("HOME", s.as_slice())
+            setenv("HOME", s.as_slice());
         }
         for s in olduserprofile.iter() {
-            setenv("USERPROFILE", s.as_slice())
+            setenv("USERPROFILE", s.as_slice());
         }
     }
 
index a101f0432126e2ff4de213bd9303071fc42f9514..7d15893af241e865136b1194dca2536d8cff462a 100644 (file)
@@ -63,8 +63,6 @@
 
 */
 
-#![deny(deprecated_owned_vector)]
-
 use collections::Collection;
 use c_str::CString;
 use clone::Clone;
@@ -527,13 +525,6 @@ fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
     }
 }
 
-impl BytesContainer for ~[u8] {
-    #[inline]
-    fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
-        self.as_slice()
-    }
-}
-
 impl BytesContainer for Vec<u8> {
     #[inline]
     fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
index 171535edbeb346b2ac4ce429a9e4f3609db81eba..494428de3a5c48aadaf85dc7563208bac908cae4 100644 (file)
@@ -22,7 +22,7 @@
 use str::Str;
 use str;
 use slice::{CloneableVector, Splits, Vector, VectorVector,
-            ImmutableEqVector, OwnedVector, ImmutableVector};
+            ImmutableEqVector, ImmutableVector};
 use vec::Vec;
 
 use super::{BytesContainer, GenericPath, GenericPathUnsafe};
@@ -282,7 +282,6 @@ fn is_ancestor_of(&self, other: &Path) -> bool {
         }
     }
 
-    #[allow(deprecated_owned_vector)]
     fn path_relative_from(&self, base: &Path) -> Option<Path> {
         if self.is_absolute() != base.is_absolute() {
             if self.is_absolute() {
index 5a1d60192fc24afe045441c506ddfae2f83d3479..b9bb0054d441a4216210956e032b0d2009ab259d 100644 (file)
@@ -21,7 +21,7 @@
 use iter::{AdditiveIterator, DoubleEndedIterator, Extendable, Iterator, Map};
 use mem;
 use option::{Option, Some, None};
-use slice::{Vector, OwnedVector, ImmutableVector};
+use slice::{Vector, ImmutableVector};
 use str::{CharSplits, Str, StrAllocating, StrVector, StrSlice};
 use string::String;
 use vec::Vec;
index eb862ecf932901c72046ca5641f6aaa52e5f885b..6fb08b6ef7556fe5906de31f4207b023ea2619d0 100644 (file)
@@ -83,7 +83,7 @@
 #[doc(no_inline)] pub use slice::{MutableCloneableVector, MutableOrdVector};
 #[doc(no_inline)] pub use slice::{ImmutableVector, MutableVector};
 #[doc(no_inline)] pub use slice::{ImmutableEqVector, ImmutableOrdVector};
-#[doc(no_inline)] pub use slice::{Vector, VectorVector, OwnedVector};
+#[doc(no_inline)] pub use slice::{Vector, VectorVector};
 #[doc(no_inline)] pub use slice::MutableVectorAllocating;
 #[doc(no_inline)] pub use string::String;
 #[doc(no_inline)] pub use vec::Vec;
index ee1935628871e52115f95b126fd0f92691c5d465..adc532879e2fade70329063df79dd22e9f8ab047 100644 (file)
@@ -60,7 +60,7 @@
 use std::rand::Rng;
 
 let mut rng = rand::task_rng();
-if rng.gen() { // bool
+if rng.gen() { // random bool
     println!("int: {}, uint: {}", rng.gen::<int>(), rng.gen::<uint>())
 }
 ```
index 8655d1e47d51a01772f112c8fde0102bc45c2a82..fe5d8fc068c919b50d18baa8bf92545cd3bc49fe 100644 (file)
@@ -71,7 +71,6 @@ fn fill_bytes(&mut self, v: &mut [u8]) {
 }
 
 #[cfg(test)]
-#[allow(deprecated_owned_vector)]
 mod test {
     use prelude::*;
 
@@ -83,24 +82,23 @@ mod test {
     #[test]
     fn test_reader_rng_u64() {
         // transmute from the target to avoid endianness concerns.
-        let v = box [1u64, 2u64, 3u64];
-        let bytes: ~[u8] = unsafe {mem::transmute(v)};
-        let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));
+        let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1,
+                     0  , 0, 0, 0, 0, 0, 0, 2,
+                     0,   0, 0, 0, 0, 0, 0, 3];
+        let mut rng = ReaderRng::new(MemReader::new(v));
 
-        assert_eq!(rng.next_u64(), 1);
-        assert_eq!(rng.next_u64(), 2);
-        assert_eq!(rng.next_u64(), 3);
+        assert_eq!(rng.next_u64(), mem::to_be64(1));
+        assert_eq!(rng.next_u64(), mem::to_be64(2));
+        assert_eq!(rng.next_u64(), mem::to_be64(3));
     }
     #[test]
     fn test_reader_rng_u32() {
-        // transmute from the target to avoid endianness concerns.
-        let v = box [1u32, 2u32, 3u32];
-        let bytes: ~[u8] = unsafe {mem::transmute(v)};
-        let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));
+        let v = vec![0u8, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3];
+        let mut rng = ReaderRng::new(MemReader::new(v));
 
-        assert_eq!(rng.next_u32(), 1);
-        assert_eq!(rng.next_u32(), 2);
-        assert_eq!(rng.next_u32(), 3);
+        assert_eq!(rng.next_u32(), mem::to_be32(1));
+        assert_eq!(rng.next_u32(), mem::to_be32(2));
+        assert_eq!(rng.next_u32(), mem::to_be32(3));
     }
     #[test]
     fn test_reader_rng_fill_bytes() {
index 3b223b68ee666204d7d7412ef6c85317e3f9fa02..9a1c0151e5411b1b55ee851a48cf5a556fb3c126 100644 (file)
@@ -37,8 +37,8 @@ fn to_str(&self) -> String {
 
 #[cfg(test)]
 mod tests {
+    use prelude::*;
     use super::*;
-    use str::StrAllocating;
 
     #[test]
     fn test_simple_types() {
@@ -54,11 +54,11 @@ fn test_simple_types() {
 
     #[test]
     fn test_vectors() {
-        let x: ~[int] = box [];
+        let x: Vec<int> = vec![];
         assert_eq!(x.to_str(), "[]".to_string());
-        assert_eq!((box [1]).to_str(), "[1]".to_string());
-        assert_eq!((box [1, 2, 3]).to_str(), "[1, 2, 3]".to_string());
-        assert!((box [box [], box [1], box [1, 1]]).to_str() ==
+        assert_eq!((vec![1]).to_str(), "[1]".to_string());
+        assert_eq!((vec![1, 2, 3]).to_str(), "[1, 2, 3]".to_string());
+        assert!((vec![vec![], vec![1], vec![1, 1]]).to_str() ==
                "[[], [1], [1, 1]]".to_string());
     }
 }
index 9f0109282564293db77e4ac8b5939202c344d0e2..66ca10b196c6c4363a6890d9140241a0a7b78f52 100644 (file)
@@ -26,7 +26,7 @@
        html_root_url = "http://doc.rust-lang.org/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![feature(phase, globs, macro_rules)]
-#![deny(deprecated_owned_vector)]
+
 #![deny(missing_doc)]
 #![no_std]
 
index 2f6caa1d6ff881b29fe18f2668ed0a7cd02513d6..5240d303ca45b27974ed3ce39b2cafafbab34de6 100644 (file)
 
 use mutex::{StaticMutex, MUTEX_INIT};
 
-/// A type which can be used to run a one-time global initialization. This type
-/// is *unsafe* to use because it is built on top of the `Mutex` in this module.
-/// It does not know whether the currently running task is in a green or native
-/// context, and a blocking mutex should *not* be used under normal
-/// circumstances on a green task.
-///
-/// Despite its unsafety, it is often useful to have a one-time initialization
-/// routine run for FFI bindings or related external functionality. This type
-/// can only be statically constructed with the `ONCE_INIT` value.
+/// A synchronization primitive which can be used to run a one-time global
+/// initialization. Useful for one-time initialization for FFI or related
+/// functionality. This type can only be constructed with the `ONCE_INIT`
+/// value.
 ///
 /// # Example
 ///
@@ -36,6 +31,7 @@
 /// use sync::one::{Once, ONCE_INIT};
 ///
 /// static mut START: Once = ONCE_INIT;
+///
 /// unsafe {
 ///     START.doit(|| {
 ///         // run initialization here
@@ -60,7 +56,7 @@ impl Once {
     /// will be executed if this is the first time `doit` has been called, and
     /// otherwise the routine will *not* be invoked.
     ///
-    /// This method will block the calling *os thread* if another initialization
+    /// This method will block the calling task if another initialization
     /// routine is currently running.
     ///
     /// When this function returns, it is guaranteed that some initialization
index d9e3e4e941d2b208ed64f207c3bb40a827c59257..c917198e7d4714fa31ab8ac82bee0e3687f7daf8 100644 (file)
@@ -421,6 +421,41 @@ pub fn get_filemap(&self, filename: &str) -> Rc<FileMap> {
         fail!("asking for {} which we don't know about", filename);
     }
 
+    pub fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos {
+        let idx = self.lookup_filemap_idx(bpos);
+        let fm = self.files.borrow().get(idx).clone();
+        let offset = bpos - fm.start_pos;
+        FileMapAndBytePos {fm: fm, pos: offset}
+    }
+
+    // Converts an absolute BytePos to a CharPos relative to the filemap and above.
+    pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
+        debug!("codemap: converting {:?} to char pos", bpos);
+        let idx = self.lookup_filemap_idx(bpos);
+        let files = self.files.borrow();
+        let map = files.get(idx);
+
+        // The number of extra bytes due to multibyte chars in the FileMap
+        let mut total_extra_bytes = 0;
+
+        for mbc in map.multibyte_chars.borrow().iter() {
+            debug!("codemap: {:?}-byte char at {:?}", mbc.bytes, mbc.pos);
+            if mbc.pos < bpos {
+                // every character is at least one byte, so we only
+                // count the actual extra bytes.
+                total_extra_bytes += mbc.bytes - 1;
+                // We should never see a byte position in the middle of a
+                // character
+                assert!(bpos.to_uint() >= mbc.pos.to_uint() + mbc.bytes);
+            } else {
+                break;
+            }
+        }
+
+        assert!(map.start_pos.to_uint() + total_extra_bytes <= bpos.to_uint());
+        CharPos(bpos.to_uint() - map.start_pos.to_uint() - total_extra_bytes)
+    }
+
     fn lookup_filemap_idx(&self, pos: BytePos) -> uint {
         let files = self.files.borrow();
         let files = files;
@@ -491,41 +526,6 @@ fn lookup_pos(&self, pos: BytePos) -> Loc {
             col: chpos - linechpos
         }
     }
-
-    fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos {
-        let idx = self.lookup_filemap_idx(bpos);
-        let fm = self.files.borrow().get(idx).clone();
-        let offset = bpos - fm.start_pos;
-        FileMapAndBytePos {fm: fm, pos: offset}
-    }
-
-    // Converts an absolute BytePos to a CharPos relative to the filemap.
-    fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
-        debug!("codemap: converting {:?} to char pos", bpos);
-        let idx = self.lookup_filemap_idx(bpos);
-        let files = self.files.borrow();
-        let map = files.get(idx);
-
-        // The number of extra bytes due to multibyte chars in the FileMap
-        let mut total_extra_bytes = 0;
-
-        for mbc in map.multibyte_chars.borrow().iter() {
-            debug!("codemap: {:?}-byte char at {:?}", mbc.bytes, mbc.pos);
-            if mbc.pos < bpos {
-                // every character is at least one byte, so we only
-                // count the actual extra bytes.
-                total_extra_bytes += mbc.bytes - 1;
-                // We should never see a byte position in the middle of a
-                // character
-                assert!(bpos.to_uint() >= mbc.pos.to_uint() + mbc.bytes);
-            } else {
-                break;
-            }
-        }
-
-        assert!(map.start_pos.to_uint() + total_extra_bytes <= bpos.to_uint());
-        CharPos(bpos.to_uint() - map.start_pos.to_uint() - total_extra_bytes)
-    }
 }
 
 #[cfg(test)]
index 9706176ca8babbe9e26a4d7b567a187a5c5737a7..e280c244929836d86080a9752978bd05ff61fee8 100644 (file)
@@ -30,6 +30,7 @@ pub enum ObsoleteSyntax {
     ObsoleteOwnedType,
     ObsoleteOwnedExpr,
     ObsoleteOwnedPattern,
+    ObsoleteOwnedVector,
 }
 
 pub trait ParserObsoleteMethods {
@@ -63,6 +64,10 @@ fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
                 "`~` notation for owned pointer patterns",
                 "use the `box` operator instead of `~`"
             ),
+            ObsoleteOwnedVector => (
+                "`~[T]` is no longer a type",
+                "use the `Vec` type instead"
+            ),
         };
 
         self.report(sp, kind, kind_str, desc);
index 282f4065e4ff125fc5043140b18285364dfbe693..437b06e3df65b252f8d7a943d352ad6d2b82ec4d 100644 (file)
@@ -1322,11 +1322,8 @@ pub fn parse_ty(&mut self, _: bool) -> P<Ty> {
             // OWNED POINTER
             self.bump();
             match self.token {
-                token::IDENT(ref ident, _)
-                        if "str" == token::get_ident(*ident).get() => {
-                    // This is OK (for now).
-                }
-                token::LBRACKET => {}   // Also OK.
+                token::LBRACKET =>
+                    self.obsolete(self.last_span, ObsoleteOwnedVector),
                 _ => self.obsolete(self.last_span, ObsoleteOwnedType),
             };
             TyUniq(self.parse_ty(false))
@@ -2349,7 +2346,10 @@ pub fn parse_prefix_expr(&mut self) -> Gc<Expr> {
             hi = e.span.hi;
             // HACK: turn ~[...] into a ~-vec
             ex = match e.node {
-              ExprVec(..) | ExprRepeat(..) => ExprVstore(e, ExprVstoreUniq),
+              ExprVec(..) | ExprRepeat(..) => {
+                  self.obsolete(self.last_span, ObsoleteOwnedVector);
+                  ExprVstore(e, ExprVstoreUniq)
+              }
               ExprLit(lit) if lit_is_str(lit) => {
                   self.obsolete(self.last_span, ObsoleteOwnedExpr);
                   ExprVstore(e, ExprVstoreUniq)
@@ -2382,6 +2382,7 @@ pub fn parse_prefix_expr(&mut self) -> Gc<Expr> {
             // HACK: turn `box [...]` into a boxed-vec
             ex = match subexpression.node {
                 ExprVec(..) | ExprRepeat(..) => {
+                    self.obsolete(self.last_span, ObsoleteOwnedVector);
                     ExprVstore(subexpression, ExprVstoreUniq)
                 }
                 ExprLit(lit) if lit_is_str(lit) => {
index 7d94e46a88a6e74b5769e57e1f5fc4e979422482..d0101e993c49d191ad10ccb11a423e6702cb1366 100644 (file)
@@ -33,7 +33,6 @@
        html_root_url = "http://doc.rust-lang.org/")]
 
 #![feature(asm, macro_rules, phase)]
-#![deny(deprecated_owned_vector)]
 
 extern crate getopts;
 extern crate regex;
@@ -72,7 +71,7 @@ pub mod test {
              MetricChange, Improvement, Regression, LikelyNoise,
              StaticTestFn, StaticTestName, DynTestName, DynTestFn,
              run_test, test_main, test_main_static, filter_tests,
-             parse_opts, StaticBenchFn, test_main_static_x};
+             parse_opts, StaticBenchFn};
 }
 
 pub mod stats;
@@ -263,14 +262,6 @@ pub fn test_main_static(args: &[String], tests: &[TestDescAndFn]) {
     test_main(args, owned_tests)
 }
 
-pub fn test_main_static_x(args: &[~str], tests: &[TestDescAndFn]) {
-    test_main_static(args.iter()
-                         .map(|x| x.to_string())
-                         .collect::<Vec<_>>()
-                         .as_slice(),
-                     tests)
-}
-
 pub enum ColorConfig {
     AutoColor,
     AlwaysColor,
index d07e5662feb1c52582185b7db59c82c1a2680024..b0562c39dc28564fcede67e5d72b417b317ca84c 100644 (file)
@@ -167,7 +167,6 @@ pub fn new(samples: &[T]) -> Summary<T> {
 impl<'a,T: FloatMath + FromPrimitive> Stats<T> for &'a [T] {
 
     // FIXME #11059 handle NaN, inf and overflow
-    #[allow(deprecated_owned_vector)]
     fn sum(self) -> T {
         let mut partials = vec![];
 
@@ -1027,7 +1026,6 @@ fn test_unif25() {
 
     #[test]
     fn test_boxplot_nonpositive() {
-        #[allow(deprecated_owned_vector)]
         fn t(s: &Summary<f64>, expected: String) {
             use std::io::MemWriter;
             let mut m = MemWriter::new();
index c13cce36c0a915e035c45abb9923b565dd68415f..63523cd3a6f6a877482e2da76f4d5743e3f515fa 100644 (file)
@@ -20,7 +20,6 @@
        html_root_url = "http://doc.rust-lang.org/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![feature(phase)]
-#![deny(deprecated_owned_vector)]
 
 #[cfg(test)] extern crate debug;
 
index 2157aecf37613f18104337eca70833917825ef1f..f42844b9f19d2612e3b7873ab5a344b62556e6c4 100644 (file)
@@ -318,7 +318,7 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateStructType(
         unwrapDI<DIArray>(Elements),
         RunTimeLang,
         unwrapDI<DIType>(VTableHolder)
-#if LLVM_VERSION_MINOR >= 5
+#if LLVM_VERSION_MINOR >= 4
         ,UniqueId
 #endif
         ));
@@ -510,7 +510,7 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
         Flags,
         unwrapDI<DIArray>(Elements),
         RunTimeLang
-#if LLVM_VERSION_MINOR >= 5
+#if LLVM_VERSION_MINOR >= 4
         ,UniqueId
 #endif
         ));
@@ -734,6 +734,11 @@ LLVMVersionMinor() {
     return LLVM_VERSION_MINOR;
 }
 
+extern "C" int
+LLVMVersionMajor() {
+    return LLVM_VERSION_MAJOR;
+}
+
 // Note that the two following functions look quite similar to the
 // LLVMGetSectionName function. Sadly, it appears that this function only
 // returns a char* pointer, which isn't guaranteed to be null-terminated. The
diff --git a/src/test/auxiliary/cross_crate_debuginfo_type_uniquing.rs b/src/test/auxiliary/cross_crate_debuginfo_type_uniquing.rs
new file mode 100644 (file)
index 0000000..f4bc723
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+#![crate_type = "rlib"]
+// compile-flags:-g
+
+struct S1;
+
+impl S1 {
+    fn f(&mut self) { }
+}
+
+
+struct S2;
+
+impl S2 {
+    fn f(&mut self) { }
+}
index 64f3e633d034c4d3a719fb81fde7cb30cb189cb8..19b9d5638d0d8f3f034586958591b6322ebacd26 100644 (file)
@@ -75,7 +75,7 @@ fn main() {
     let clen = seq.len();
 
     let mut seqlen = Future::spawn(proc() {
-        let substs = ~[
+        let substs = vec![
             (regex!("B"), "(c|g|t)"),
             (regex!("D"), "(a|g|t)"),
             (regex!("H"), "(a|c|t)"),
@@ -95,7 +95,7 @@ fn main() {
         seq.len()
     });
 
-    let variants = ~[
+    let variants = vec![
         regex!("agggtaaa|tttaccct"),
         regex!("[cgt]gggtaaa|tttaccc[acg]"),
         regex!("a[act]ggtaaa|tttacc[agt]t"),
index 3ced98592400ee24692a8cea022465d00579e0f7..3cd582ca0b8c3a9bad17071194031bd10ca34b64 100644 (file)
@@ -9,11 +9,10 @@
 // except according to those terms.
 
 fn test() {
-    let w: ~[int];
+    let w: &mut [int];
     w[5] = 0; //~ ERROR use of possibly uninitialized variable: `w`
-              //~^ ERROR cannot assign to immutable vec content `w[..]`
 
-    let mut w: ~[int];
+    let mut w: &mut [int];
     w[5] = 0; //~ ERROR use of possibly uninitialized variable: `w`
 }
 
index b12e6799e6a7945920ad22b8b01cd5d08155f40d..7457a1020cee1c31c7fdf01bfaa6663fdb5497c9 100644 (file)
@@ -11,8 +11,6 @@
 #![deny(unreachable_code)]
 #![allow(unused_variable)]
 #![allow(dead_code)]
-#![allow(deprecated_owned_vector)]
-
 
 fn fail_len(v: Vec<int> ) -> uint {
     let mut i = 3;
diff --git a/src/test/compile-fail/lint-deprecated-owned-vector.rs b/src/test/compile-fail/lint-deprecated-owned-vector.rs
deleted file mode 100644 (file)
index 537f3c9..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![deny(deprecated_owned_vector)]
-
-fn main() {
-    ~[1]; //~ ERROR use of deprecated `~[]`
-    //~^ ERROR use of deprecated `~[]`
-}
index ae18e9bebad599b07c45a29ba05203fca3f55af1..26cae1aa708112331822d8e9aef3649bf733d1b3 100644 (file)
@@ -11,7 +11,6 @@
 #![feature(managed_boxes)]
 #![forbid(heap_memory)]
 #![allow(dead_code)]
-#![allow(deprecated_owned_vector)]
 
 
 struct Foo {
index cb05c2833345c0d2fec11866bf5eb56247d1186c..4334d2f63ea59c41e94263c90b12700daf9330d6 100644 (file)
@@ -11,7 +11,6 @@
 #![feature(globs)]
 #![deny(unused_imports)]
 #![allow(dead_code)]
-#![allow(deprecated_owned_vector)]
 
 use cal = bar::c::cc;
 
index 671fecc4e22e7581d57ffca4a3f463b86c56dbfe..d5f34669a25e2355b415b366485fa2fce3ea2cb6 100644 (file)
@@ -13,7 +13,6 @@
 #![allow(dead_assignment)]
 #![allow(unused_variable)]
 #![allow(dead_code)]
-#![allow(deprecated_owned_vector)]
 #![deny(unused_mut)]
 
 
index 7c459434bcabd1023d47f86e05654ecee8195f1d..8ae3f1fdd0d74bc76efe6ba3a745d1885edb2771 100644 (file)
@@ -12,7 +12,6 @@
 
 #![allow(dead_code)]
 #![deny(unused_unsafe)]
-#![allow(deprecated_owned_vector)]
 
 
 mod foo {
diff --git a/src/test/compile-fail/shadowing-in-the-same-pattern.rs b/src/test/compile-fail/shadowing-in-the-same-pattern.rs
new file mode 100644 (file)
index 0000000..0b78023
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test for issue #14581.
+
+fn f((a, a): (int, int)) {} //~ ERROR identifier `a` is bound more than once
+
+fn main() {
+    let (a, a) = (1, 1);    //~ ERROR identifier `a` is bound more than once
+}
+
diff --git a/src/test/debuginfo/cross-crate-type-uniquing.rs b/src/test/debuginfo/cross-crate-type-uniquing.rs
new file mode 100644 (file)
index 0000000..47de06c
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-android: FIXME(#10381)
+
+// aux-build:cross_crate_debuginfo_type_uniquing.rs
+extern crate cross_crate_debuginfo_type_uniquing;
+
+// no-prefer-dynamic
+// compile-flags:-g -Zlto
+
+pub struct C;
+pub fn p() -> C {
+    C
+}
+
+fn main() { }
\ No newline at end of file
diff --git a/src/test/run-make/save-analysis/Makefile b/src/test/run-make/save-analysis/Makefile
new file mode 100644 (file)
index 0000000..e1cbf75
--- /dev/null
@@ -0,0 +1,3 @@
+-include ../tools.mk
+all:
+       $(RUSTC) foo.rs -Zsave-analysis
diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make/save-analysis/foo.rs
new file mode 100644 (file)
index 0000000..bf5cc83
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+    f: int
+}
+
+impl Foo {
+    fn bar(&self) -> int {
+        println!("f is {}", self.f);
+        self.f
+    }
+}
+
+trait Tr {
+    fn tar(&self, x: Box<Foo>) -> Foo;
+}
+
+impl Tr for Foo {
+    fn tar(&self, x: Box<Foo>) -> Foo {
+        Foo{ f: self.f + x.f }
+    }
+}
+
+trait Tr2<X, Y: Tr> {
+    fn squid(&self, y: &Y, z: Self) -> Box<X>;
+}
+
+impl Tr2<Foo, Foo> for Foo {
+    fn squid(&self, y: &Foo, z: Foo) -> Box<Foo> {
+        box Foo { f: y.f + z.f + self.f }
+    }
+}
+
+enum En {
+    Var1,
+    Var2,
+    Var3(int, int, Foo)
+}
+
+fn main() {
+    let x = Foo { f: 237 };
+    let _f = x.bar();
+    let en = Var2;
+
+    let _ = match en {
+        Var1 => x.bar(),
+        Var2 => 34,
+        Var3(x, y, f) => f.bar()
+    };
+}
index a6baf21549e5845f8f7bfdbd63998d98b2af72a3..15544468ae992a7ecdc4cbbce137c92ee54bbfbc 100644 (file)
@@ -13,7 +13,4 @@ pub fn main() {
 
     struct Foo;
     assert!(Some(box Foo).is_some());
-
-    let xs: ~[()] = ~[];
-    assert!(Some(xs).is_some());
 }
index bf108dbe4d886b30a3a3fac9a83608c7950343d6..e00b3bb64bd3b1c57a19180662acee02f61d900a 100644 (file)
@@ -13,7 +13,6 @@
 #![feature(macro_rules, managed_boxes)]
 #![deny(warnings)]
 #![allow(unused_must_use)]
-#![allow(deprecated_owned_vector)]
 
 extern crate debug;
 
index 782cea2979f2702966cdd65bf942fcfa83bfe17c..cd5903ad4e3b5f6d2ab949ee7787d3e597f1d87f 100644 (file)
@@ -45,7 +45,7 @@ pub fn main() {
     p.borrow_mut().y += 3;
     assert_eq!(*p.borrow(), Point {x: 3, y: 5});
 
-    let v = Rc::new(RefCell::new(~[1, 2, 3]));
+    let v = Rc::new(RefCell::new([1, 2, 3]));
     v.borrow_mut()[0] = 3;
     v.borrow_mut()[1] += 3;
     assert_eq!((v.borrow()[0], v.borrow()[1], v.borrow()[2]), (3, 5, 3));
index 6fbb311593bfafd96fb4883f5d7554a279e9e5a3..b471d13901e093a4878c370ad2df856ca81ab7b0 100644 (file)
@@ -62,8 +62,6 @@ fn visit_f128(&mut self) -> bool { true }
 
     fn visit_char(&mut self) -> bool { true }
 
-    fn visit_estr_box(&mut self) -> bool { true }
-    fn visit_estr_uniq(&mut self) -> bool { true }
     fn visit_estr_slice(&mut self) -> bool { true }
     fn visit_estr_fixed(&mut self,
                         _sz: uint, _sz2: uint,
@@ -74,13 +72,6 @@ fn visit_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_ptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_rptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
 
-    fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool {
-        self.types.push("[".to_string());
-        unsafe { visit_tydesc(inner, &mut *self as &mut TyVisitor); }
-        self.types.push("]".to_string());
-        true
-    }
     fn visit_evec_slice(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_evec_fixed(&mut self, _n: uint, _sz: uint, _align: uint,
                         _mtbl: uint, _inner: *TyDesc) -> bool { true }