about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/doc/reference.md14
-rwxr-xr-xsrc/etc/generate-deriving-span-tests.py1
-rw-r--r--src/libcollections/ring_buf.rs711
-rw-r--r--src/libcore/option.rs25
-rw-r--r--src/librustc/diagnostics.rs1
-rw-r--r--src/librustc/lint/builtin.rs20
-rw-r--r--src/librustc/lint/context.rs1
-rw-r--r--src/librustc/lint/mod.rs1
-rw-r--r--src/librustc/metadata/tydecode.rs1
-rw-r--r--src/librustc/metadata/tyencode.rs1
-rw-r--r--src/librustc/middle/check_match.rs8
-rw-r--r--src/librustc/middle/const_eval.rs5
-rw-r--r--src/librustc/middle/privacy.rs8
-rw-r--r--src/librustc/middle/resolve.rs16
-rw-r--r--src/librustc/middle/save/mod.rs21
-rw-r--r--src/librustc/middle/traits/coherence.rs1
-rw-r--r--src/librustc/middle/traits/select.rs1
-rw-r--r--src/librustc/middle/trans/_match.rs2
-rw-r--r--src/librustc/middle/trans/adt.rs14
-rw-r--r--src/librustc/middle/trans/base.rs22
-rw-r--r--src/librustc/middle/trans/callee.rs4
-rw-r--r--src/librustc/middle/trans/consts.rs1
-rw-r--r--src/librustc/middle/trans/context.rs8
-rw-r--r--src/librustc/middle/trans/debuginfo.rs29
-rw-r--r--src/librustc/middle/trans/foreign.rs2
-rw-r--r--src/librustc/middle/trans/glue.rs13
-rw-r--r--src/librustc/middle/trans/meth.rs1
-rw-r--r--src/librustc/middle/trans/type_of.rs8
-rw-r--r--src/librustc/middle/ty.rs124
-rw-r--r--src/librustc/middle/ty_fold.rs2
-rw-r--r--src/librustc/middle/typeck/astconv.rs89
-rw-r--r--src/librustc/middle/typeck/check/method.rs2
-rw-r--r--src/librustc/middle/typeck/check/mod.rs52
-rw-r--r--src/librustc/middle/typeck/check/regionmanip.rs1
-rw-r--r--src/librustc/middle/typeck/coherence/mod.rs4
-rw-r--r--src/librustc/middle/typeck/collect.rs8
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs5
-rw-r--r--src/librustc/middle/typeck/infer/error_reporting.rs18
-rw-r--r--src/librustc/middle/typeck/infer/skolemize.rs1
-rw-r--r--src/librustc/middle/typeck/mod.rs2
-rw-r--r--src/librustc/middle/typeck/variance.rs2
-rw-r--r--src/librustc/util/ppaux.rs3
-rw-r--r--src/librustdoc/clean/mod.rs54
-rw-r--r--src/librustdoc/html/format.rs34
-rw-r--r--src/libsyntax/ast.rs29
-rw-r--r--src/libsyntax/ext/base.rs2
-rw-r--r--src/libsyntax/ext/build.rs21
-rw-r--r--src/libsyntax/ext/concat.rs1
-rw-r--r--src/libsyntax/ext/deriving/encodable.rs6
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs2
-rw-r--r--src/libsyntax/ext/deriving/generic/ty.rs11
-rw-r--r--src/libsyntax/ext/expand.rs2
-rw-r--r--src/libsyntax/ext/format.rs2
-rw-r--r--src/libsyntax/feature_gate.rs15
-rw-r--r--src/libsyntax/fold.rs19
-rw-r--r--src/libsyntax/lib.rs2
-rw-r--r--src/libsyntax/parse/mod.rs7
-rw-r--r--src/libsyntax/parse/obsolete.rs6
-rw-r--r--src/libsyntax/parse/parser.rs168
-rw-r--r--src/libsyntax/print/pprust.rs102
-rw-r--r--src/libsyntax/test.rs18
-rw-r--r--src/libsyntax/visit.rs20
-rw-r--r--src/test/compile-fail/deriving-primitive.rs2
-rw-r--r--src/test/compile-fail/deriving-span-Clone-enum-struct-variant.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Clone-enum.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Clone-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Clone-tuple-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Default-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Default-tuple-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Hash-enum-struct-variant.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Hash-enum.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Hash-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Hash-tuple-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-PartialEq-enum-struct-variant.rs1
-rw-r--r--src/test/compile-fail/deriving-span-PartialEq-enum.rs1
-rw-r--r--src/test/compile-fail/deriving-span-PartialEq-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-PartialEq-tuple-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-PartialOrd-enum-struct-variant.rs1
-rw-r--r--src/test/compile-fail/deriving-span-PartialOrd-enum.rs1
-rw-r--r--src/test/compile-fail/deriving-span-PartialOrd-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-PartialOrd-tuple-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Rand-enum-struct-variant.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Rand-enum.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Rand-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Rand-tuple-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Show-enum-struct-variant.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Show-enum.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Show-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Show-tuple-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-TotalEq-enum-struct-variant.rs1
-rw-r--r--src/test/compile-fail/deriving-span-TotalEq-enum.rs1
-rw-r--r--src/test/compile-fail/deriving-span-TotalEq-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-TotalEq-tuple-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-TotalOrd-enum-struct-variant.rs1
-rw-r--r--src/test/compile-fail/deriving-span-TotalOrd-enum.rs1
-rw-r--r--src/test/compile-fail/deriving-span-TotalOrd-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-TotalOrd-tuple-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Zero-struct.rs1
-rw-r--r--src/test/compile-fail/deriving-span-Zero-tuple-struct.rs1
-rw-r--r--src/test/compile-fail/dup-struct-enum-struct-variant.rs2
-rw-r--r--src/test/compile-fail/gated-non-ascii-idents.rs3
-rw-r--r--src/test/compile-fail/issue-13624.rs2
-rw-r--r--src/test/compile-fail/issue-16939.rs2
-rw-r--r--src/test/compile-fail/issue-18252.rs2
-rw-r--r--src/test/compile-fail/lint-dead-code-4.rs1
-rw-r--r--src/test/compile-fail/lint-dead-code-5.rs1
-rw-r--r--src/test/compile-fail/lint-missing-doc.rs8
-rw-r--r--src/test/compile-fail/lint-raw-ptr-deriving.rs1
-rw-r--r--src/test/compile-fail/lint-visible-private-types.rs4
-rw-r--r--src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs2
-rw-r--r--src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs2
-rw-r--r--src/test/compile-fail/non-constant-enum-for-vec-repeat.rs2
-rw-r--r--src/test/compile-fail/non-exhaustive-pattern-witness.rs2
-rw-r--r--src/test/compile-fail/repeat_count.rs5
-rw-r--r--src/test/compile-fail/struct-like-enum-nonexhaustive.rs2
-rw-r--r--src/test/compile-fail/struct-variant-no-pub.rs (renamed from src/test/compile-fail/gated-struct-enums.rs)10
-rw-r--r--src/test/compile-fail/struct-variant-privacy-xc.rs2
-rw-r--r--src/test/compile-fail/struct-variant-privacy.rs2
-rw-r--r--src/test/compile-fail/unsized5.rs1
-rw-r--r--src/test/run-pass/concat.rs4
120 files changed, 1029 insertions, 843 deletions
diff --git a/src/doc/reference.md b/src/doc/reference.md
index 5d1401e27ba..28cb2de2923 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -133,7 +133,7 @@ Some productions are defined by exclusion of particular Unicode characters:
 
 ```{.ebnf .gram}
 comment : block_comment | line_comment ;
-block_comment : "/*" block_comment_body * '*' + '/' ;
+block_comment : "/*" block_comment_body * "*/" ;
 block_comment_body : [block_comment | character] * ;
 line_comment : "//" non_eol * ;
 ```
@@ -458,10 +458,9 @@ Examples of floating-point literals of various forms:
 12E+99_f64;                        // type f64
 ```
 
-##### Unit and boolean literals
+##### Boolean literals
 
-The _unit value_, the only value of the type that has the same name, is written
-as `()`. The two values of the boolean type are written `true` and `false`.
+The two values of the boolean type are written `true` and `false`.
 
 ### Symbols
 
@@ -2717,7 +2716,7 @@ or an item. Path expressions are [lvalues](#lvalues,-rvalues-and-temporaries).
 
 ### Tuple expressions
 
-Tuples are written by enclosing one or more comma-separated expressions in
+Tuples are written by enclosing zero or more comma-separated expressions in
 parentheses. They are used to create [tuple-typed](#tuple-types) values.
 
 ```{.tuple}
@@ -2726,6 +2725,11 @@ parentheses. They are used to create [tuple-typed](#tuple-types) values.
 ("a", 4u, true);
 ```
 
+### Unit expressions
+
+The expression `()` denotes the _unit value_, the only value of the type with
+the same name.
+
 ### Structure expressions
 
 ```{.ebnf .gram}
diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py
index 94b3fb6b93a..1e5d5ccf339 100755
--- a/src/etc/generate-deriving-span-tests.py
+++ b/src/etc/generate-deriving-span-tests.py
@@ -37,7 +37,6 @@ TEMPLATE = """// Copyright {year} The Rust Project Developers. See the COPYRIGHT
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 {error_deriving}
diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs
index 46fd86df987..e95660b546e 100644
--- a/src/libcollections/ring_buf.rs
+++ b/src/libcollections/ring_buf.rs
@@ -15,14 +15,19 @@
 
 use core::prelude::*;
 
-use core::cmp;
 use core::default::Default;
 use core::fmt;
 use core::iter;
-use core::slice;
+use core::raw::Slice as RawSlice;
+use core::ptr;
+use core::kinds::marker;
+use core::mem;
+use core::num::{Int, UnsignedInt};
+
 use std::hash::{Writer, Hash};
+use std::cmp;
 
-use vec::Vec;
+use alloc::heap;
 
 static INITIAL_CAPACITY: uint = 8u; // 2^3
 static MINIMUM_CAPACITY: uint = 2u;
@@ -33,11 +38,37 @@ static MINIMUM_CAPACITY: uint = 2u;
 
 
 /// `RingBuf` is a circular buffer that implements `Deque`.
-#[deriving(Clone)]
 pub struct RingBuf<T> {
-    nelts: uint,
-    lo: uint,
-    elts: Vec<Option<T>>
+    // tail and head are pointers into the buffer. Tail always points
+    // to the first element that could be read, Head always points
+    // to where data should be written.
+    // If tail == head the buffer is empty. The length of the ringbuf
+    // is defined as the distance between the two.
+
+    tail: uint,
+    head: uint,
+    cap: uint,
+    ptr: *mut T
+}
+
+impl<T: Clone> Clone for RingBuf<T> {
+    fn clone(&self) -> RingBuf<T> {
+        self.iter().map(|t| t.clone()).collect()
+    }
+}
+
+#[unsafe_destructor]
+impl<T> Drop for RingBuf<T> {
+    fn drop(&mut self) {
+        self.clear();
+        unsafe {
+            if mem::size_of::<T>() != 0 {
+                heap::deallocate(self.ptr as *mut u8,
+                                 self.cap * mem::size_of::<T>(),
+                                 mem::min_align_of::<T>())
+            }
+        }
+    }
 }
 
 impl<T> Default for RingBuf<T> {
@@ -46,6 +77,34 @@ impl<T> Default for RingBuf<T> {
 }
 
 impl<T> RingBuf<T> {
+    /// Turn ptr into a slice
+    #[inline]
+    unsafe fn buffer_as_slice(&self) -> &[T] {
+        mem::transmute(RawSlice { data: self.ptr as *const T, len: self.cap })
+    }
+
+    /// Moves an element out of the buffer
+    #[inline]
+    unsafe fn buffer_read(&mut self, off: uint) -> T {
+        ptr::read(self.ptr.offset(off as int) as *const T)
+    }
+
+    /// Writes an element into the buffer, moving it.
+    #[inline]
+    unsafe fn buffer_write(&mut self, off: uint, t: T) {
+        ptr::write(self.ptr.offset(off as int), t);
+    }
+
+    /// Returns true iff the buffer is at capacity
+    #[inline]
+    fn is_full(&self) -> bool { self.cap - self.len() == 1 }
+
+    /// Returns the index in the underlying buffer for a given logical element index.
+    #[inline]
+    fn wrap_index(&self, idx: uint) -> uint { wrap_index(idx, self.cap) }
+}
+
+impl<T> RingBuf<T> {
     /// Creates an empty `RingBuf`.
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn new() -> RingBuf<T> {
@@ -55,8 +114,27 @@ impl<T> RingBuf<T> {
     /// Creates an empty `RingBuf` with space for at least `n` elements.
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn with_capacity(n: uint) -> RingBuf<T> {
-        RingBuf{nelts: 0, lo: 0,
-              elts: Vec::from_fn(cmp::max(MINIMUM_CAPACITY, n), |_| None)}
+        // +1 since the ringbuffer always leaves one space empty
+        let cap = cmp::max(n + 1, MINIMUM_CAPACITY).next_power_of_two();
+        let size = cap.checked_mul(mem::size_of::<T>())
+                      .expect("capacity overflow");
+
+        let ptr = if mem::size_of::<T>() != 0 {
+            unsafe {
+                let ptr = heap::allocate(size, mem::min_align_of::<T>())  as *mut T;;
+                if ptr.is_null() { ::alloc::oom() }
+                ptr
+            }
+        } else {
+            heap::EMPTY as *mut T
+        };
+
+        RingBuf {
+            tail: 0,
+            head: 0,
+            cap: cap,
+            ptr: ptr
+        }
     }
 
     /// Retrieves an element in the `RingBuf` by index.
@@ -74,9 +152,11 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn get(&self, i: uint) -> Option<&T> {
-        match self.elts.get(i) {
-            None => None,
-            Some(opt) => opt.as_ref(),
+        if i < self.len() {
+            let idx = self.wrap_index(self.tail + i);
+            unsafe { Some(&*self.ptr.offset(idx as int)) }
+        } else {
+            None
         }
     }
 
@@ -102,9 +182,11 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn get_mut(&mut self, i: uint) -> Option<&mut T> {
-        match self.elts.get_mut(i) {
-            None => None,
-            Some(opt) => opt.as_mut(),
+        if i < self.len() {
+            let idx = self.wrap_index(self.tail + i);
+            unsafe { Some(&mut *self.ptr.offset(idx as int)) }
+        } else {
+            None
         }
     }
 
@@ -130,15 +212,11 @@ impl<T> RingBuf<T> {
     pub fn swap(&mut self, i: uint, j: uint) {
         assert!(i < self.len());
         assert!(j < self.len());
-        let ri = self.raw_index(i);
-        let rj = self.raw_index(j);
-        self.elts.as_mut_slice().swap(ri, rj);
-    }
-
-    /// Returns the index in the underlying `Vec` for a given logical element
-    /// index.
-    fn raw_index(&self, idx: uint) -> uint {
-        raw_index(self.lo, self.elts.len(), idx)
+        let ri = self.wrap_index(self.tail + i);
+        let rj = self.wrap_index(self.tail + j);
+        unsafe {
+            ptr::swap(self.ptr.offset(ri as int), self.ptr.offset(rj as int))
+        }
     }
 
     /// Returns the number of elements the `RingBuf` can hold without
@@ -150,14 +228,11 @@ impl<T> RingBuf<T> {
     /// use std::collections::RingBuf;
     ///
     /// let buf: RingBuf<int> = RingBuf::with_capacity(10);
-    /// assert_eq!(buf.capacity(), 10);
+    /// assert!(buf.capacity() >= 10);
     /// ```
     #[inline]
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn capacity(&self) -> uint {
-        // FXIME(Gankro): not the actual usable capacity if you use reserve/reserve_exact
-        self.elts.capacity()
-    }
+    pub fn capacity(&self) -> uint { self.cap - 1 }
 
     /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
     /// given `RingBuf`. Does nothing if the capacity is already sufficient.
@@ -181,8 +256,7 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn reserve_exact(&mut self, additional: uint) {
-        // FIXME(Gankro): this is just wrong. The ringbuf won't actually use this space
-        self.elts.reserve_exact(additional);
+        self.reserve(additional);
     }
 
     /// Reserves capacity for at least `additional` more elements to be inserted in the given
@@ -203,8 +277,69 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn reserve(&mut self, additional: uint) {
-        // FIXME(Gankro): this is just wrong. The ringbuf won't actually use this space
-        self.elts.reserve(additional);
+        let new_len = self.len() + additional;
+        assert!(new_len + 1 > self.len(), "capacity overflow");
+        if new_len > self.capacity() {
+            let count = (new_len + 1).next_power_of_two();
+            assert!(count >= new_len + 1);
+
+            if mem::size_of::<T>() != 0 {
+                let old = self.cap * mem::size_of::<T>();
+                let new = count.checked_mul(mem::size_of::<T>())
+                               .expect("capacity overflow");
+                unsafe {
+                    self.ptr = heap::reallocate(self.ptr as *mut u8,
+                                                old,
+                                                new,
+                                                mem::min_align_of::<T>()) as *mut T;
+                    if self.ptr.is_null() { ::alloc::oom() }
+                }
+            }
+
+            // Move the shortest contiguous section of the ring buffer
+            //    T             H
+            //   [o o o o o o o . ]
+            //    T             H
+            // A [o o o o o o o . . . . . . . . . ]
+            //        H T
+            //   [o o . o o o o o ]
+            //          T             H
+            // B [. . . o o o o o o o . . . . . . ]
+            //              H T
+            //   [o o o o o . o o ]
+            //              H                 T
+            // C [o o o o o . . . . . . . . . o o ]
+
+            let oldcap = self.cap;
+            self.cap = count;
+
+            if self.tail <= self.head { // A
+                // Nop
+            } else if self.head < oldcap - self.tail { // B
+                unsafe {
+                    ptr::copy_nonoverlapping_memory(
+                        self.ptr.offset(oldcap as int),
+                        self.ptr as *const T,
+                        self.head
+                    );
+                }
+                self.head += oldcap;
+                debug_assert!(self.head > self.tail);
+            } else { // C
+                unsafe {
+                    ptr::copy_nonoverlapping_memory(
+                        self.ptr.offset((count - (oldcap - self.tail)) as int),
+                        self.ptr.offset(self.tail as int) as *const T,
+                        oldcap - self.tail
+                    );
+                }
+                self.tail = count - (oldcap - self.tail);
+                debug_assert!(self.head < self.tail);
+            }
+            debug_assert!(self.head < self.cap);
+            debug_assert!(self.tail < self.cap);
+            debug_assert!(self.cap.count_ones() == 1);
+        }
     }
 
     /// Returns a front-to-back iterator.
@@ -223,7 +358,11 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn iter(&self) -> Items<T> {
-        Items{index: 0, rindex: self.nelts, lo: self.lo, elts: self.elts.as_slice()}
+        Items {
+            tail: self.tail,
+            head: self.head,
+            ring: unsafe { self.buffer_as_slice() }
+        }
     }
 
     /// Returns a front-to-back iterator which returns mutable references.
@@ -244,32 +383,14 @@ impl<T> RingBuf<T> {
     /// assert_eq!(buf.iter_mut().collect::<Vec<&mut int>>()[], b);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter_mut(&mut self) -> MutItems<T> {
-        let start_index = raw_index(self.lo, self.elts.len(), 0);
-        let end_index = raw_index(self.lo, self.elts.len(), self.nelts);
-
-        // Divide up the array
-        if end_index <= start_index {
-            // Items to iterate goes from:
-            //    start_index to self.elts.len()
-            // and then
-            //    0 to end_index
-            let (temp, remaining1) = self.elts.split_at_mut(start_index);
-            let (remaining2, _) = temp.split_at_mut(end_index);
-            MutItems {
-                remaining1: remaining1.iter_mut(),
-                remaining2: remaining2.iter_mut(),
-                nelts: self.nelts,
-            }
-        } else {
-            // Items to iterate goes from start_index to end_index:
-            let (empty, elts) = self.elts.split_at_mut(0);
-            let remaining1 = elts[mut start_index..end_index];
-            MutItems {
-                remaining1: remaining1.iter_mut(),
-                remaining2: empty.iter_mut(),
-                nelts: self.nelts,
-            }
+    pub fn iter_mut<'a>(&'a mut self) -> MutItems<'a, T> {
+        MutItems {
+            tail: self.tail,
+            head: self.head,
+            cap: self.cap,
+            ptr: self.ptr,
+            marker: marker::ContravariantLifetime::<'a>,
+            marker2: marker::NoCopy
         }
     }
 
@@ -286,7 +407,7 @@ impl<T> RingBuf<T> {
     /// assert_eq!(v.len(), 1);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn len(&self) -> uint { self.nelts }
+    pub fn len(&self) -> uint { count(self.tail, self.head, self.cap) }
 
     /// Returns true if the buffer contains no elements
     ///
@@ -317,9 +438,9 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn clear(&mut self) {
-        for x in self.elts.iter_mut() { *x = None }
-        self.nelts = 0;
-        self.lo = 0;
+        while self.pop_front().is_some() {}
+        self.head = 0;
+        self.tail = 0;
     }
 
     /// Provides a reference to the front element, or `None` if the sequence is
@@ -339,7 +460,7 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn front(&self) -> Option<&T> {
-        if self.nelts > 0 { Some(&self[0]) } else { None }
+        if !self.is_empty() { Some(&self[0]) } else { None }
     }
 
     /// Provides a mutable reference to the front element, or `None` if the
@@ -363,7 +484,7 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn front_mut(&mut self) -> Option<&mut T> {
-        if self.nelts > 0 { Some(&mut self[0]) } else { None }
+        if !self.is_empty() { Some(&mut self[0]) } else { None }
     }
 
     /// Provides a reference to the back element, or `None` if the sequence is
@@ -383,7 +504,7 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn back(&self) -> Option<&T> {
-        if self.nelts > 0 { Some(&self[self.nelts - 1]) } else { None }
+        if !self.is_empty() { Some(&self[self.len() - 1]) } else { None }
     }
 
     /// Provides a mutable reference to the back element, or `None` if the
@@ -407,8 +528,8 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn back_mut(&mut self) -> Option<&mut T> {
-        let nelts = self.nelts;
-        if nelts > 0 { Some(&mut self[nelts - 1]) } else { None }
+        let len = self.len();
+        if !self.is_empty() { Some(&mut self[len - 1]) } else { None }
     }
 
     /// Removes the first element and returns it, or `None` if the sequence is
@@ -429,12 +550,13 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn pop_front(&mut self) -> Option<T> {
-        let result = self.elts[self.lo].take();
-        if result.is_some() {
-            self.lo = (self.lo + 1u) % self.elts.len();
-            self.nelts -= 1u;
+        if self.is_empty() {
+            None
+        } else {
+            let tail = self.tail;
+            self.tail = self.wrap_index(self.tail + 1);
+            unsafe { Some(self.buffer_read(tail)) }
         }
-        result
     }
 
     /// Inserts an element first in the sequence.
@@ -451,14 +573,14 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn push_front(&mut self, t: T) {
-        if self.nelts == self.elts.len() {
-            grow(self.nelts, &mut self.lo, &mut self.elts);
+        if self.is_full() {
+            self.reserve(1);
+            debug_assert!(!self.is_full());
         }
-        if self.lo == 0u {
-            self.lo = self.elts.len() - 1u;
-        } else { self.lo -= 1u; }
-        self.elts[self.lo] = Some(t);
-        self.nelts += 1u;
+
+        self.tail = self.wrap_index(self.tail - 1);
+        let tail = self.tail;
+        unsafe { self.buffer_write(tail, t); }
     }
 
     /// Deprecated: Renamed to `push_back`.
@@ -481,12 +603,14 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn push_back(&mut self, t: T) {
-        if self.nelts == self.elts.len() {
-            grow(self.nelts, &mut self.lo, &mut self.elts);
+        if self.is_full() {
+            self.reserve(1);
+            debug_assert!(!self.is_full());
         }
-        let hi = self.raw_index(self.nelts);
-        self.elts[hi] = Some(t);
-        self.nelts += 1u;
+
+        let head = self.head;
+        self.head = self.wrap_index(self.head + 1);
+        unsafe { self.buffer_write(head, t) }
     }
 
     /// Deprecated: Renamed to `pop_back`.
@@ -511,38 +635,51 @@ impl<T> RingBuf<T> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn pop_back(&mut self) -> Option<T> {
-        if self.nelts > 0 {
-            self.nelts -= 1;
-            let hi = self.raw_index(self.nelts);
-            self.elts[hi].take()
-        } else {
+        if self.is_empty() {
             None
+        } else {
+            self.head = self.wrap_index(self.head - 1);
+            let head = self.head;
+            unsafe { Some(self.buffer_read(head)) }
         }
     }
 }
 
+/// Returns the index in the underlying buffer for a given logical element index.
+#[inline]
+fn wrap_index(index: uint, size: uint) -> uint {
+    // size is always a power of 2
+    index & (size - 1)
+}
+
+/// Calculate the number of elements left to be read in the buffer
+#[inline]
+fn count(tail: uint, head: uint, size: uint) -> uint {
+    // size is always a power of 2
+    (head - tail) & (size - 1)
+}
+
 /// `RingBuf` iterator.
 pub struct Items<'a, T:'a> {
-    lo: uint,
-    index: uint,
-    rindex: uint,
-    elts: &'a [Option<T>],
+    ring: &'a [T],
+    tail: uint,
+    head: uint
 }
 
 impl<'a, T> Iterator<&'a T> for Items<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a T> {
-        if self.index == self.rindex {
+        if self.tail == self.head {
             return None;
         }
-        let raw_index = raw_index(self.lo, self.elts.len(), self.index);
-        self.index += 1;
-        Some(self.elts[raw_index].as_ref().unwrap())
+        let tail = self.tail;
+        self.tail = wrap_index(self.tail + 1, self.ring.len());
+        unsafe { Some(self.ring.unsafe_get(tail)) }
     }
 
     #[inline]
     fn size_hint(&self) -> (uint, Option<uint>) {
-        let len = self.rindex - self.index;
+        let len = count(self.tail, self.head, self.ring.len());
         (len, Some(len))
     }
 }
@@ -550,129 +687,87 @@ impl<'a, T> Iterator<&'a T> for Items<'a, T> {
 impl<'a, T> DoubleEndedIterator<&'a T> for Items<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a T> {
-        if self.index == self.rindex {
+        if self.tail == self.head {
             return None;
         }
-        self.rindex -= 1;
-        let raw_index = raw_index(self.lo, self.elts.len(), self.rindex);
-        Some(self.elts[raw_index].as_ref().unwrap())
+        self.head = wrap_index(self.head - 1, self.ring.len());
+        unsafe { Some(self.ring.unsafe_get(self.head)) }
     }
 }
 
+
 impl<'a, T> ExactSize<&'a T> for Items<'a, T> {}
 
 impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
     #[inline]
-    fn indexable(&self) -> uint { self.rindex - self.index }
+    fn indexable(&self) -> uint {
+        let (len, _) = self.size_hint();
+        len
+    }
 
     #[inline]
     fn idx(&mut self, j: uint) -> Option<&'a T> {
         if j >= self.indexable() {
             None
         } else {
-            let raw_index = raw_index(self.lo, self.elts.len(), self.index + j);
-            Some(self.elts[raw_index].as_ref().unwrap())
+            let idx = wrap_index(self.tail + j, self.ring.len());
+            unsafe { Some(self.ring.unsafe_get(idx)) }
         }
     }
 }
 
+// FIXME This was implemented differently from Items because of a problem
+//       with returning the mutable reference. I couldn't find a way to
+//       make the lifetime checker happy so, but there should be a way.
 /// `RingBuf` mutable iterator.
 pub struct MutItems<'a, T:'a> {
-    remaining1: slice::MutItems<'a, Option<T>>,
-    remaining2: slice::MutItems<'a, Option<T>>,
-    nelts: uint,
+    ptr: *mut T,
+    tail: uint,
+    head: uint,
+    cap: uint,
+    marker: marker::ContravariantLifetime<'a>,
+    marker2: marker::NoCopy
 }
 
 impl<'a, T> Iterator<&'a mut T> for MutItems<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a mut T> {
-        if self.nelts == 0 {
+        if self.tail == self.head {
             return None;
         }
-        self.nelts -= 1;
-        match self.remaining1.next() {
-            Some(ptr) => return Some(ptr.as_mut().unwrap()),
-            None => {}
-        }
-        match self.remaining2.next() {
-            Some(ptr) => return Some(ptr.as_mut().unwrap()),
-            None => unreachable!(),
+        let tail = self.tail;
+        self.tail = wrap_index(self.tail + 1, self.cap);
+        if mem::size_of::<T>() != 0 {
+            unsafe { Some(&mut *self.ptr.offset(tail as int)) }
+        } else {
+            // use a non-zero pointer
+            Some(unsafe { mem::transmute(1u) })
         }
     }
 
     #[inline]
     fn size_hint(&self) -> (uint, Option<uint>) {
-        (self.nelts, Some(self.nelts))
+        let len = count(self.tail, self.head, self.cap);
+        (len, Some(len))
     }
 }
 
 impl<'a, T> DoubleEndedIterator<&'a mut T> for MutItems<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut T> {
-        if self.nelts == 0 {
+        if self.tail == self.head {
             return None;
         }
-        self.nelts -= 1;
-        match self.remaining2.next_back() {
-            Some(ptr) => return Some(ptr.as_mut().unwrap()),
-            None => {}
-        }
-        match self.remaining1.next_back() {
-            Some(ptr) => return Some(ptr.as_mut().unwrap()),
-            None => unreachable!(),
-        }
+        self.head = wrap_index(self.head - 1, self.cap);
+        unsafe { Some(&mut *self.ptr.offset(self.head as int)) }
     }
 }
 
 impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {}
 
-/// Grow is only called on full elts, so nelts is also len(elts), unlike
-/// elsewhere.
-fn grow<T>(nelts: uint, loptr: &mut uint, elts: &mut Vec<Option<T>>) {
-    assert_eq!(nelts, elts.len());
-    let lo = *loptr;
-    elts.reserve_exact(nelts);
-    let newlen = elts.capacity();
-
-    /* fill with None */
-    for _ in range(elts.len(), newlen) {
-        elts.push(None);
-    }
-
-    /*
-      Move the shortest half into the newly reserved area.
-      lo ---->|
-      nelts ----------->|
-        [o o o|o o o o o]
-      A [. . .|o o o o o o o o|. . . . .]
-      B [o o o|. . . . . . . .|o o o o o]
-     */
-
-    assert!(newlen - nelts/2 >= nelts);
-    if lo <= (nelts - lo) { // A
-        for i in range(0u, lo) {
-            elts.as_mut_slice().swap(i, nelts + i);
-        }
-    } else {                // B
-        for i in range(lo, nelts) {
-            elts.as_mut_slice().swap(i, newlen - nelts + i);
-        }
-        *loptr += newlen - nelts;
-    }
-}
-
-/// Returns the index in the underlying `Vec` for a given logical element index.
-fn raw_index(lo: uint, len: uint, index: uint) -> uint {
-    if lo >= len - index {
-        lo + index - len
-    } else {
-        lo + index
-    }
-}
-
 impl<A: PartialEq> PartialEq for RingBuf<A> {
     fn eq(&self, other: &RingBuf<A>) -> bool {
-        self.nelts == other.nelts &&
+        self.len() == other.len() &&
             self.iter().zip(other.iter()).all(|(a, b)| a.eq(b))
     }
     fn ne(&self, other: &RingBuf<A>) -> bool {
@@ -707,22 +802,14 @@ impl<S: Writer, A: Hash<S>> Hash<S> for RingBuf<A> {
 impl<A> Index<uint, A> for RingBuf<A> {
     #[inline]
     fn index<'a>(&'a self, i: &uint) -> &'a A {
-        let idx = self.raw_index(*i);
-        match self.elts[idx] {
-            None => panic!(),
-            Some(ref v) => v,
-        }
+        self.get(*i).expect("Out of bounds access")
     }
 }
 
 impl<A> IndexMut<uint, A> for RingBuf<A> {
     #[inline]
     fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut A {
-        let idx = self.raw_index(*i);
-        match *(&mut self.elts[idx]) {
-            None => panic!(),
-            Some(ref mut v) => v
-        }
+        self.get_mut(*i).expect("Out of bounds access")
     }
 }
 
@@ -888,36 +975,99 @@ mod tests {
     #[bench]
     fn bench_new(b: &mut test::Bencher) {
         b.iter(|| {
-            let _: RingBuf<u64> = RingBuf::new();
+            let ring: RingBuf<u64> = RingBuf::new();
+            test::black_box(ring);
         })
     }
 
     #[bench]
-    fn bench_push_back(b: &mut test::Bencher) {
-        let mut deq = RingBuf::new();
+    fn bench_push_back_100(b: &mut test::Bencher) {
+        let mut deq = RingBuf::with_capacity(101);
         b.iter(|| {
-            deq.push_back(0i);
+            for i in range(0i, 100) {
+                deq.push_back(i);
+            }
+            deq.head = 0;
+            deq.tail = 0;
         })
     }
 
     #[bench]
-    fn bench_push_front(b: &mut test::Bencher) {
-        let mut deq = RingBuf::new();
+    fn bench_push_front_100(b: &mut test::Bencher) {
+        let mut deq = RingBuf::with_capacity(101);
         b.iter(|| {
-            deq.push_front(0i);
+            for i in range(0i, 100) {
+                deq.push_front(i);
+            }
+            deq.head = 0;
+            deq.tail = 0;
         })
     }
 
     #[bench]
-    fn bench_grow(b: &mut test::Bencher) {
-        let mut deq = RingBuf::new();
+    fn bench_pop_back_100(b: &mut test::Bencher) {
+        let mut deq: RingBuf<int> = RingBuf::with_capacity(101);
+
+        b.iter(|| {
+            deq.head = 100;
+            deq.tail = 0;
+            while !deq.is_empty() {
+                test::black_box(deq.pop_back());
+            }
+        })
+    }
+
+    #[bench]
+    fn bench_pop_front_100(b: &mut test::Bencher) {
+        let mut deq: RingBuf<int> = RingBuf::with_capacity(101);
+
+        b.iter(|| {
+            deq.head = 100;
+            deq.tail = 0;
+            while !deq.is_empty() {
+                test::black_box(deq.pop_front());
+            }
+        })
+    }
+
+    #[bench]
+    fn bench_grow_1025(b: &mut test::Bencher) {
+        b.iter(|| {
+            let mut deq = RingBuf::new();
+            for i in range(0i, 1025) {
+                deq.push_front(i);
+            }
+            test::black_box(deq);
+        })
+    }
+
+    #[bench]
+    fn bench_iter_1000(b: &mut test::Bencher) {
+        let ring: RingBuf<int> = range(0i, 1000).collect();
+
         b.iter(|| {
-            for _ in range(0i, 65) {
-                deq.push_front(1i);
+            let mut sum = 0;
+            for &i in ring.iter() {
+                sum += i;
             }
+            test::black_box(sum);
         })
     }
 
+    #[bench]
+    fn bench_mut_iter_1000(b: &mut test::Bencher) {
+        let mut ring: RingBuf<int> = range(0i, 1000).collect();
+
+        b.iter(|| {
+            let mut sum = 0;
+            for i in ring.iter_mut() {
+                sum += *i;
+            }
+            test::black_box(sum);
+        })
+    }
+
+
     #[deriving(Clone, PartialEq, Show)]
     enum Taggy {
         One(int),
@@ -1034,11 +1184,11 @@ mod tests {
         let mut d = RingBuf::new();
         d.push_back(0u64);
         d.reserve(50);
-        assert!(d.capacity() >= 64);
+        assert!(d.capacity() >= 51);
         let mut d = RingBuf::new();
         d.push_back(0u32);
         d.reserve(50);
-        assert!(d.capacity() >= 64);
+        assert!(d.capacity() >= 51);
     }
 
     #[test]
@@ -1257,4 +1407,169 @@ mod tests {
                                                                         .collect();
         assert!(format!("{}", ringbuf).as_slice() == "[just, one, test, more]");
     }
+
+    #[test]
+    fn test_drop() {
+        static mut drops: uint = 0;
+        struct Elem;
+        impl Drop for Elem {
+            fn drop(&mut self) {
+                unsafe { drops += 1; }
+            }
+        }
+
+        let mut ring = RingBuf::new();
+        ring.push_back(Elem);
+        ring.push_front(Elem);
+        ring.push_back(Elem);
+        ring.push_front(Elem);
+        drop(ring);
+
+        assert_eq!(unsafe {drops}, 4);
+    }
+
+    #[test]
+    fn test_drop_with_pop() {
+        static mut drops: uint = 0;
+        struct Elem;
+        impl Drop for Elem {
+            fn drop(&mut self) {
+                unsafe { drops += 1; }
+            }
+        }
+
+        let mut ring = RingBuf::new();
+        ring.push_back(Elem);
+        ring.push_front(Elem);
+        ring.push_back(Elem);
+        ring.push_front(Elem);
+
+        drop(ring.pop_back());
+        drop(ring.pop_front());
+        assert_eq!(unsafe {drops}, 2);
+
+        drop(ring);
+        assert_eq!(unsafe {drops}, 4);
+    }
+
+    #[test]
+    fn test_drop_clear() {
+        static mut drops: uint = 0;
+        struct Elem;
+        impl Drop for Elem {
+            fn drop(&mut self) {
+                unsafe { drops += 1; }
+            }
+        }
+
+        let mut ring = RingBuf::new();
+        ring.push_back(Elem);
+        ring.push_front(Elem);
+        ring.push_back(Elem);
+        ring.push_front(Elem);
+        ring.clear();
+        assert_eq!(unsafe {drops}, 4);
+
+        drop(ring);
+        assert_eq!(unsafe {drops}, 4);
+    }
+
+    #[test]
+    fn test_reserve_grow() {
+        // test growth path A
+        // [T o o H] -> [T o o H . . . . ]
+        let mut ring = RingBuf::with_capacity(4);
+        for i in range(0i, 3) {
+            ring.push_back(i);
+        }
+        ring.reserve(7);
+        for i in range(0i, 3) {
+            assert_eq!(ring.pop_front(), Some(i));
+        }
+
+        // test growth path B
+        // [H T o o] -> [. T o o H . . . ]
+        let mut ring = RingBuf::with_capacity(4);
+        for i in range(0i, 1) {
+            ring.push_back(i);
+            assert_eq!(ring.pop_front(), Some(i));
+        }
+        for i in range(0i, 3) {
+            ring.push_back(i);
+        }
+        ring.reserve(7);
+        for i in range(0i, 3) {
+            assert_eq!(ring.pop_front(), Some(i));
+        }
+
+        // test growth path C
+        // [o o H T] -> [o o H . . . . T ]
+        let mut ring = RingBuf::with_capacity(4);
+        for i in range(0i, 3) {
+            ring.push_back(i);
+            assert_eq!(ring.pop_front(), Some(i));
+        }
+        for i in range(0i, 3) {
+            ring.push_back(i);
+        }
+        ring.reserve(7);
+        for i in range(0i, 3) {
+            assert_eq!(ring.pop_front(), Some(i));
+        }
+    }
+
+    #[test]
+    fn test_get() {
+        let mut ring = RingBuf::new();
+        ring.push_back(0i);
+        assert_eq!(ring.get(0), Some(&0));
+        assert_eq!(ring.get(1), None);
+
+        ring.push_back(1);
+        assert_eq!(ring.get(0), Some(&0));
+        assert_eq!(ring.get(1), Some(&1));
+        assert_eq!(ring.get(2), None);
+
+        ring.push_back(2);
+        assert_eq!(ring.get(0), Some(&0));
+        assert_eq!(ring.get(1), Some(&1));
+        assert_eq!(ring.get(2), Some(&2));
+        assert_eq!(ring.get(3), None);
+
+        assert_eq!(ring.pop_front(), Some(0));
+        assert_eq!(ring.get(0), Some(&1));
+        assert_eq!(ring.get(1), Some(&2));
+        assert_eq!(ring.get(2), None);
+
+        assert_eq!(ring.pop_front(), Some(1));
+        assert_eq!(ring.get(0), Some(&2));
+        assert_eq!(ring.get(1), None);
+
+        assert_eq!(ring.pop_front(), Some(2));
+        assert_eq!(ring.get(0), None);
+        assert_eq!(ring.get(1), None);
+    }
+
+    #[test]
+    fn test_get_mut() {
+        let mut ring = RingBuf::new();
+        for i in range(0i, 3) {
+            ring.push_back(i);
+        }
+
+        match ring.get_mut(1) {
+            Some(x) => *x = -1,
+            None => ()
+        };
+
+        assert_eq!(ring.get_mut(0), Some(&mut 0));
+        assert_eq!(ring.get_mut(1), Some(&mut -1));
+        assert_eq!(ring.get_mut(2), Some(&mut 2));
+        assert_eq!(ring.get_mut(3), None);
+
+        assert_eq!(ring.pop_front(), Some(0));
+        assert_eq!(ring.get_mut(0), Some(&mut -1));
+        assert_eq!(ring.get_mut(1), Some(&mut 2));
+        assert_eq!(ring.get_mut(2), None);
+    }
 }
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 5ae1060dd29..f05a681a526 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -236,7 +236,10 @@ impl<T> Option<T> {
     #[inline]
     #[stable]
     pub fn as_ref<'r>(&'r self) -> Option<&'r T> {
-        match *self { Some(ref x) => Some(x), None => None }
+        match *self {
+            Some(ref x) => Some(x),
+            None => None
+        }
     }
 
     /// Convert from `Option<T>` to `Option<&mut T>`
@@ -254,7 +257,10 @@ impl<T> Option<T> {
     #[inline]
     #[unstable = "waiting for mut conventions"]
     pub fn as_mut<'r>(&'r mut self) -> Option<&'r mut T> {
-        match *self { Some(ref mut x) => Some(x), None => None }
+        match *self {
+            Some(ref mut x) => Some(x),
+            None => None
+        }
     }
 
     /// Convert from `Option<T>` to `&mut [T]` (without copying)
@@ -402,7 +408,10 @@ impl<T> Option<T> {
     #[inline]
     #[unstable = "waiting for unboxed closures"]
     pub fn map<U>(self, f: |T| -> U) -> Option<U> {
-        match self { Some(x) => Some(f(x)), None => None }
+        match self {
+            Some(x) => Some(f(x)),
+            None => None
+        }
     }
 
     /// Applies a function to the contained value or returns a default.
@@ -419,7 +428,10 @@ impl<T> Option<T> {
     #[inline]
     #[unstable = "waiting for unboxed closures"]
     pub fn map_or<U>(self, def: U, f: |T| -> U) -> U {
-        match self { None => def, Some(t) => f(t) }
+        match self {
+            Some(t) => f(t),
+            None => def
+        }
     }
 
     /// Applies a function to the contained value or computes a default.
@@ -438,7 +450,10 @@ impl<T> Option<T> {
     #[inline]
     #[unstable = "waiting for unboxed closures"]
     pub fn map_or_else<U>(self, def: || -> U, f: |T| -> U) -> U {
-        match self { None => def(), Some(t) => f(t) }
+        match self {
+            Some(t) => f(t),
+            None => def()
+        }
     }
 
     /// Transforms the `Option<T>` into a `Result<T, E>`, mapping `Some(v)` to
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index d5e9c1ef99f..1792599783b 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -66,7 +66,6 @@ register_diagnostics!(
     E0055,
     E0056,
     E0057,
-    E0058,
     E0059,
     E0060,
     E0061,
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index c2bb702d5c0..ac2f6dd9d37 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -447,7 +447,9 @@ impl LintPass for ImproperCTypes {
             for input in decl.inputs.iter() {
                 check_ty(cx, &*input.ty);
             }
-            check_ty(cx, &*decl.output)
+            if let ast::Return(ref ret_ty) = decl.output {
+                check_ty(cx, &**ret_ty);
+            }
         }
 
         match it.node {
@@ -735,7 +737,8 @@ impl LintPass for UnusedResults {
         let t = ty::expr_ty(cx.tcx, expr);
         let mut warned = false;
         match ty::get(t).sty {
-            ty::ty_nil | ty::ty_bool => return,
+            ty::ty_tup(ref tys) if tys.is_empty() => return,
+            ty::ty_bool => return,
             ty::ty_struct(did, _) |
             ty::ty_enum(did, _) => {
                 if ast_util::is_local(did) {
@@ -1399,6 +1402,9 @@ pub struct MissingDoc {
     /// Stack of IDs of struct definitions.
     struct_def_stack: Vec<ast::NodeId>,
 
+    /// True if inside variant definition
+    in_variant: bool,
+
     /// Stack of whether #[doc(hidden)] is set
     /// at each level which has lint attributes.
     doc_hidden_stack: Vec<bool>,
@@ -1408,6 +1414,7 @@ impl MissingDoc {
     pub fn new() -> MissingDoc {
         MissingDoc {
             struct_def_stack: vec!(),
+            in_variant: false,
             doc_hidden_stack: vec!(false),
         }
     }
@@ -1522,7 +1529,7 @@ impl LintPass for MissingDoc {
 
     fn check_struct_field(&mut self, cx: &Context, sf: &ast::StructField) {
         match sf.node.kind {
-            ast::NamedField(_, vis) if vis == ast::Public => {
+            ast::NamedField(_, vis) if vis == ast::Public || self.in_variant => {
                 let cur_struct_def = *self.struct_def_stack.last()
                     .expect("empty struct_def_stack");
                 self.check_missing_docs_attrs(cx, Some(cur_struct_def),
@@ -1536,6 +1543,13 @@ impl LintPass for MissingDoc {
     fn check_variant(&mut self, cx: &Context, v: &ast::Variant, _: &ast::Generics) {
         self.check_missing_docs_attrs(cx, Some(v.node.id), v.node.attrs.as_slice(),
                                      v.span, "a variant");
+        assert!(!self.in_variant);
+        self.in_variant = true;
+    }
+
+    fn check_variant_post(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generics) {
+        assert!(self.in_variant);
+        self.in_variant = false;
     }
 }
 
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 7f8b779dac1..917f05365ec 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -665,6 +665,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
         self.with_lint_attrs(v.node.attrs.as_slice(), |cx| {
             run_lints!(cx, check_variant, v, g);
             visit::walk_variant(cx, v, g);
+            run_lints!(cx, check_variant_post, v, g);
         })
     }
 
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 0202aa18558..3ea4c9c720c 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -149,6 +149,7 @@ pub trait LintPass {
         _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { }
     fn check_struct_field(&mut self, _: &Context, _: &ast::StructField) { }
     fn check_variant(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generics) { }
+    fn check_variant_post(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generics) { }
     fn check_opt_lifetime_ref(&mut self, _: &Context, _: Span, _: &Option<ast::Lifetime>) { }
     fn check_lifetime_ref(&mut self, _: &Context, _: &ast::Lifetime) { }
     fn check_lifetime_decl(&mut self, _: &Context, _: &ast::LifetimeDef) { }
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 364cc298e8c..d660cc970e7 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -360,7 +360,6 @@ fn parse_trait_ref(st: &mut PState, conv: conv_did) -> ty::TraitRef {
 
 fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
     match next(st) {
-      'n' => return ty::mk_nil(),
       'b' => return ty::mk_bool(),
       'i' => return ty::mk_int(),
       'u' => return ty::mk_uint(),
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 56e44b69a5f..3242d396146 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -199,7 +199,6 @@ pub fn enc_trait_store(w: &mut SeekableMemWriter, cx: &ctxt, s: ty::TraitStore)
 
 fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) {
     match *st {
-        ty::ty_nil => mywrite!(w, "n"),
         ty::ty_bool => mywrite!(w, "b"),
         ty::ty_char => mywrite!(w, "c"),
         ty::ty_int(t) => {
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 74a438190fa..9e1e4552ee2 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::const_eval::{compare_const_vals, const_bool, const_float, const_nil, const_val};
+use middle::const_eval::{compare_const_vals, const_bool, const_float, const_val};
 use middle::const_eval::{const_expr_to_pat, eval_const_expr, lookup_const_by_id};
 use middle::def::*;
 use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Init};
@@ -332,7 +332,6 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix) {
 fn const_val_to_expr(value: &const_val) -> P<Expr> {
     let node = match value {
         &const_bool(b) => LitBool(b),
-        &const_nil => LitNil,
         _ => unreachable!()
     };
     P(Expr {
@@ -497,9 +496,6 @@ fn all_constructors(cx: &MatchCheckCtxt, left_ty: ty::t,
         ty::ty_bool =>
             [true, false].iter().map(|b| ConstantValue(const_bool(*b))).collect(),
 
-        ty::ty_nil =>
-            vec!(ConstantValue(const_nil)),
-
         ty::ty_rptr(_, ty::mt { ty, .. }) => match ty::get(ty).sty {
             ty::ty_vec(_, None) =>
                 range_inclusive(0, max_slice_length).map(|length| Slice(length)).collect(),
@@ -552,7 +548,7 @@ fn is_useful(cx: &MatchCheckCtxt,
         None => v[0]
     };
     let left_ty = if real_pat.id == DUMMY_NODE_ID {
-        ty::mk_nil()
+        ty::mk_nil(cx.tcx)
     } else {
         ty::pat_ty(cx.tcx, &*real_pat)
     };
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 1a3267492d2..a626a028e2e 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -311,8 +311,7 @@ pub enum const_val {
     const_uint(u64),
     const_str(InternedString),
     const_binary(Rc<Vec<u8> >),
-    const_bool(bool),
-    const_nil
+    const_bool(bool)
 }
 
 pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<Pat> {
@@ -589,7 +588,6 @@ pub fn lit_to_const(lit: &Lit) -> const_val {
         LitFloatUnsuffixed(ref n) => {
             const_float(from_str::<f64>(n.get()).unwrap() as f64)
         }
-        LitNil => const_nil,
         LitBool(b) => const_bool(b)
     }
 }
@@ -605,7 +603,6 @@ pub fn compare_const_vals(a: &const_val, b: &const_val) -> Option<int> {
         (&const_str(ref a), &const_str(ref b)) => compare_vals(a, b),
         (&const_bool(a), &const_bool(b)) => compare_vals(a, b),
         (&const_binary(ref a), &const_binary(ref b)) => compare_vals(a, b),
-        (&const_nil, &const_nil) => compare_vals((), ()),
         _ => None
     }
 }
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index e9884d0376d..d3b70afe39b 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -1239,6 +1239,7 @@ struct VisiblePrivateTypesVisitor<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
     exported_items: &'a ExportedItems,
     public_items: &'a PublicItems,
+    in_variant: bool,
 }
 
 struct CheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
@@ -1514,13 +1515,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
 
     fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics) {
         if self.exported_items.contains(&v.node.id) {
+            self.in_variant = true;
             visit::walk_variant(self, v, g);
+            self.in_variant = false;
         }
     }
 
     fn visit_struct_field(&mut self, s: &ast::StructField) {
         match s.node.kind {
-            ast::NamedField(_, ast::Public)  => {
+            ast::NamedField(_, vis) if vis == ast::Public || self.in_variant => {
                 visit::walk_struct_field(self, s);
             }
             _ => {}
@@ -1598,7 +1601,8 @@ pub fn check_crate(tcx: &ty::ctxt,
         let mut visitor = VisiblePrivateTypesVisitor {
             tcx: tcx,
             exported_items: &exported_items,
-            public_items: &public_items
+            public_items: &public_items,
+            in_variant: false,
         };
         visit::walk_crate(&mut visitor, krate);
     }
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index e4a6b14767f..fd62d0cdc11 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -102,10 +102,10 @@ pub enum LastPrivate {
     // and whether the import is in fact used for each.
     // If the Option<PrivateDep> fields are None, it means there is no definition
     // in that namespace.
-    LastImport{pub value_priv: Option<PrivateDep>,
-               pub value_used: ImportUse,
-               pub type_priv: Option<PrivateDep>,
-               pub type_used: ImportUse},
+    LastImport{value_priv: Option<PrivateDep>,
+               value_used: ImportUse,
+               type_priv: Option<PrivateDep>,
+               type_used: ImportUse},
 }
 
 #[deriving(Show)]
@@ -4285,7 +4285,9 @@ impl<'a> Resolver<'a> {
                                     _ => {}
                                 }
 
-                                this.resolve_type(&*ty_m.decl.output);
+                                if let ast::Return(ref ret_ty) = ty_m.decl.output {
+                                    this.resolve_type(&**ret_ty);
+                                }
                             });
                           }
                           ast::ProvidedMethod(ref m) => {
@@ -4467,7 +4469,9 @@ impl<'a> Resolver<'a> {
                         debug!("(resolving function) recorded argument");
                     }
 
-                    this.resolve_type(&*declaration.output);
+                    if let ast::Return(ref ret_ty) = declaration.output {
+                        this.resolve_type(&**ret_ty);
+                    }
                 }
             }
 
diff --git a/src/librustc/middle/save/mod.rs b/src/librustc/middle/save/mod.rs
index 59fbcde85e8..367fe2845dd 100644
--- a/src/librustc/middle/save/mod.rs
+++ b/src/librustc/middle/save/mod.rs
@@ -383,7 +383,11 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
         for arg in method.pe_fn_decl().inputs.iter() {
             self.visit_ty(&*arg.ty);
         }
-        self.visit_ty(&*method.pe_fn_decl().output);
+
+        if let ast::Return(ref ret_ty) = method.pe_fn_decl().output {
+            self.visit_ty(&**ret_ty);
+        }
+
         // walk the fn body
         self.nest(method.id, |v| v.visit_block(&*method.pe_body()));
 
@@ -491,7 +495,10 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
         for arg in decl.inputs.iter() {
             self.visit_ty(&*arg.ty);
         }
-        self.visit_ty(&*decl.output);
+
+        if let ast::Return(ref ret_ty) = decl.output {
+            self.visit_ty(&**ret_ty);
+        }
 
         // walk the body
         self.nest(item.id, |v| v.visit_block(&*body));
@@ -1136,7 +1143,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                 for arg in method_type.decl.inputs.iter() {
                     self.visit_ty(&*arg.ty);
                 }
-                self.visit_ty(&*method_type.decl.output);
+
+                if let ast::Return(ref ret_ty) = method_type.decl.output {
+                    self.visit_ty(&**ret_ty);
+                }
 
                 self.process_generic_params(&method_type.generics,
                                             method_type.span,
@@ -1352,7 +1362,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                 for arg in decl.inputs.iter() {
                     self.visit_ty(&*arg.ty);
                 }
-                self.visit_ty(&*decl.output);
+
+                if let ast::Return(ref ret_ty) = decl.output {
+                    self.visit_ty(&**ret_ty);
+                }
 
                 // walk the body
                 self.nest(ex.id, |v| v.visit_block(&**body));
diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs
index 9900620b229..be5a007c1eb 100644
--- a/src/librustc/middle/traits/coherence.rs
+++ b/src/librustc/middle/traits/coherence.rs
@@ -79,7 +79,6 @@ pub fn ty_is_local(tcx: &ty::ctxt,
     debug!("ty_is_local({})", ty.repr(tcx));
 
     match ty::get(ty).sty {
-        ty::ty_nil |
         ty::ty_bool |
         ty::ty_char |
         ty::ty_int(..) |
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index ce8ba7c14d3..b50956ec9db 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -1227,7 +1227,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::ty_infer(ty::FloatVar(_)) |
             ty::ty_uint(_) |
             ty::ty_int(_) |
-            ty::ty_nil |
             ty::ty_bool |
             ty::ty_float(_) |
             ty::ty_bare_fn(_) |
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 46a72ae8dc0..7035df542c0 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -1012,7 +1012,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                          .unwrap_or(DUMMY_NODE_ID);
 
     let left_ty = if pat_id == DUMMY_NODE_ID {
-        ty::mk_nil()
+        ty::mk_nil(tcx)
     } else {
         node_id_type(bcx, pat_id)
     };
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index 0d3a84eb8bc..19209a3b8e6 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -101,9 +101,9 @@ pub enum Repr {
      * otherwise it indicates the other case.
      */
     RawNullablePointer {
-        pub nndiscr: Disr,
-        pub nnty: ty::t,
-        pub nullfields: Vec<ty::t>
+        nndiscr: Disr,
+        nnty: ty::t,
+        nullfields: Vec<ty::t>
     },
     /**
      * Two cases distinguished by a nullable pointer: the case with discriminant
@@ -117,10 +117,10 @@ pub enum Repr {
      * identity function.
      */
     StructWrappedNullablePointer {
-        pub nonnull: Struct,
-        pub nndiscr: Disr,
-        pub ptrfield: PointerField,
-        pub nullfields: Vec<ty::t>,
+        nonnull: Struct,
+        nndiscr: Disr,
+        ptrfield: PointerField,
+        nullfields: Vec<ty::t>,
     }
 }
 
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index d79d703336f..86fe3e7a641 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -47,7 +47,7 @@ use middle::trans::builder::{Builder, noname};
 use middle::trans::callee;
 use middle::trans::cleanup::{CleanupMethods, ScopeId};
 use middle::trans::cleanup;
-use middle::trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral, C_nil};
+use middle::trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral};
 use middle::trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_uint, C_undef};
 use middle::trans::common::{CrateContext, ExternMap, FunctionContext};
 use middle::trans::common::{NodeInfo, Result, SubstP};
@@ -517,7 +517,7 @@ pub fn get_res_dtor(ccx: &CrateContext,
         let class_ty = ty::lookup_item_type(tcx, parent_id).ty.subst(tcx, substs);
         let llty = type_of_dtor(ccx, class_ty);
         let dtor_ty = ty::mk_ctor_fn(ccx.tcx(), ast::DUMMY_NODE_ID,
-                                     [glue::get_drop_glue_type(ccx, t)], ty::mk_nil());
+                                     [glue::get_drop_glue_type(ccx, t)], ty::mk_nil(ccx.tcx()));
         get_extern_fn(ccx,
                       &mut *ccx.externs().borrow_mut(),
                       name.as_slice(),
@@ -551,7 +551,7 @@ pub fn compare_scalar_types<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
     let f = |a| Result::new(cx, compare_scalar_values(cx, lhs, rhs, a, op));
 
     match ty::get(t).sty {
-        ty::ty_nil => f(nil_type),
+        ty::ty_tup(ref tys) if tys.is_empty() => f(nil_type),
         ty::ty_bool | ty::ty_uint(_) | ty::ty_char => f(unsigned_int),
         ty::ty_ptr(mt) if ty::type_is_sized(cx.tcx(), mt.ty) => f(unsigned_int),
         ty::ty_int(_) => f(signed_int),
@@ -1578,12 +1578,6 @@ fn create_datums_for_fn_args_under_call_abi(
                                                                 "argtuple"));
                 result.push(tuple);
             }
-            ty::ty_nil => {
-                let mode = datum::Rvalue::new(datum::ByValue);
-                result.push(datum::Datum::new(C_nil(bcx.ccx()),
-                                              ty::mk_nil(),
-                                              mode))
-            }
             _ => {
                 bcx.tcx().sess.bug("last argument of a function with \
                                     `rust-call` ABI isn't a tuple?!")
@@ -1647,10 +1641,8 @@ fn copy_unboxed_closure_args_to_allocas<'blk, 'tcx>(
                       arg_datum.to_lvalue_datum_in_scope(bcx,
                                                          "argtuple",
                                                          arg_scope_id));
-    let empty = Vec::new();
     let untupled_arg_types = match ty::get(monomorphized_arg_types[0]).sty {
         ty::ty_tup(ref types) => types.as_slice(),
-        ty::ty_nil => empty.as_slice(),
         _ => {
             bcx.tcx().sess.span_bug(args[0].pat.span,
                                     "first arg to `rust-call` ABI function \
@@ -1824,7 +1816,7 @@ pub fn trans_closure(ccx: &CrateContext,
         NotUnboxedClosure => monomorphized_arg_types,
 
         // Tuple up closure argument types for the "rust-call" ABI.
-        IsUnboxedClosure => vec![ty::mk_tup_or_nil(ccx.tcx(), monomorphized_arg_types)]
+        IsUnboxedClosure => vec![ty::mk_tup(ccx.tcx(), monomorphized_arg_types)]
     };
     for monomorphized_arg_type in monomorphized_arg_types.iter() {
         debug!("trans_closure: monomorphized_arg_type: {}",
@@ -2380,7 +2372,6 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
             assert!(abi == RustCall);
 
             match ty::get(fn_sig.inputs[0]).sty {
-                ty::ty_nil => Vec::new(),
                 ty::ty_tup(ref inputs) => inputs.clone(),
                 _ => ccx.sess().bug("expected tuple'd inputs")
             }
@@ -2389,7 +2380,6 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
             let mut inputs = vec![fn_sig.inputs[0]];
 
             match ty::get(fn_sig.inputs[1]).sty {
-                ty::ty_nil => inputs,
                 ty::ty_tup(ref t_in) => {
                     inputs.push_all(t_in.as_slice());
                     inputs
@@ -2532,7 +2522,7 @@ pub fn register_fn_llvmty(ccx: &CrateContext,
                           llfty: Type) -> ValueRef {
     debug!("register_fn_llvmty id={} sym={}", node_id, sym);
 
-    let llfn = decl_fn(ccx, sym.as_slice(), cc, llfty, ty::FnConverging(ty::mk_nil()));
+    let llfn = decl_fn(ccx, sym.as_slice(), cc, llfty, ty::FnConverging(ty::mk_nil(ccx.tcx())));
     finish_register_fn(ccx, sp, sym, node_id, llfn);
     llfn
 }
@@ -2564,7 +2554,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
         let llfty = Type::func([ccx.int_type(), Type::i8p(ccx).ptr_to()],
                                &ccx.int_type());
 
-        let llfn = decl_cdecl_fn(ccx, "main", llfty, ty::mk_nil());
+        let llfn = decl_cdecl_fn(ccx, "main", llfty, ty::mk_nil(ccx.tcx()));
 
         // FIXME: #16581: Marking a symbol in the executable with `dllexport`
         // linkage forces MinGW's linker to output a `.reloc` section for ASLR
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 7a040196ea8..f62159cd490 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -764,7 +764,7 @@ pub fn trans_call_inner<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         expr::Ignore => {
             let ret_ty = match ret_ty {
                 ty::FnConverging(ret_ty) => ret_ty,
-                ty::FnDiverging => ty::mk_nil()
+                ty::FnDiverging => ty::mk_nil(ccx.tcx())
             };
             if !is_rust_fn ||
               type_of::return_uses_outptr(ccx, ret_ty) ||
@@ -957,7 +957,6 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
                 llargs.push(arg_datum.add_clean(bcx.fcx, arg_cleanup_scope));
             }
         }
-        ty::ty_nil => {}
         _ => {
             bcx.sess().span_bug(tuple_expr.span,
                                 "argument to `.call()` wasn't a tuple?!")
@@ -1004,7 +1003,6 @@ fn trans_overloaded_call_args<'blk, 'tcx>(
                 }))
             }
         }
-        ty::ty_nil => {}
         _ => {
             bcx.sess().span_bug(arg_exprs[0].span,
                                 "argument to `.call()` wasn't a tuple?!")
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index 6c8ae8b45ff..1cdd681c8bc 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -81,7 +81,6 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
             }
         }
         ast::LitBool(b) => C_bool(cx, b),
-        ast::LitNil => C_nil(cx),
         ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
         ast::LitBinary(ref data) => C_binary_slice(cx, data.as_slice()),
     }
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index aa3d9ae83fa..85700efec71 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -718,7 +718,9 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
     macro_rules! ifn (
         ($name:expr fn() -> $ret:expr) => (
             if *key == $name {
-                let f = base::decl_cdecl_fn(ccx, $name, Type::func([], &$ret), ty::mk_nil());
+                let f = base::decl_cdecl_fn(
+                    ccx, $name, Type::func([], &$ret),
+                    ty::mk_nil(ccx.tcx()));
                 ccx.intrinsics().borrow_mut().insert($name, f.clone());
                 return Some(f);
             }
@@ -726,7 +728,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
         ($name:expr fn($($arg:expr),*) -> $ret:expr) => (
             if *key == $name {
                 let f = base::decl_cdecl_fn(ccx, $name,
-                                  Type::func([$($arg),*], &$ret), ty::mk_nil());
+                                  Type::func([$($arg),*], &$ret), ty::mk_nil(ccx.tcx()));
                 ccx.intrinsics().borrow_mut().insert($name, f.clone());
                 return Some(f);
             }
@@ -863,7 +865,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
             } else if *key == $name {
                 let f = base::decl_cdecl_fn(ccx, stringify!($cname),
                                       Type::func([$($arg),*], &$ret),
-                                      ty::mk_nil());
+                                      ty::mk_nil(ccx.tcx()));
                 ccx.intrinsics().borrow_mut().insert($name, f.clone());
                 return Some(f);
             }
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index ebf05f51e73..6e909e6532e 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -350,7 +350,6 @@ impl TypeMap {
         unique_type_id.push('{');
 
         match ty::get(type_).sty {
-            ty::ty_nil      |
             ty::ty_bool     |
             ty::ty_char     |
             ty::ty_str      |
@@ -367,6 +366,9 @@ impl TypeMap {
                 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) if component_types.is_empty() => {
+                push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
+            },
             ty::ty_tup(ref component_types) => {
                 unique_type_id.push_str("tuple ");
                 for &component_type in component_types.iter() {
@@ -1372,10 +1374,9 @@ pub fn create_function_debug_context(cx: &CrateContext,
         let mut signature = Vec::with_capacity(fn_decl.inputs.len() + 1);
 
         // Return type -- llvm::DIBuilder wants this at index 0
-        match fn_decl.output.node {
-            ast::TyNil => {
-                signature.push(ptr::null_mut());
-            }
+        match fn_decl.output {
+            ast::Return(ref ret_ty) if ret_ty.node == ast::TyTup(vec![]) =>
+                signature.push(ptr::null_mut()),
             _ => {
                 assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
 
@@ -1736,7 +1737,8 @@ fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
     debug!("basic_type_metadata: {}", ty::get(t));
 
     let (name, encoding) = match ty::get(t).sty {
-        ty::ty_nil => ("()".to_string(), DW_ATE_unsigned),
+        ty::ty_tup(ref elements) if elements.is_empty() =>
+            ("()".to_string(), DW_ATE_unsigned),
         ty::ty_bool => ("bool".to_string(), DW_ATE_boolean),
         ty::ty_char => ("char".to_string(), DW_ATE_unsigned_char),
         ty::ty_int(int_ty) => match int_ty {
@@ -2773,7 +2775,7 @@ fn subroutine_type_metadata(cx: &CrateContext,
     // return type
     signature_metadata.push(match signature.output {
         ty::FnConverging(ret_ty) => match ty::get(ret_ty).sty {
-            ty::ty_nil => ptr::null_mut(),
+            ty::ty_tup(ref tys) if tys.is_empty() => ptr::null_mut(),
             _ => type_metadata(cx, ret_ty, span)
         },
         ty::FnDiverging => diverging_type_metadata(cx)
@@ -2880,7 +2882,6 @@ fn type_metadata(cx: &CrateContext,
 
     let sty = &ty::get(t).sty;
     let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
-        ty::ty_nil      |
         ty::ty_bool     |
         ty::ty_char     |
         ty::ty_int(_)   |
@@ -2888,6 +2889,9 @@ fn type_metadata(cx: &CrateContext,
         ty::ty_float(_) => {
             MetadataCreationResult::new(basic_type_metadata(cx, t), false)
         }
+        ty::ty_tup(ref elements) if elements.is_empty() => {
+            MetadataCreationResult::new(basic_type_metadata(cx, t), false)
+        }
         ty::ty_enum(def_id, _) => {
             prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx)
         }
@@ -3669,9 +3673,8 @@ fn compute_debuginfo_type_name(cx: &CrateContext,
 fn push_debuginfo_type_name(cx: &CrateContext,
                             t: ty::t,
                             qualified: bool,
-                            output:&mut String) {
+                            output: &mut String) {
     match ty::get(t).sty {
-        ty::ty_nil               => output.push_str("()"),
         ty::ty_bool              => output.push_str("bool"),
         ty::ty_char              => output.push_str("char"),
         ty::ty_str               => output.push_str("str"),
@@ -3698,8 +3701,10 @@ fn push_debuginfo_type_name(cx: &CrateContext,
                 push_debuginfo_type_name(cx, component_type, true, output);
                 output.push_str(", ");
             }
-            output.pop();
-            output.pop();
+            if !component_types.is_empty() {
+                output.pop();
+                output.pop();
+            }
             output.push(')');
         },
         ty::ty_uniq(inner_type) => {
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index bed45a28691..0b03163a02b 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -520,7 +520,7 @@ pub fn decl_rust_fn_with_foreign_abi(ccx: &CrateContext,
         }
         _ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi")
     };
-    let llfn = base::decl_fn(ccx, name, cconv, llfn_ty, ty::FnConverging(ty::mk_nil()));
+    let llfn = base::decl_fn(ccx, name, cconv, llfn_ty, ty::FnConverging(ty::mk_nil(ccx.tcx())));
     add_argument_attributes(&tys, llfn);
     debug!("decl_rust_fn_with_foreign_abi(llfn_ty={}, llfn={})",
            ccx.tn().type_to_string(llfn_ty), ccx.tn().val_to_string(llfn));
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 0a44abb6780..f5db3d41812 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -159,7 +159,7 @@ pub fn get_drop_glue(ccx: &CrateContext, t: ty::t) -> ValueRef {
 
     let (glue, new_sym) = match ccx.available_drop_glues().borrow().get(&t) {
         Some(old_sym) => {
-            let glue = decl_cdecl_fn(ccx, old_sym.as_slice(), llfnty, ty::mk_nil());
+            let glue = decl_cdecl_fn(ccx, old_sym.as_slice(), llfnty, ty::mk_nil(ccx.tcx()));
             (glue, None)
         },
         None => {
@@ -288,7 +288,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
 
         let dtor_ty = ty::mk_ctor_fn(variant_cx.tcx(), ast::DUMMY_NODE_ID,
-                                     [get_drop_glue_type(bcx.ccx(), t)], ty::mk_nil());
+                                     [get_drop_glue_type(bcx.ccx(), t)], ty::mk_nil(bcx.tcx()));
         let (_, variant_cx) = invoke(variant_cx, dtor_addr, args, dtor_ty, None, false);
 
         variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope);
@@ -520,7 +520,7 @@ fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
         ccx,
         t,
         format!("glue_{}", name).as_slice());
-    let llfn = decl_cdecl_fn(ccx, fn_nm.as_slice(), llfnty, ty::mk_nil());
+    let llfn = decl_cdecl_fn(ccx, fn_nm.as_slice(), llfnty, ty::mk_nil(ccx.tcx()));
     note_unique_llvm_symbol(ccx, fn_nm.clone());
     return (fn_nm, llfn);
 }
@@ -538,10 +538,11 @@ fn make_generic_glue(ccx: &CrateContext,
 
     let arena = TypedArena::new();
     let empty_param_substs = param_substs::empty();
-    let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false, ty::FnConverging(ty::mk_nil()),
+    let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false,
+                          ty::FnConverging(ty::mk_nil(ccx.tcx())),
                           &empty_param_substs, None, &arena);
 
-    let bcx = init_function(&fcx, false, ty::FnConverging(ty::mk_nil()));
+    let bcx = init_function(&fcx, false, ty::FnConverging(ty::mk_nil(ccx.tcx())));
 
     update_linkage(ccx, llfn, None, OriginalTranslation);
 
@@ -556,7 +557,7 @@ fn make_generic_glue(ccx: &CrateContext,
 
     let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint);
     let bcx = helper(bcx, llrawptr0, t);
-    finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil()));
+    finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())));
 
     llfn
 }
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 553e0b22d5c..4af4b397a6e 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -594,7 +594,6 @@ pub fn get_vtable(bcx: Block,
                                             new_inputs.push(element.subst(bcx.tcx(), substs));
                                         }
                                     }
-                                    ty::ty_nil => {}
                                     _ => {
                                         bcx.tcx().sess.bug("get_vtable(): closure \
                                                             type wasn't a tuple")
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index 092fe2d1fa9..c185a1ba539 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -83,7 +83,6 @@ pub fn untuple_arguments_if_necessary(ccx: &CrateContext,
                 result.push(tupled_argument);
             }
         }
-        ty::ty_nil => {}
         _ => {
             ccx.tcx().sess.bug("argument to function with \"rust-call\" ABI \
                                 is neither a tuple nor unit")
@@ -186,7 +185,6 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
                                   ppaux::ty_to_string(cx.tcx(), t)).as_slice())
         }
 
-        ty::ty_nil => Type::nil(cx),
         ty::ty_bool => Type::bool(cx),
         ty::ty_char => Type::char(cx),
         ty::ty_int(t) => Type::int_from_ty(cx, t),
@@ -211,6 +209,10 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
             Type::array(&llty, size)
         }
 
+        ty::ty_tup(ref tys) if tys.is_empty() => {
+            Type::nil(cx)
+        }
+
         ty::ty_tup(..) | ty::ty_enum(..) | ty::ty_unboxed_closure(..) => {
             let repr = adt::represent_type(cx, t);
             adt::sizing_type_of(cx, &*repr, false)
@@ -298,7 +300,6 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
     }
 
     let mut llty = match ty::get(t).sty {
-      ty::ty_nil => Type::nil(cx),
       ty::ty_bool => Type::bool(cx),
       ty::ty_char => Type::char(cx),
       ty::ty_int(t) => Type::int_from_ty(cx, t),
@@ -365,6 +366,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
           let fn_ty = type_of_fn_from_ty(cx, t).ptr_to();
           Type::struct_(cx, [fn_ty, Type::i8p(cx)], false)
       }
+      ty::ty_tup(ref tys) if tys.is_empty() => Type::nil(cx),
       ty::ty_tup(..) => {
           let repr = adt::represent_type(cx, t);
           adt::type_of(cx, &*repr)
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 8ec5e381b92..059394dc832 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -906,7 +906,6 @@ mod primitives {
         )
     )
 
-    def_prim_ty!(TY_NIL,    super::ty_nil)
     def_prim_ty!(TY_BOOL,   super::ty_bool)
     def_prim_ty!(TY_CHAR,   super::ty_char)
     def_prim_ty!(TY_INT,    super::ty_int(ast::TyI))
@@ -932,7 +931,6 @@ mod primitives {
 // AST structure in libsyntax/ast.rs as well.
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub enum sty {
-    ty_nil,
     ty_bool,
     ty_char,
     ty_int(ast::IntTy),
@@ -1557,7 +1555,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
 pub fn mk_t(cx: &ctxt, st: sty) -> t {
     // Check for primitive types.
     match st {
-        ty_nil => return mk_nil(),
         ty_err => return mk_err(),
         ty_bool => return mk_bool(),
         ty_int(i) => return mk_mach_int(i),
@@ -1603,7 +1600,7 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
         rflags(bounds.region_bound)
     }
     match &st {
-      &ty_nil | &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
+      &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
       &ty_str => {}
       // You might think that we could just return ty_err for
       // any type containing ty_err as a component, and get
@@ -1690,9 +1687,6 @@ pub fn mk_prim_t(primitive: &'static t_box_) -> t {
 }
 
 #[inline]
-pub fn mk_nil() -> t { mk_prim_t(&primitives::TY_NIL) }
-
-#[inline]
 pub fn mk_err() -> t { mk_prim_t(&primitives::TY_ERR) }
 
 #[inline]
@@ -1803,7 +1797,7 @@ pub fn mk_imm_ptr(cx: &ctxt, ty: t) -> t {
 }
 
 pub fn mk_nil_ptr(cx: &ctxt) -> t {
-    mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::MutImmutable})
+    mk_ptr(cx, mt {ty: mk_nil(cx), mutbl: ast::MutImmutable})
 }
 
 pub fn mk_vec(cx: &ctxt, t: t, sz: Option<uint>) -> t {
@@ -1818,14 +1812,12 @@ pub fn mk_slice(cx: &ctxt, r: Region, tm: mt) -> t {
             })
 }
 
-pub fn mk_tup(cx: &ctxt, ts: Vec<t>) -> t { mk_t(cx, ty_tup(ts)) }
+pub fn mk_tup(cx: &ctxt, ts: Vec<t>) -> t {
+    mk_t(cx, ty_tup(ts))
+}
 
-pub fn mk_tup_or_nil(cx: &ctxt, ts: Vec<t>) -> t {
-    if ts.len() == 0 {
-        ty::mk_nil()
-    } else {
-        mk_t(cx, ty_tup(ts))
-    }
+pub fn mk_nil(cx: &ctxt) -> t {
+    mk_tup(cx, Vec::new())
 }
 
 pub fn mk_closure(cx: &ctxt, fty: ClosureTy) -> t {
@@ -1908,7 +1900,7 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
         return;
     }
     match get(ty).sty {
-        ty_nil | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
+        ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
         ty_str | ty_infer(_) | ty_param(_) | ty_err => {}
         ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty(ty, f),
         ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
@@ -1996,7 +1988,10 @@ impl ParamBounds {
 // Type utilities
 
 pub fn type_is_nil(ty: t) -> bool {
-    get(ty).sty == ty_nil
+    match get(ty).sty {
+        ty_tup(ref tys) => tys.is_empty(),
+        _ => false
+    }
 }
 
 pub fn type_is_error(ty: t) -> bool {
@@ -2133,9 +2128,10 @@ pub fn type_is_fat_ptr(cx: &ctxt, ty: t) -> bool {
 */
 pub fn type_is_scalar(ty: t) -> bool {
     match get(ty).sty {
-      ty_nil | ty_bool | ty_char | ty_int(_) | ty_float(_) | ty_uint(_) |
+      ty_bool | ty_char | ty_int(_) | ty_float(_) | ty_uint(_) |
       ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) |
       ty_bare_fn(..) | ty_ptr(_) => true,
+      ty_tup(ref tys) if tys.is_empty() => true,
       _ => false
     }
 }
@@ -2170,7 +2166,7 @@ pub fn type_needs_unwind_cleanup(cx: &ctxt, ty: t) -> bool {
         let mut needs_unwind_cleanup = false;
         maybe_walk_ty(ty, |ty| {
             needs_unwind_cleanup |= match get(ty).sty {
-                ty_nil | ty_bool | ty_int(_) | ty_uint(_) |
+                ty_bool | ty_int(_) | ty_uint(_) |
                 ty_float(_) | ty_tup(_) | ty_ptr(_) => false,
 
                 ty_enum(did, ref substs) =>
@@ -2429,7 +2425,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
 
             // Scalar and unique types are sendable, and durable
             ty_infer(ty::SkolemizedIntTy(_)) |
-            ty_nil | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
+            ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
             ty_bare_fn(_) | ty::ty_char => {
                 TC::None
             }
@@ -2740,7 +2736,6 @@ pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
             ty_vec(_, Some(0)) => false, // don't need no contents
             ty_vec(ty, Some(_)) => type_requires(cx, seen, r_ty, ty),
 
-            ty_nil |
             ty_bool |
             ty_char |
             ty_int(_) |
@@ -3779,10 +3774,11 @@ pub fn impl_or_trait_item_idx(id: ast::Name, trait_items: &[ImplOrTraitItem])
 
 pub fn ty_sort_string(cx: &ctxt, t: t) -> String {
     match get(t).sty {
-        ty_nil | ty_bool | ty_char | ty_int(_) |
+        ty_bool | ty_char | ty_int(_) |
         ty_uint(_) | ty_float(_) | ty_str => {
             ::util::ppaux::ty_to_string(cx, t)
         }
+        ty_tup(ref tys) if tys.is_empty() => ::util::ppaux::ty_to_string(cx, t),
 
         ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
         ty_uniq(_) => "box".to_string(),
@@ -4777,54 +4773,42 @@ pub fn normalize_ty(cx: &ctxt, t: t) -> t {
 // Returns the repeat count for a repeating vector expression.
 pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
     match const_eval::eval_const_expr_partial(tcx, count_expr) {
-      Ok(ref const_val) => match *const_val {
-        const_eval::const_int(count) => if count < 0 {
-            tcx.sess.span_err(count_expr.span,
-                              "expected positive integer for \
-                               repeat count, found negative integer");
-            0
-        } else {
-            count as uint
-        },
-        const_eval::const_uint(count) => count as uint,
-        const_eval::const_float(count) => {
-            tcx.sess.span_err(count_expr.span,
-                              "expected positive integer for \
-                               repeat count, found float");
-            count as uint
-        }
-        const_eval::const_str(_) => {
-            tcx.sess.span_err(count_expr.span,
-                              "expected positive integer for \
-                               repeat count, found string");
-            0
-        }
-        const_eval::const_bool(_) => {
-            tcx.sess.span_err(count_expr.span,
-                              "expected positive integer for \
-                               repeat count, found boolean");
-            0
-        }
-        const_eval::const_binary(_) => {
-            tcx.sess.span_err(count_expr.span,
-                              "expected positive integer for \
-                               repeat count, found binary array");
-            0
-        }
-        const_eval::const_nil => {
-            tcx.sess.span_err(count_expr.span,
-                              "expected positive integer for \
-                               repeat count, found ()");
-            0
-        }
-      },
-      Err(..) => {
-        tcx.sess.span_err(count_expr.span,
-                          "expected constant integer for repeat count, \
-                           found variable");
-        0
-      }
+        Ok(val) => {
+            let found = match val {
+                const_eval::const_uint(count) => return count as uint,
+                const_eval::const_int(count) if count >= 0 => return count as uint,
+                const_eval::const_int(_) =>
+                    "negative integer",
+                const_eval::const_float(_) =>
+                    "float",
+                const_eval::const_str(_) =>
+                    "string",
+                const_eval::const_bool(_) =>
+                    "boolean",
+                const_eval::const_binary(_) =>
+                    "binary array"
+            };
+            tcx.sess.span_err(count_expr.span, format!(
+                "expected positive integer for repeat count, found {}",
+                found).as_slice());
+        }
+        Err(_) => {
+            let found = match count_expr.node {
+                ast::ExprPath(ast::Path {
+                    global: false,
+                    ref segments,
+                    ..
+                }) if segments.len() == 1 =>
+                    "variable",
+                _ =>
+                    "non-constant expression"
+            };
+            tcx.sess.span_err(count_expr.span, format!(
+                "expected constant integer for repeat count, found {}",
+                found).as_slice());
+        }
     }
+    0
 }
 
 // Iterate over a type parameter's bounded traits and any supertraits
@@ -5141,7 +5125,6 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
     };
     ty::walk_ty(t, |t| {
         match ty::get(t).sty {
-            ty_nil => byte!(0),
             ty_bool => byte!(2),
             ty_char => byte!(3),
             ty_int(i) => {
@@ -5512,7 +5495,6 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
                 accumulator.push(*region);
                 accum_substs(accumulator, substs);
             }
-            ty_nil |
             ty_bool |
             ty_char |
             ty_int(_) |
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 031c7b2aed6..6d8d03aa0ab 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -554,7 +554,7 @@ pub fn super_fold_sty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
         ty::ty_unboxed_closure(did, ref region, ref substs) => {
             ty::ty_unboxed_closure(did, region.fold_with(this), substs.fold_with(this))
         }
-        ty::ty_nil | ty::ty_bool | ty::ty_char | ty::ty_str |
+        ty::ty_bool | ty::ty_char | ty::ty_str |
         ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
         ty::ty_err | ty::ty_infer(_) |
         ty::ty_param(..) => {
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index ec289a2d806..8df4d59a292 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -385,11 +385,11 @@ fn ast_path_substs<'tcx,AC,RS>(
         let inputs = data.inputs.iter()
                                 .map(|a_t| ast_ty_to_ty(this, &binding_rscope, &**a_t))
                                 .collect();
-        let input_ty = ty::mk_tup_or_nil(this.tcx(), inputs);
+        let input_ty = ty::mk_tup(this.tcx(), inputs);
 
         let output = match data.output {
             Some(ref output_ty) => ast_ty_to_ty(this, &binding_rscope, &**output_ty),
-            None => ty::mk_nil()
+            None => ty::mk_nil(this.tcx())
         };
 
         (Vec::new(), vec![input_ty, output])
@@ -652,12 +652,6 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
     }
 }
 
-#[deriving(Show)]
-enum PointerTy {
-    RPtr(ty::Region),
-    Uniq
-}
-
 // Handle `~`, `Box`, and `&` being able to mean strs and vecs.
 // If a_seq_ty is a str or a vec, make it a str/vec.
 // Also handle first-class trait types.
@@ -666,14 +660,14 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
         rscope: &RS,
         a_seq_mutbl: ast::Mutability,
         a_seq_ty: &ast::Ty,
-        ptr_ty: PointerTy,
+        region: ty::Region,
         constr: |ty::t| -> ty::t)
         -> ty::t
 {
     let tcx = this.tcx();
 
-    debug!("mk_pointer(ptr_ty={}, a_seq_ty={})",
-           ptr_ty,
+    debug!("mk_pointer(region={}, a_seq_ty={})",
+           region,
            a_seq_ty.repr(tcx));
 
     match a_seq_ty.node {
@@ -688,14 +682,7 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
             match tcx.def_map.borrow().get(&id) {
                 Some(&def::DefPrimTy(ast::TyStr)) => {
                     check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                    match ptr_ty {
-                        Uniq => {
-                            return constr(ty::mk_str(tcx));
-                        }
-                        RPtr(r) => {
-                            return ty::mk_str_slice(tcx, r, a_seq_mutbl);
-                        }
-                    }
+                    return ty::mk_str_slice(tcx, region, a_seq_mutbl);
                 }
                 Some(&def::DefTrait(trait_def_id)) => {
                     let result = ast_path_to_trait_ref(this,
@@ -716,14 +703,7 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                     let tr = ty::mk_trait(tcx,
                                           result,
                                           existential_bounds);
-                    return match ptr_ty {
-                        Uniq => {
-                            return ty::mk_uniq(tcx, tr);
-                        }
-                        RPtr(r) => {
-                            return ty::mk_rptr(tcx, r, ty::mt{mutbl: a_seq_mutbl, ty: tr});
-                        }
-                    };
+                    return ty::mk_rptr(tcx, region, ty::mt{mutbl: a_seq_mutbl, ty: tr});
                 }
                 _ => {}
             }
@@ -824,12 +804,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
 
     let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| {
         match ast_ty.node {
-            ast::TyNil => ty::mk_nil(),
-            ast::TyBot => unreachable!(),
-            ast::TyUniq(ref ty) => {
-                mk_pointer(this, rscope, ast::MutImmutable, &**ty, Uniq,
-                           |ty| ty::mk_uniq(tcx, ty))
-            }
             ast::TyVec(ref ty) => {
                 ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
             }
@@ -842,7 +816,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
             ast::TyRptr(ref region, ref mt) => {
                 let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
                 debug!("ty_rptr r={}", r.repr(this.tcx()));
-                mk_pointer(this, rscope, mt.mutbl, &*mt.ty, RPtr(r),
+                mk_pointer(this, rscope, mt.mutbl, &*mt.ty, r,
                            |ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
             }
             ast::TyTup(ref fields) => {
@@ -1208,22 +1182,24 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>(
                                                                    .filter(|&(_, l)| l != 0)
                                                                    .collect();
 
-    let output_ty = match decl.output.node {
-        ast::TyBot => ty::FnDiverging,
-        ast::TyInfer => ty::FnConverging(this.ty_infer(decl.output.span)),
-        _ => ty::FnConverging(match implied_output_region {
-            Some(implied_output_region) => {
-                let rb = SpecificRscope::new(implied_output_region);
-                ast_ty_to_ty(this, &rb, &*decl.output)
-            }
-            None => {
-                // All regions must be explicitly specified in the output
-                // if the lifetime elision rules do not apply. This saves
-                // the user from potentially-confusing errors.
-                let rb = UnelidableRscope::new(param_lifetimes);
-                ast_ty_to_ty(this, &rb, &*decl.output)
-            }
-        })
+    let output_ty = match decl.output {
+        ast::Return(ref output) if output.node == ast::TyInfer =>
+            ty::FnConverging(this.ty_infer(output.span)),
+        ast::Return(ref output) =>
+            ty::FnConverging(match implied_output_region {
+                Some(implied_output_region) => {
+                    let rb = SpecificRscope::new(implied_output_region);
+                    ast_ty_to_ty(this, &rb, &**output)
+                }
+                None => {
+                    // All regions must be explicitly specified in the output
+                    // if the lifetime elision rules do not apply. This saves
+                    // the user from potentially-confusing errors.
+                    let rb = UnelidableRscope::new(param_lifetimes);
+                    ast_ty_to_ty(this, &rb, &**output)
+                }
+            }),
+        ast::NoReturn(_) => ty::FnDiverging
     };
 
     (ty::BareFnTy {
@@ -1346,11 +1322,14 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
 
     let expected_ret_ty = expected_sig.map(|e| e.output);
 
-    let output_ty = match decl.output.node {
-        ast::TyBot => ty::FnDiverging,
-        ast::TyInfer if expected_ret_ty.is_some() => expected_ret_ty.unwrap(),
-        ast::TyInfer => ty::FnConverging(this.ty_infer(decl.output.span)),
-        _ => ty::FnConverging(ast_ty_to_ty(this, &rb, &*decl.output))
+    let output_ty = match decl.output {
+        ast::Return(ref output) if output.node == ast::TyInfer && expected_ret_ty.is_some() =>
+            expected_ret_ty.unwrap(),
+        ast::Return(ref output) if output.node == ast::TyInfer =>
+            ty::FnConverging(this.ty_infer(output.span)),
+        ast::Return(ref output) =>
+            ty::FnConverging(ast_ty_to_ty(this, &rb, &**output)),
+        ast::NoReturn(_) => ty::FnDiverging
     };
 
     ty::ClosureTy {
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 6280fce035a..a35bc502813 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -1214,7 +1214,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
             ty_bare_fn(..) | ty_uniq(..) | ty_rptr(..) |
             ty_infer(IntVar(_)) |
             ty_infer(FloatVar(_)) |
-            ty_param(..) | ty_nil | ty_bool |
+            ty_param(..) | ty_bool |
             ty_char | ty_int(..) | ty_uint(..) |
             ty_float(..) | ty_enum(..) | ty_ptr(..) | ty_struct(..) |
             ty_unboxed_closure(..) | ty_tup(..) | ty_open(..) |
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 0cf5069218e..d783286272c 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -556,7 +556,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
         .collect();
 
     if let ty::FnConverging(ret_ty) = ret_ty {
-        fcx.require_type_is_sized(ret_ty, decl.output.span, traits::ReturnType);
+        fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
         fn_sig_tys.push(ret_ty);
     }
 
@@ -1569,7 +1569,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn default_diverging_type_variables_to_nil(&self) {
         for (_, &ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
             if self.infcx().type_var_diverges(self.infcx().resolve_type_vars_if_possible(*ty)) {
-                demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil());
+                demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
             }
         }
     }
@@ -1741,7 +1741,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     pub fn write_nil(&self, node_id: ast::NodeId) {
-        self.write_ty(node_id, ty::mk_nil());
+        self.write_ty(node_id, ty::mk_nil(self.tcx()));
     }
     pub fn write_error(&self, node_id: ast::NodeId) {
         self.write_ty(node_id, ty::mk_err());
@@ -2664,17 +2664,6 @@ fn check_argument_types<'a>(fcx: &FnCtxt,
                     (*arg_types).clone()
                 }
             }
-            ty::ty_nil => {
-                if args.len() != 0 {
-                    span_err!(tcx.sess, sp, E0058,
-                        "this function takes 0 parameters but {} parameter{} supplied",
-                        args.len(),
-                        if args.len() == 1 {" was"} else {"s were"});
-                    err_args(args.len())
-                } else {
-                    vec![]
-                }
-            }
             _ => {
                 span_err!(tcx.sess, sp, E0059,
                     "cannot use call notation; the first type parameter \
@@ -2865,7 +2854,6 @@ fn check_lit(fcx: &FnCtxt,
             opt_ty.unwrap_or_else(
                 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
         }
-        ast::LitNil => ty::mk_nil(),
         ast::LitBool(_) => ty::mk_bool()
     }
 }
@@ -3179,7 +3167,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                                         infer::IfExpressionWithNoElse(sp),
                                         false,
                                         then_ty,
-                                        ty::mk_nil())
+                                        ty::mk_nil(fcx.tcx()))
             }
         };
 
@@ -3480,7 +3468,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
 
         // Tuple up the arguments and insert the resulting function type into
         // the `unboxed_closures` table.
-        fn_ty.sig.inputs = vec![ty::mk_tup_or_nil(fcx.tcx(), fn_ty.sig.inputs)];
+        fn_ty.sig.inputs = vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.inputs)];
 
         let kind = match kind {
             ast::FnUnboxedClosureKind => ty::FnUnboxedClosureKind,
@@ -4148,7 +4136,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                 match *expr_opt {
                     None =>
                         if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
-                                                    result_type, ty::mk_nil()) {
+                                                    result_type, ty::mk_nil(fcx.tcx())) {
                             span_err!(tcx.sess, expr.span, E0069,
                                 "`return;` in function returning non-nil");
                         },
@@ -4743,7 +4731,7 @@ pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt)  {
       ast::StmtExpr(ref expr, id) => {
         node_id = id;
         // Check with expected type of ()
-        check_expr_has_type(fcx, &**expr, ty::mk_nil());
+        check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
         let expr_ty = fcx.expr_ty(&**expr);
         saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
         saw_err = saw_err || ty::type_is_error(expr_ty);
@@ -4769,12 +4757,12 @@ pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt)  {
 }
 
 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block)  {
-    check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
+    check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
     let blkty = fcx.node_ty(blk.id);
     if ty::type_is_error(blkty) {
         fcx.write_error(blk.id);
     } else {
-        let nilty = ty::mk_nil();
+        let nilty = ty::mk_nil(fcx.tcx());
         demand::suptype(fcx, blk.span, nilty, blkty);
     }
 }
@@ -5497,7 +5485,7 @@ pub fn instantiate_path(fcx: &FnCtxt,
             data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
 
         let tuple_ty =
-            ty::mk_tup_or_nil(fcx.tcx(), input_tys);
+            ty::mk_tup(fcx.tcx(), input_tys);
 
         if type_count >= 1 {
             substs.types.push(space, tuple_ty);
@@ -5507,7 +5495,7 @@ pub fn instantiate_path(fcx: &FnCtxt,
             data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
 
         let output_ty =
-            output_ty.unwrap_or(ty::mk_nil());
+            output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
 
         if type_count >= 2 {
             substs.types.push(space, output_ty);
@@ -5727,7 +5715,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
             "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
                        param(ccx, 0)),
             "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
-                        ty::mk_nil()),
+                        ty::mk_nil(tcx)),
 
             "xchg" | "xadd" | "xsub" | "and"  | "nand" | "or" | "xor" | "max" |
             "min"  | "umax" | "umin" => {
@@ -5735,7 +5723,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                  param(ccx, 0))
             }
             "fence" => {
-                (0, Vec::new(), ty::mk_nil())
+                (0, Vec::new(), ty::mk_nil(tcx))
             }
             op => {
                 span_err!(tcx.sess, it.span, E0092,
@@ -5748,12 +5736,12 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
         (0, Vec::new(), ty::FnDiverging)
     } else {
         let (n_tps, inputs, output) = match name.get() {
-            "breakpoint" => (0, Vec::new(), ty::mk_nil()),
+            "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
             "size_of" |
             "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
             "init" => (1u, Vec::new(), param(ccx, 0u)),
             "uninit" => (1u, Vec::new(), param(ccx, 0u)),
-            "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
+            "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
             "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
             "move_val_init" => {
                 (1u,
@@ -5761,7 +5749,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                     ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
                     param(ccx, 0u)
                   ),
-               ty::mk_nil())
+               ty::mk_nil(tcx))
             }
             "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
             "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
@@ -5817,7 +5805,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                   }),
                   ty::mk_uint()
                ),
-               ty::mk_nil())
+               ty::mk_nil(tcx))
             }
             "set_memory" | "volatile_set_memory" => {
               (1,
@@ -5829,7 +5817,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                   ty::mk_u8(),
                   ty::mk_uint()
                ),
-               ty::mk_nil())
+               ty::mk_nil(tcx))
             }
             "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
             "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
@@ -5912,7 +5900,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
             "volatile_load" =>
                 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
             "volatile_store" =>
-                (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
+                (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
 
             "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
                 (0, vec!(ty::mk_i8(), ty::mk_i8()),
@@ -5948,7 +5936,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
 
             "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
 
-            "assume" => (0, vec![ty::mk_bool()], ty::mk_nil()),
+            "assume" => (0, vec![ty::mk_bool()], ty::mk_nil(tcx)),
 
             ref other => {
                 span_err!(tcx.sess, it.span, E0093,
diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs
index 0856c86946b..032b31b1f38 100644
--- a/src/librustc/middle/typeck/check/regionmanip.rs
+++ b/src/librustc/middle/typeck/check/regionmanip.rs
@@ -91,7 +91,6 @@ impl<'a, 'tcx> Wf<'a, 'tcx> {
                ty.repr(self.tcx));
 
         match ty::get(ty).sty {
-            ty::ty_nil |
             ty::ty_bool |
             ty::ty_char |
             ty::ty_int(..) |
diff --git a/src/librustc/middle/typeck/coherence/mod.rs b/src/librustc/middle/typeck/coherence/mod.rs
index 9e4728195b6..574b04c9e99 100644
--- a/src/librustc/middle/typeck/coherence/mod.rs
+++ b/src/librustc/middle/typeck/coherence/mod.rs
@@ -24,7 +24,7 @@ use middle::ty::get;
 use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
 use middle::ty::{TypeTraitItemId, lookup_item_type};
 use middle::ty::{t, ty_bool, ty_char, ty_enum, ty_err};
-use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil, ty_open};
+use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open};
 use middle::ty::{ty_param, Polytype, ty_ptr};
 use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
 use middle::ty::{ty_uint, ty_unboxed_closure, ty_uniq, ty_bare_fn};
@@ -82,7 +82,7 @@ fn get_base_type(inference_context: &InferCtxt,
             Some(resolved_type)
         }
 
-        ty_nil | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
+        ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
         ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
         ty_infer(..) | ty_param(..) | ty_err | ty_open(..) | ty_uniq(_) |
         ty_ptr(_) | ty_rptr(_, _) => {
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 6685bb9be77..eed574a1a1d 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -2096,9 +2096,11 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
                         .map(|a| ty_of_arg(ccx, &rb, a, None))
                         .collect();
 
-    let output = match decl.output.node {
-        ast::TyBot => ty::FnDiverging,
-        _ => ty::FnConverging(ast_ty_to_ty(ccx, &rb, &*decl.output))
+    let output = match decl.output {
+        ast::Return(ref ty) =>
+            ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
+        ast::NoReturn(_) =>
+            ty::FnDiverging
     };
 
     let t_fn = ty::mk_bare_fn(
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index 83d90274fd3..078a2c10bcb 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -433,7 +433,6 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<t
         }
 
       (&ty::ty_char, _) |
-      (&ty::ty_nil, _) |
       (&ty::ty_bool, _) |
       (&ty::ty_int(_), _) |
       (&ty::ty_uint(_), _) |
@@ -540,9 +539,11 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<t
                .map(|(a, b)| this.tys(*a, *b))
                .collect::<Result<_, _>>()
                .map(|ts| ty::mk_tup(tcx, ts))
-        } else {
+        } else if as_.len() != 0 && bs.len() != 0 {
             Err(ty::terr_tuple_size(
                 expected_found(this, as_.len(), bs.len())))
+        } else {
+            Err(ty::terr_sorts(expected_found(this, a, b)))
         }
       }
 
diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs
index 80b4948f6fb..e12019a1530 100644
--- a/src/librustc/middle/typeck/infer/error_reporting.rs
+++ b/src/librustc/middle/typeck/infer/error_reporting.rs
@@ -973,8 +973,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                                                    &anon_nums, &region_names);
             inputs = self.rebuild_args_ty(inputs.as_slice(), lifetime,
                                           &anon_nums, &region_names);
-            output = self.rebuild_arg_ty_or_output(&*output, lifetime,
-                                                   &anon_nums, &region_names);
+            output = self.rebuild_output(&output, lifetime, &anon_nums, &region_names);
             ty_params = self.rebuild_ty_params(ty_params, lifetime,
                                                &region_names);
         }
@@ -989,7 +988,6 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
         let new_fn_decl = ast::FnDecl {
             inputs: inputs,
             output: output,
-            cf: self.fn_decl.cf,
             variadic: self.fn_decl.variadic
         };
         (new_fn_decl, expl_self_opt, generics)
@@ -1206,6 +1204,18 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
         new_inputs
     }
 
+    fn rebuild_output(&self, ty: &ast::FunctionRetTy,
+                      lifetime: ast::Lifetime,
+                      anon_nums: &HashSet<uint>,
+                      region_names: &HashSet<ast::Name>) -> ast::FunctionRetTy {
+        match *ty {
+            ast::Return(ref ret_ty) => ast::Return(
+                self.rebuild_arg_ty_or_output(&**ret_ty, lifetime, anon_nums, region_names)
+            ),
+            ast::NoReturn(span) => ast::NoReturn(span)
+        }
+    }
+
     fn rebuild_arg_ty_or_output(&self,
                                 ty: &ast::Ty,
                                 lifetime: ast::Lifetime,
@@ -1301,7 +1311,6 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                     ty_queue.push(&*mut_ty.ty);
                 }
                 ast::TyVec(ref ty) |
-                ast::TyUniq(ref ty) |
                 ast::TyFixedLengthVec(ref ty, _) => {
                     ty_queue.push(&**ty);
                 }
@@ -1338,7 +1347,6 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                         })
                     }
                     ast::TyVec(ty) => ast::TyVec(build_to(ty, to)),
-                    ast::TyUniq(ty) => ast::TyUniq(build_to(ty, to)),
                     ast::TyFixedLengthVec(ty, e) => {
                         ast::TyFixedLengthVec(build_to(ty, to), e)
                     }
diff --git a/src/librustc/middle/typeck/infer/skolemize.rs b/src/librustc/middle/typeck/infer/skolemize.rs
index 6e5e8d72839..9458960156e 100644
--- a/src/librustc/middle/typeck/infer/skolemize.rs
+++ b/src/librustc/middle/typeck/infer/skolemize.rs
@@ -148,7 +148,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeSkolemizer<'a, 'tcx> {
                 self.tcx().sess.bug("Cannot skolemize an open existential type");
             }
 
-            ty::ty_nil |
             ty::ty_bool |
             ty::ty_char |
             ty::ty_int(..) |
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index f348e6155a2..2c8d1ce3f4f 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -382,7 +382,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 sig: ty::FnSig {
                     binder_id: main_id,
                     inputs: Vec::new(),
-                    output: ty::FnConverging(ty::mk_nil()),
+                    output: ty::FnConverging(ty::mk_nil(tcx)),
                     variadic: false
                 }
             });
diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs
index 3a2dc1d5ff0..97d7f9f1863 100644
--- a/src/librustc/middle/typeck/variance.rs
+++ b/src/librustc/middle/typeck/variance.rs
@@ -728,7 +728,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         debug!("add_constraints_from_ty(ty={})", ty.repr(self.tcx()));
 
         match ty::get(ty).sty {
-            ty::ty_nil | ty::ty_bool |
+            ty::ty_bool |
             ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) |
             ty::ty_float(_) | ty::ty_str => {
                 /* leaf type -- noop */
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 60a7436dbaa..bcd70510edd 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -19,7 +19,7 @@ use middle::ty::{ReSkolemized, ReVar, BrEnv};
 use middle::ty::{mt, t, ParamTy};
 use middle::ty::{ty_bool, ty_char, ty_struct, ty_enum};
 use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
-use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_tup, ty_open};
+use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup, ty_open};
 use middle::ty::{ty_unboxed_closure};
 use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
 use middle::ty;
@@ -384,7 +384,6 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String {
 
     // pretty print the structural type representation:
     match ty::get(typ).sty {
-        ty_nil => "()".to_string(),
         ty_bool => "bool".to_string(),
         ty_char => "char".to_string(),
         ty_int(t) => ast_util::int_ty_to_string(t, None).to_string(),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 38e0c4fe040..24cad1b6d05 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -710,8 +710,7 @@ impl Clean<Item> for ast::Method {
             inputs: Arguments {
                 values: inputs.iter().map(|x| x.clean(cx)).collect(),
             },
-            output: (self.pe_fn_decl().output.clean(cx)),
-            cf: self.pe_fn_decl().cf.clean(cx),
+            output: self.pe_fn_decl().output.clean(cx),
             attrs: Vec::new()
         };
         Item {
@@ -749,8 +748,7 @@ impl Clean<Item> for ast::TypeMethod {
             inputs: Arguments {
                 values: inputs.iter().map(|x| x.clean(cx)).collect(),
             },
-            output: (self.decl.output.clean(cx)),
-            cf: self.decl.cf.clean(cx),
+            output: self.decl.output.clean(cx),
             attrs: Vec::new()
         };
         Item {
@@ -840,8 +838,7 @@ impl Clean<ClosureDecl> for ast::ClosureTy {
 #[deriving(Clone, Encodable, Decodable, PartialEq)]
 pub struct FnDecl {
     pub inputs: Arguments,
-    pub output: Type,
-    pub cf: RetStyle,
+    pub output: FunctionRetTy,
     pub attrs: Vec<Attribute>,
 }
 
@@ -857,7 +854,6 @@ impl Clean<FnDecl> for ast::FnDecl {
                 values: self.inputs.clean(cx),
             },
             output: self.output.clean(cx),
-            cf: self.cf.clean(cx),
             attrs: Vec::new()
         }
     }
@@ -884,8 +880,7 @@ impl<'a> Clean<FnDecl> for (ast::DefId, &'a ty::FnSig) {
             let _ = names.next();
         }
         FnDecl {
-            output: sig.output.clean(cx),
-            cf: Return,
+            output: Return(sig.output.clean(cx)),
             attrs: Vec::new(),
             inputs: Arguments {
                 values: sig.inputs.iter().map(|t| {
@@ -918,16 +913,16 @@ impl Clean<Argument> for ast::Arg {
 }
 
 #[deriving(Clone, Encodable, Decodable, PartialEq)]
-pub enum RetStyle {
-    NoReturn,
-    Return
+pub enum FunctionRetTy {
+    Return(Type),
+    NoReturn
 }
 
-impl Clean<RetStyle> for ast::RetStyle {
-    fn clean(&self, _: &DocContext) -> RetStyle {
+impl Clean<FunctionRetTy> for ast::FunctionRetTy {
+    fn clean(&self, cx: &DocContext) -> FunctionRetTy {
         match *self {
-            ast::Return => Return,
-            ast::NoReturn => NoReturn
+            ast::Return(ref typ) => Return(typ.clean(cx)),
+            ast::NoReturn(_) => NoReturn
         }
     }
 }
@@ -1085,9 +1080,9 @@ impl Clean<Item> for ty::ImplOrTraitItem {
 pub enum Type {
     /// structs/enums/traits (anything that'd be an ast::TyPath)
     ResolvedPath {
-        pub path: Path,
-        pub typarams: Option<Vec<TyParamBound>>,
-        pub did: ast::DefId,
+        path: Path,
+        typarams: Option<Vec<TyParamBound>>,
+        did: ast::DefId,
     },
     // I have no idea how to usefully use this.
     TyParamBinder(ast::NodeId),
@@ -1110,9 +1105,9 @@ pub enum Type {
     Unique(Box<Type>),
     RawPointer(Mutability, Box<Type>),
     BorrowedRef {
-        pub lifetime: Option<Lifetime>,
-        pub mutability: Mutability,
-        pub type_: Box<Type>,
+        lifetime: Option<Lifetime>,
+        mutability: Mutability,
+        type_: Box<Type>,
     },
     // region, raw, other boxes, mutable
 }
@@ -1124,7 +1119,6 @@ pub enum PrimitiveType {
     F32, F64,
     Char,
     Bool,
-    Unit,
     Str,
     Slice,
     PrimitiveTuple,
@@ -1156,7 +1150,6 @@ impl PrimitiveType {
             "u32" => Some(U32),
             "u64" => Some(U64),
             "bool" => Some(Bool),
-            "unit" => Some(Unit),
             "char" => Some(Char),
             "str" => Some(Str),
             "f32" => Some(F32),
@@ -1205,17 +1198,13 @@ impl PrimitiveType {
             Str => "str",
             Bool => "bool",
             Char => "char",
-            Unit => "()",
             Slice => "slice",
             PrimitiveTuple => "tuple",
         }
     }
 
     pub fn to_url_str(&self) -> &'static str {
-        match *self {
-            Unit => "unit",
-            other => other.to_string(),
-        }
+        self.to_string()
     }
 
     /// Creates a rustdoc-specific node id for primitive types.
@@ -1230,12 +1219,10 @@ impl Clean<Type> for ast::Ty {
     fn clean(&self, cx: &DocContext) -> Type {
         use syntax::ast::*;
         match self.node {
-            TyNil => Primitive(Unit),
             TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
             TyRptr(ref l, ref m) =>
                 BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
                              type_: box m.ty.clean(cx)},
-            TyUniq(ref ty) => Unique(box ty.clean(cx)),
             TyVec(ref ty) => Vector(box ty.clean(cx)),
             TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
                                                            e.span.to_src(cx)),
@@ -1247,7 +1234,6 @@ impl Clean<Type> for ast::Ty {
             TyProc(ref c) => Proc(box c.clean(cx)),
             TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
             TyParen(ref ty) => ty.clean(cx),
-            TyBot => Bottom,
             ref x => panic!("Unimplemented type {}", x),
         }
     }
@@ -1256,7 +1242,6 @@ impl Clean<Type> for ast::Ty {
 impl Clean<Type> for ty::t {
     fn clean(&self, cx: &DocContext) -> Type {
         match ty::get(*self).sty {
-            ty::ty_nil => Primitive(Unit),
             ty::ty_bool => Primitive(Bool),
             ty::ty_char => Primitive(Char),
             ty::ty_int(ast::TyI) => Primitive(Int),
@@ -1342,7 +1327,7 @@ impl Clean<Type> for ty::t {
                 }
             }
 
-            ty::ty_unboxed_closure(..) => Primitive(Unit), // FIXME(pcwalton)
+            ty::ty_unboxed_closure(..) => Tuple(vec![]), // FIXME(pcwalton)
 
             ty::ty_infer(..) => panic!("ty_infer"),
             ty::ty_open(..) => panic!("ty_open"),
@@ -2041,7 +2026,6 @@ fn lit_to_string(lit: &ast::Lit) -> String {
         ast::LitFloat(ref f, _t) => f.get().to_string(),
         ast::LitFloatUnsuffixed(ref f) => f.get().to_string(),
         ast::LitBool(b) => b.to_string(),
-        ast::LitNil => "".to_string(),
     }
 }
 
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index fe96c9b3a9f..a7f33151547 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -393,10 +393,7 @@ impl fmt::Show for clean::Type {
                            format!("&lt;{:#}&gt;", decl.lifetimes)
                        },
                        args = decl.decl.inputs,
-                       arrow = match decl.decl.output {
-                           clean::Primitive(clean::Unit) => "".to_string(),
-                           _ => format!(" -&gt; {}", decl.decl.output),
-                       },
+                       arrow = decl.decl.output,
                        bounds = {
                            let mut ret = String::new();
                            for bound in decl.bounds.iter() {
@@ -435,10 +432,7 @@ impl fmt::Show for clean::Type {
                                ": {}",
                                m.collect::<Vec<String>>().connect(" + "))
                        },
-                       arrow = match decl.decl.output {
-                           clean::Primitive(clean::Unit) => "".to_string(),
-                           _ => format!(" -&gt; {}", decl.decl.output)
-                       })
+                       arrow = decl.decl.output)
             }
             clean::BareFunction(ref decl) => {
                 write!(f, "{}{}fn{}{}",
@@ -514,14 +508,19 @@ impl fmt::Show for clean::Arguments {
     }
 }
 
+impl fmt::Show for clean::FunctionRetTy {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            clean::Return(clean::Tuple(ref tys)) if tys.is_empty() => Ok(()),
+            clean::Return(ref ty) => write!(f, " -&gt; {}", ty),
+            clean::NoReturn => write!(f, " -&gt; !")
+        }
+    }
+}
+
 impl fmt::Show for clean::FnDecl {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "({args}){arrow}",
-               args = self.inputs,
-               arrow = match self.output {
-                   clean::Primitive(clean::Unit) => "".to_string(),
-                   _ => format!(" -&gt; {}", self.output),
-               })
+        write!(f, "({args}){arrow}", args = self.inputs, arrow = self.output)
     }
 }
 
@@ -551,12 +550,7 @@ impl<'a> fmt::Show for Method<'a> {
             }
             args.push_str(format!("{}", input.type_).as_slice());
         }
-        write!(f, "({args}){arrow}",
-               args = args,
-               arrow = match d.output {
-                   clean::Primitive(clean::Unit) => "".to_string(),
-                   _ => format!(" -&gt; {}", d.output),
-               })
+        write!(f, "({args}){arrow}", args = args, arrow = d.output)
     }
 }
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 7c5de627d08..593d5811553 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -893,7 +893,6 @@ pub enum Lit_ {
     LitInt(u64, LitIntType),
     LitFloat(InternedString, FloatTy),
     LitFloatUnsuffixed(InternedString),
-    LitNil,
     LitBool(bool),
 }
 
@@ -1086,12 +1085,6 @@ pub struct BareFnTy {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 /// The different kinds of types recognized by the compiler
 pub enum Ty_ {
-    /// The unit type (`()`)
-    TyNil,
-    /// The bottom type (`!`)
-    TyBot,
-    TyUniq(P<Ty>),
-    /// An array (`[T]`)
     TyVec(P<Ty>),
     /// A fixed length array (`[T, ..n]`)
     TyFixedLengthVec(P<Ty>, P<Expr>),
@@ -1175,8 +1168,7 @@ impl Arg {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct FnDecl {
     pub inputs: Vec<Arg>,
-    pub output: P<Ty>,
-    pub cf: RetStyle,
+    pub output: FunctionRetTy,
     pub variadic: bool
 }
 
@@ -1198,12 +1190,21 @@ impl fmt::Show for FnStyle {
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
-pub enum RetStyle {
+pub enum FunctionRetTy {
     /// Functions with return type ! that always
     /// raise an error or exit (i.e. never return to the caller)
-    NoReturn,
+    NoReturn(Span),
     /// Everything else
-    Return,
+    Return(P<Ty>),
+}
+
+impl FunctionRetTy {
+    pub fn span(&self) -> Span {
+        match *self {
+            NoReturn(span) => span,
+            Return(ref ty) => ty.span
+        }
+    }
 }
 
 /// Represents the kind of 'self' associated with a method
@@ -1292,8 +1293,8 @@ pub type Variant = Spanned<Variant_>;
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum PathListItem_ {
-    PathListIdent { pub name: Ident, pub id: NodeId },
-    PathListMod { pub id: NodeId }
+    PathListIdent { name: Ident, id: NodeId },
+    PathListMod { id: NodeId }
 }
 
 impl PathListItem_ {
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 1e2d935af00..0c7a3cf4a6c 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -248,7 +248,7 @@ impl DummyResult {
     pub fn raw_expr(sp: Span) -> P<ast::Expr> {
         P(ast::Expr {
             id: ast::DUMMY_NODE_ID,
-            node: ast::ExprLit(P(codemap::respan(sp, ast::LitNil))),
+            node: ast::ExprLit(P(codemap::respan(sp, ast::LitBool(false)))),
             span: sp,
         })
     }
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 862cbf3d7ca..ffc42b67033 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -54,11 +54,9 @@ pub trait AstBuilder {
     fn ty_ptr(&self, span: Span,
               ty: P<ast::Ty>,
               mutbl: ast::Mutability) -> P<ast::Ty>;
-    fn ty_uniq(&self, span: Span, ty: P<ast::Ty>) -> P<ast::Ty>;
 
     fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty>;
     fn ty_infer(&self, sp: Span) -> P<ast::Ty>;
-    fn ty_nil(&self) -> P<ast::Ty>;
 
     fn ty_vars(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> ;
     fn ty_vars_global(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> ;
@@ -377,9 +375,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.ty(span,
                 ast::TyPtr(self.ty_mt(ty, mutbl)))
     }
-    fn ty_uniq(&self, span: Span, ty: P<ast::Ty>) -> P<ast::Ty> {
-        self.ty(span, ast::TyUniq(ty))
-    }
 
     fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty> {
         self.ty_path(
@@ -406,14 +401,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.ty(span, ast::TyInfer)
     }
 
-    fn ty_nil(&self) -> P<ast::Ty> {
-        P(ast::Ty {
-            id: ast::DUMMY_NODE_ID,
-            node: ast::TyNil,
-            span: DUMMY_SP,
-        })
-    }
-
     fn typaram(&self,
                span: Span,
                id: ast::Ident,
@@ -809,8 +796,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.pat(span, pat)
     }
     fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
-        let pat = ast::PatTup(pats);
-        self.pat(span, pat)
+        self.pat(span, ast::PatTup(pats))
     }
 
     fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
@@ -931,11 +917,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     // FIXME unused self
-    fn fn_decl(&self, inputs: Vec<ast::Arg> , output: P<ast::Ty>) -> P<ast::FnDecl> {
+    fn fn_decl(&self, inputs: Vec<ast::Arg>, output: P<ast::Ty>) -> P<ast::FnDecl> {
         P(ast::FnDecl {
             inputs: inputs,
-            output: output,
-            cf: ast::Return,
+            output: ast::Return(output),
             variadic: false
         })
     }
diff --git a/src/libsyntax/ext/concat.rs b/src/libsyntax/ext/concat.rs
index af7cd4157ec..e2867c2fbab 100644
--- a/src/libsyntax/ext/concat.rs
+++ b/src/libsyntax/ext/concat.rs
@@ -46,7 +46,6 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
                     ast::LitInt(i, ast::UnsuffixedIntLit(ast::Minus)) => {
                         accumulator.push_str(format!("-{}", i).as_slice());
                     }
-                    ast::LitNil => {}
                     ast::LitBool(b) => {
                         accumulator.push_str(format!("{}", b).as_slice());
                     }
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index 69eb260b8c4..62f3b5d01b4 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -88,7 +88,7 @@
 //! }
 //! ```
 
-use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil};
+use ast::{MetaItem, Item, Expr, ExprRet, MutMutable};
 use codemap::Span;
 use ext::base::ExtCtxt;
 use ext::build::AstBuilder;
@@ -186,7 +186,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
             if stmts.is_empty() {
                 let ret_ok = cx.expr(trait_span,
                                      ExprRet(Some(cx.expr_ok(trait_span,
-                                                             cx.expr_lit(trait_span, LitNil)))));
+                                                             cx.expr_tuple(trait_span, vec![])))));
                 stmts.push(cx.stmt_expr(ret_ok));
             }
 
@@ -231,7 +231,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
             if stmts.len() == 0 {
                 let ret_ok = cx.expr(trait_span,
                                      ExprRet(Some(cx.expr_ok(trait_span,
-                                                             cx.expr_lit(trait_span, LitNil)))));
+                                                             cx.expr_tuple(trait_span, vec![])))));
                 stmts.push(cx.stmt_expr(ret_ok));
             }
 
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 7c32b845508..4be299994fd 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -922,7 +922,7 @@ impl<'a> MethodDef<'a> {
                 }
 
                 // Here is the pat = `(&VariantK, &VariantK, ...)`
-                let single_pat = cx.pat(sp, ast::PatTup(subpats));
+                let single_pat = cx.pat_tuple(sp, subpats);
 
                 // For the BodyK, we need to delegate to our caller,
                 // passing it an EnumMatching to indicate which case
diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs
index 1ec1e3b1224..8b46769d633 100644
--- a/src/libsyntax/ext/deriving/generic/ty.rs
+++ b/src/libsyntax/ext/deriving/generic/ty.rs
@@ -152,14 +152,9 @@ impl<'a> Ty<'a> {
                 cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
             }
             Tuple(ref fields) => {
-                let ty = if fields.is_empty() {
-                    ast::TyNil
-                } else {
-                    ast::TyTup(fields.iter()
-                                     .map(|f| f.to_ty(cx, span, self_ty, self_generics))
-                                     .collect())
-                };
-
+                let ty = ast::TyTup(fields.iter()
+                    .map(|f| f.to_ty(cx, span, self_ty, self_generics))
+                    .collect());
                 cx.ty(span, ty)
             }
         }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 87406081aae..fa69495fa42 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -159,7 +159,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
             // `_ => [<elseopt> | ()]`
             let else_arm = {
                 let pat_under = fld.cx.pat_wild(span);
-                let else_expr = elseopt.unwrap_or_else(|| fld.cx.expr_lit(span, ast::LitNil));
+                let else_expr = elseopt.unwrap_or_else(|| fld.cx.expr_tuple(span, vec![]));
                 fld.cx.arm(span, vec![pat_under], else_expr)
             };
 
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index a28f24e7663..a816b479630 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -654,7 +654,7 @@ impl<'a, 'b> Context<'a, 'b> {
         //
         // But the nested match expression is proved to perform not as well
         // as series of let's; the first approach does.
-        let pat = self.ecx.pat(self.fmtsp, ast::PatTup(pats));
+        let pat = self.ecx.pat_tuple(self.fmtsp, pats);
         let arm = self.ecx.arm(self.fmtsp, vec!(pat), body);
         let head = self.ecx.expr(self.fmtsp, ast::ExprTup(heads));
         self.ecx.expr_match(self.fmtsp, head, vec!(arm))
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index c38fea9b3d5..019d2315c1a 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -37,7 +37,7 @@ use std::slice;
 static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
     ("globs", Active),
     ("macro_rules", Active),
-    ("struct_variant", Active),
+    ("struct_variant", Accepted),
     ("asm", Active),
     ("managed_boxes", Removed),
     ("non_ascii_idents", Active),
@@ -184,19 +184,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
             }
         }
         match i.node {
-            ast::ItemEnum(ref def, _) => {
-                for variant in def.variants.iter() {
-                    match variant.node.kind {
-                        ast::StructVariantKind(..) => {
-                            self.gate_feature("struct_variant", variant.span,
-                                              "enum struct variants are \
-                                               experimental and possibly buggy");
-                        }
-                        _ => {}
-                    }
-                }
-            }
-
             ast::ItemForeignMod(ref foreign_module) => {
                 if attr::contains_name(i.attrs.as_slice(), "link_args") {
                     self.gate_feature("link_args", i.span,
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index d7c3ca8efc4..56d91282437 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -391,8 +391,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
     t.map(|Ty {id, node, span}| Ty {
         id: fld.new_id(id),
         node: match node {
-            TyNil | TyBot | TyInfer => node,
-            TyUniq(ty) => TyUniq(fld.fold_ty(ty)),
+            TyInfer => node,
             TyVec(ty) => TyVec(fld.fold_ty(ty)),
             TyPtr(mt) => TyPtr(fld.fold_mt(mt)),
             TyRptr(region, mt) => {
@@ -706,10 +705,12 @@ pub fn noop_fold_interpolated<T: Folder>(nt: token::Nonterminal, fld: &mut T)
 }
 
 pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
-    decl.map(|FnDecl {inputs, output, cf, variadic}| FnDecl {
+    decl.map(|FnDecl {inputs, output, variadic}| FnDecl {
         inputs: inputs.move_map(|x| fld.fold_arg(x)),
-        output: fld.fold_ty(output),
-        cf: cf,
+        output: match output {
+            Return(ty) => Return(fld.fold_ty(ty)),
+            NoReturn(span) => NoReturn(span)
+        },
         variadic: variadic
     })
 }
@@ -1146,10 +1147,12 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) ->
         attrs: attrs.move_map(|x| folder.fold_attribute(x)),
         node: match node {
             ForeignItemFn(fdec, generics) => {
-                ForeignItemFn(fdec.map(|FnDecl {inputs, output, cf, variadic}| FnDecl {
+                ForeignItemFn(fdec.map(|FnDecl {inputs, output, variadic}| FnDecl {
                     inputs: inputs.move_map(|a| folder.fold_arg(a)),
-                    output: folder.fold_ty(output),
-                    cf: cf,
+                    output: match output {
+                        Return(ty) => Return(folder.fold_ty(ty)),
+                        NoReturn(span) => NoReturn(span)
+                    },
                     variadic: variadic
                 }), folder.fold_generics(generics))
             }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 4881be8996a..fa10cb90f83 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -24,7 +24,7 @@
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![allow(unknown_features)]
-#![feature(macro_rules, globs, default_type_params, phase, slicing_syntax)]
+#![feature(if_let, macro_rules, globs, default_type_params, phase, slicing_syntax)]
 #![feature(quote, struct_variant, unsafe_destructor, import_shadowing)]
 
 extern crate arena;
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 51738ece80f..2810db4eadd 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -1037,10 +1037,9 @@ mod test {
                                     }),
                                         id: ast::DUMMY_NODE_ID
                                     }),
-                                output: P(ast::Ty{id: ast::DUMMY_NODE_ID,
-                                                  node: ast::TyNil,
-                                                  span:sp(15,15)}), // not sure
-                                cf: ast::Return,
+                                output: ast::Return(P(ast::Ty{id: ast::DUMMY_NODE_ID,
+                                                  node: ast::TyTup(vec![]),
+                                                  span:sp(15,15)})), // not sure
                                 variadic: false
                             }),
                                     ast::NormalFn,
diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs
index 73787763c8b..1b2ab3c235d 100644
--- a/src/libsyntax/parse/obsolete.rs
+++ b/src/libsyntax/parse/obsolete.rs
@@ -17,8 +17,8 @@ Obsolete syntax that becomes too hard to parse can be
 removed.
 */
 
-use ast::{Expr, ExprLit, LitNil};
-use codemap::{Span, respan};
+use ast::{Expr, ExprTup};
+use codemap::Span;
 use parse::parser;
 use parse::token;
 use ptr::P;
@@ -96,7 +96,7 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
     /// a placeholder expression
     fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> P<Expr> {
         self.obsolete(sp, kind);
-        self.mk_expr(sp.lo, sp.hi, ExprLit(P(respan(sp, LitNil))))
+        self.mk_expr(sp.lo, sp.hi, ExprTup(vec![]))
     }
 
     fn report(&mut self,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index db10dc1bc90..50e3483fb15 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -30,13 +30,13 @@ use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
 use ast::{Once, Many};
 use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
 use ast::{FnOnceUnboxedClosureKind};
-use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
+use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
 use ast::{Ident, NormalFn, Inherited, ImplItem, Item, Item_, ItemStatic};
 use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst};
 use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy};
 use ast::{LifetimeDef, Lit, Lit_};
 use ast::{LitBool, LitChar, LitByte, LitBinary};
-use ast::{LitNil, LitStr, LitInt, Local, LocalLet};
+use ast::{LitStr, LitInt, Local, LocalLet};
 use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchNormal};
 use ast::{Method, MutTy, BiMul, Mutability};
 use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot};
@@ -44,18 +44,18 @@ use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct};
 use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
 use ast::{PolyTraitRef};
 use ast::{QPath, RequiredMethod};
-use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
+use ast::{Return, BiShl, BiShr, Stmt, StmtDecl};
 use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
 use ast::{StructVariantKind, BiSub};
 use ast::StrStyle;
 use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
 use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef};
 use ast::{TtDelimited, TtSequence, TtToken};
-use ast::{TupleVariantKind, Ty, Ty_, TyBot};
+use ast::{TupleVariantKind, Ty, Ty_};
 use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
 use ast::{TyTypeof, TyInfer, TypeMethod};
-use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
-use ast::{TyRptr, TyTup, TyU32, TyUniq, TyVec, UnUniq};
+use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
+use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
 use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
 use ast::{UnnamedField, UnsafeBlock};
 use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
@@ -1066,11 +1066,10 @@ impl<'a> Parser<'a> {
         self.expect_keyword(keywords::Fn);
         let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
         let (inputs, variadic) = self.parse_fn_args(false, true);
-        let (ret_style, ret_ty) = self.parse_ret_ty();
+        let ret_ty = self.parse_ret_ty();
         let decl = P(FnDecl {
             inputs: inputs,
             output: ret_ty,
-            cf: ret_style,
             variadic: variadic
         });
         TyBareFn(P(BareFnTy {
@@ -1100,11 +1099,10 @@ impl<'a> Parser<'a> {
         let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
         let (inputs, variadic) = self.parse_fn_args(false, false);
         let bounds = self.parse_colon_then_ty_param_bounds();
-        let (ret_style, ret_ty) = self.parse_ret_ty();
+        let ret_ty = self.parse_ret_ty();
         let decl = P(FnDecl {
             inputs: inputs,
             output: ret_ty,
-            cf: ret_style,
             variadic: variadic
         });
         TyProc(P(ClosureTy {
@@ -1200,11 +1198,10 @@ impl<'a> Parser<'a> {
 
         let bounds = self.parse_colon_then_ty_param_bounds();
 
-        let (return_style, output) = self.parse_ret_ty();
+        let output = self.parse_ret_ty();
         let decl = P(FnDecl {
             inputs: inputs,
             output: output,
-            cf: return_style,
             variadic: false
         });
 
@@ -1384,31 +1381,20 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse optional return type [ -> TY ] in function decl
-    pub fn parse_ret_ty(&mut self) -> (RetStyle, P<Ty>) {
-        return if self.eat(&token::RArrow) {
-            let lo = self.span.lo;
+    pub fn parse_ret_ty(&mut self) -> FunctionRetTy {
+        if self.eat(&token::RArrow) {
             if self.eat(&token::Not) {
-                (
-                    NoReturn,
-                    P(Ty {
-                        id: ast::DUMMY_NODE_ID,
-                        node: TyBot,
-                        span: mk_sp(lo, self.last_span.hi)
-                    })
-                )
+                NoReturn(self.span)
             } else {
-                (Return, self.parse_ty(true))
+                Return(self.parse_ty(true))
             }
         } else {
             let pos = self.span.lo;
-            (
-                Return,
-                P(Ty {
-                    id: ast::DUMMY_NODE_ID,
-                    node: TyNil,
-                    span: mk_sp(pos, pos),
-                })
-            )
+            Return(P(Ty {
+                id: ast::DUMMY_NODE_ID,
+                node: TyTup(vec![]),
+                span: mk_sp(pos, pos),
+            }))
         }
     }
 
@@ -1423,34 +1409,29 @@ impl<'a> Parser<'a> {
 
         let t = if self.token == token::OpenDelim(token::Paren) {
             self.bump();
-            if self.token == token::CloseDelim(token::Paren) {
-                self.bump();
-                TyNil
-            } else {
-                // (t) is a parenthesized ty
-                // (t,) is the type of a tuple with only one field,
-                // of type t
-                let mut ts = vec!(self.parse_ty(true));
-                let mut one_tuple = false;
-                while self.token == token::Comma {
-                    self.bump();
-                    if self.token != token::CloseDelim(token::Paren) {
-                        ts.push(self.parse_ty(true));
-                    }
-                    else {
-                        one_tuple = true;
-                    }
-                }
 
-                if ts.len() == 1 && !one_tuple {
-                    self.expect(&token::CloseDelim(token::Paren));
-                    TyParen(ts.into_iter().nth(0).unwrap())
+            // (t) is a parenthesized ty
+            // (t,) is the type of a tuple with only one field,
+            // of type t
+            let mut ts = vec![];
+            let mut last_comma = false;
+            while self.token != token::CloseDelim(token::Paren) {
+                ts.push(self.parse_ty(true));
+                if self.token == token::Comma {
+                    last_comma = true;
+                    self.bump();
                 } else {
-                    let t = TyTup(ts);
-                    self.expect(&token::CloseDelim(token::Paren));
-                    t
+                    last_comma = false;
+                    break;
                 }
             }
+
+            self.expect(&token::CloseDelim(token::Paren));
+            if ts.len() == 1 && !last_comma {
+                TyParen(ts.into_iter().nth(0).unwrap())
+            } else {
+                TyTup(ts)
+            }
         } else if self.token == token::Tilde {
             // OWNED POINTER
             self.bump();
@@ -1459,7 +1440,7 @@ impl<'a> Parser<'a> {
                 token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector),
                 _ => self.obsolete(last_span, ObsoleteOwnedType)
             }
-            TyUniq(self.parse_ty(false))
+            TyTup(vec![self.parse_ty(false)])
         } else if self.token == token::BinOp(token::Star) {
             // STAR POINTER (bare pointer?)
             self.bump();
@@ -1662,10 +1643,6 @@ impl<'a> Parser<'a> {
                 LitBinary(parse::binary_lit(i.as_str())),
             token::LitBinaryRaw(i, _) =>
                 LitBinary(Rc::new(i.as_str().as_bytes().iter().map(|&x| x).collect())),
-            token::OpenDelim(token::Paren) => {
-                self.expect(&token::CloseDelim(token::Paren));
-                LitNil
-            },
             _ => { self.unexpected_last(tok); }
         }
     }
@@ -2126,33 +2103,29 @@ impl<'a> Parser<'a> {
         match self.token {
             token::OpenDelim(token::Paren) => {
                 self.bump();
+
                 // (e) is parenthesized e
                 // (e,) is a tuple with only one field, e
+                let mut es = vec![];
                 let mut trailing_comma = false;
-                if self.token == token::CloseDelim(token::Paren) {
-                    hi = self.span.hi;
-                    self.bump();
-                    let lit = P(spanned(lo, hi, LitNil));
-                    return self.mk_expr(lo, hi, ExprLit(lit));
-                }
-                let mut es = vec!(self.parse_expr());
-                self.commit_expr(&**es.last().unwrap(), &[],
-                                 &[token::Comma, token::CloseDelim(token::Paren)]);
-                while self.token == token::Comma {
-                    self.bump();
-                    if self.token != token::CloseDelim(token::Paren) {
-                        es.push(self.parse_expr());
-                        self.commit_expr(&**es.last().unwrap(), &[],
-                                         &[token::Comma, token::CloseDelim(token::Paren)]);
-                    } else {
+                while self.token != token::CloseDelim(token::Paren) {
+                    es.push(self.parse_expr());
+                    self.commit_expr(&**es.last().unwrap(), &[],
+                                     &[token::Comma, token::CloseDelim(token::Paren)]);
+                    if self.token == token::Comma {
                         trailing_comma = true;
+
+                        self.bump();
+                    } else {
+                        trailing_comma = false;
+                        break;
                     }
                 }
-                hi = self.span.hi;
-                self.commit_expr_expecting(&**es.last().unwrap(), token::CloseDelim(token::Paren));
+                self.bump();
 
+                hi = self.span.hi;
                 return if es.len() == 1 && !trailing_comma {
-                   self.mk_expr(lo, hi, ExprParen(es.into_iter().nth(0).unwrap()))
+                    self.mk_expr(lo, hi, ExprParen(es.into_iter().nth(0).unwrap()))
                 } else {
                     self.mk_expr(lo, hi, ExprTup(es))
                 }
@@ -3293,13 +3266,8 @@ impl<'a> Parser<'a> {
             // parse (pat,pat,pat,...) as tuple
             self.bump();
             if self.token == token::CloseDelim(token::Paren) {
-                hi = self.span.hi;
                 self.bump();
-                let lit = P(codemap::Spanned {
-                    node: LitNil,
-                    span: mk_sp(lo, hi)});
-                let expr = self.mk_expr(lo, hi, ExprLit(lit));
-                pat = PatLit(expr);
+                pat = PatTup(vec![]);
             } else {
                 let mut fields = vec!(self.parse_pat());
                 if self.look_ahead(1, |t| *t != token::CloseDelim(token::Paren)) {
@@ -4137,12 +4105,11 @@ impl<'a> Parser<'a> {
     pub fn parse_fn_decl(&mut self, allow_variadic: bool) -> P<FnDecl> {
 
         let (args, variadic) = self.parse_fn_args(true, allow_variadic);
-        let (ret_style, ret_ty) = self.parse_ret_ty();
+        let ret_ty = self.parse_ret_ty();
 
         P(FnDecl {
             inputs: args,
             output: ret_ty,
-            cf: ret_style,
             variadic: variadic
         })
     }
@@ -4337,12 +4304,11 @@ impl<'a> Parser<'a> {
 
         let hi = self.span.hi;
 
-        let (ret_style, ret_ty) = self.parse_ret_ty();
+        let ret_ty = self.parse_ret_ty();
 
         let fn_decl = P(FnDecl {
             inputs: fn_inputs,
             output: ret_ty,
-            cf: ret_style,
             variadic: false
         });
 
@@ -4368,10 +4334,10 @@ impl<'a> Parser<'a> {
                 (optional_unboxed_closure_kind, args)
             }
         };
-        let (style, output) = if self.token == token::RArrow {
+        let output = if self.token == token::RArrow {
             self.parse_ret_ty()
         } else {
-            (Return, P(Ty {
+            Return(P(Ty {
                 id: ast::DUMMY_NODE_ID,
                 node: TyInfer,
                 span: self.span,
@@ -4381,7 +4347,6 @@ impl<'a> Parser<'a> {
         (P(FnDecl {
             inputs: inputs_captures,
             output: output,
-            cf: style,
             variadic: false
         }), optional_unboxed_closure_kind)
     }
@@ -4394,10 +4359,10 @@ impl<'a> Parser<'a> {
                                      seq_sep_trailing_allowed(token::Comma),
                                      |p| p.parse_fn_block_arg());
 
-        let (style, output) = if self.token == token::RArrow {
+        let output = if self.token == token::RArrow {
             self.parse_ret_ty()
         } else {
-            (Return, P(Ty {
+            Return(P(Ty {
                 id: ast::DUMMY_NODE_ID,
                 node: TyInfer,
                 span: self.span,
@@ -4407,7 +4372,6 @@ impl<'a> Parser<'a> {
         P(FnDecl {
             inputs: inputs,
             output: output,
-            cf: style,
             variadic: false
         })
     }
@@ -4648,7 +4612,7 @@ impl<'a> Parser<'a> {
             is_tuple_like = false;
             fields = Vec::new();
             while self.token != token::CloseDelim(token::Brace) {
-                fields.push(self.parse_struct_decl_field());
+                fields.push(self.parse_struct_decl_field(true));
             }
             if fields.len() == 0 {
                 self.fatal(format!("unit-like struct definition should be \
@@ -4725,12 +4689,16 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse an element of a struct definition
-    fn parse_struct_decl_field(&mut self) -> StructField {
+    fn parse_struct_decl_field(&mut self, allow_pub: bool) -> StructField {
 
         let attrs = self.parse_outer_attributes();
 
         if self.eat_keyword(keywords::Pub) {
-           return self.parse_single_struct_field(Public, attrs);
+            if !allow_pub {
+                let span = self.last_span;
+                self.span_err(span, "`pub` is not allowed here");
+            }
+            return self.parse_single_struct_field(Public, attrs);
         }
 
         return self.parse_single_struct_field(Inherited, attrs);
@@ -5178,7 +5146,7 @@ impl<'a> Parser<'a> {
     fn parse_struct_def(&mut self) -> P<StructDef> {
         let mut fields: Vec<StructField> = Vec::new();
         while self.token != token::CloseDelim(token::Brace) {
-            fields.push(self.parse_struct_decl_field());
+            fields.push(self.parse_struct_decl_field(false));
         }
         self.bump();
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index c1515a36bec..7025555ab40 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -645,12 +645,6 @@ impl<'a> State<'a> {
         try!(self.maybe_print_comment(ty.span.lo));
         try!(self.ibox(0u));
         match ty.node {
-            ast::TyNil => try!(word(&mut self.s, "()")),
-            ast::TyBot => try!(word(&mut self.s, "!")),
-            ast::TyUniq(ref ty) => {
-                try!(word(&mut self.s, "~"));
-                try!(self.print_type(&**ty));
-            }
             ast::TyVec(ref ty) => {
                 try!(word(&mut self.s, "["));
                 try!(self.print_type(&**ty));
@@ -2307,15 +2301,7 @@ impl<'a> State<'a> {
         }
         try!(self.pclose());
 
-        try!(self.maybe_print_comment(decl.output.span.lo));
-        match decl.output.node {
-            ast::TyNil => Ok(()),
-            _ => {
-                try!(self.space_if_not_bol());
-                try!(self.word_space("->"));
-                self.print_type(&*decl.output)
-            }
-        }
+        self.print_fn_output(decl)
     }
 
     pub fn print_fn_block_args(
@@ -2333,16 +2319,24 @@ impl<'a> State<'a> {
         try!(self.print_fn_args(decl, None));
         try!(word(&mut self.s, "|"));
 
-        match decl.output.node {
-            ast::TyInfer => {}
-            _ => {
-                try!(self.space_if_not_bol());
-                try!(self.word_space("->"));
-                try!(self.print_type(&*decl.output));
+        if let ast::Return(ref ty) = decl.output {
+            if ty.node == ast::TyInfer {
+                return self.maybe_print_comment(ty.span.lo);
             }
         }
 
-        self.maybe_print_comment(decl.output.span.lo)
+        try!(self.space_if_not_bol());
+        try!(self.word_space("->"));
+        match decl.output {
+            ast::Return(ref ty) => {
+                try!(self.print_type(&**ty));
+                self.maybe_print_comment(ty.span.lo)
+            }
+            ast::NoReturn(span) => {
+                try!(self.word_nbsp("!"));
+                self.maybe_print_comment(span.lo)
+            }
+        }
     }
 
     pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureClause)
@@ -2359,16 +2353,24 @@ impl<'a> State<'a> {
         try!(self.print_fn_args(decl, None));
         try!(word(&mut self.s, ")"));
 
-        match decl.output.node {
-            ast::TyInfer => {}
-            _ => {
-                try!(self.space_if_not_bol());
-                try!(self.word_space("->"));
-                try!(self.print_type(&*decl.output));
+        if let ast::Return(ref ty) = decl.output {
+            if ty.node == ast::TyInfer {
+                return self.maybe_print_comment(ty.span.lo);
             }
         }
 
-        self.maybe_print_comment(decl.output.span.lo)
+        try!(self.space_if_not_bol());
+        try!(self.word_space("->"));
+        match decl.output {
+            ast::Return(ref ty) => {
+                try!(self.print_type(&**ty));
+                self.maybe_print_comment(ty.span.lo)
+            }
+            ast::NoReturn(span) => {
+                try!(self.word_nbsp("!"));
+                self.maybe_print_comment(span.lo)
+            }
+        }
     }
 
     pub fn print_bounds(&mut self,
@@ -2627,20 +2629,30 @@ impl<'a> State<'a> {
     }
 
     pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
-        match decl.output.node {
-            ast::TyNil => Ok(()),
-            _ => {
-                try!(self.space_if_not_bol());
-                try!(self.ibox(indent_unit));
-                try!(self.word_space("->"));
-                if decl.cf == ast::NoReturn {
-                    try!(self.word_nbsp("!"));
-                } else {
-                    try!(self.print_type(&*decl.output));
+        if let ast::Return(ref ty) = decl.output {
+            match ty.node {
+                ast::TyTup(ref tys) if tys.is_empty() => {
+                    return self.maybe_print_comment(ty.span.lo);
                 }
-                self.end()
+                _ => ()
             }
         }
+
+        try!(self.space_if_not_bol());
+        try!(self.ibox(indent_unit));
+        try!(self.word_space("->"));
+        match decl.output {
+            ast::NoReturn(_) =>
+                try!(self.word_nbsp("!")),
+            ast::Return(ref ty) =>
+                try!(self.print_type(&**ty))
+        }
+        try!(self.end());
+
+        match decl.output {
+            ast::Return(ref output) => self.maybe_print_comment(output.span.lo),
+            _ => Ok(())
+        }
     }
 
     pub fn print_ty_fn(&mut self,
@@ -2700,8 +2712,6 @@ impl<'a> State<'a> {
 
         try!(self.print_bounds(":", bounds));
 
-        try!(self.maybe_print_comment(decl.output.span.lo));
-
         try!(self.print_fn_output(decl));
 
         match generics {
@@ -2807,7 +2817,6 @@ impl<'a> State<'a> {
                          ast_util::float_ty_to_string(t).as_slice()).as_slice())
             }
             ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, f.get()),
-            ast::LitNil => word(&mut self.s, "()"),
             ast::LitBool(val) => {
                 if val { word(&mut self.s, "true") } else { word(&mut self.s, "false") }
             }
@@ -3003,10 +3012,9 @@ mod test {
 
         let decl = ast::FnDecl {
             inputs: Vec::new(),
-            output: P(ast::Ty {id: 0,
-                               node: ast::TyNil,
-                               span: codemap::DUMMY_SP}),
-            cf: ast::Return,
+            output: ast::Return(P(ast::Ty {id: 0,
+                               node: ast::TyTup(vec![]),
+                               span: codemap::DUMMY_SP})),
             variadic: false
         };
         let generics = ast_util::empty_generics();
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 29637e88dd5..8b6d752d484 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -289,9 +289,12 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
     fn has_test_signature(i: &ast::Item) -> HasTestSignature {
         match &i.node {
           &ast::ItemFn(ref decl, _, _, ref generics, _) => {
-            let no_output = match decl.output.node {
-                ast::TyNil => true,
-                _ => false,
+            let no_output = match decl.output {
+                ast::Return(ref ret_ty) => match ret_ty.node {
+                    ast::TyTup(ref tys) if tys.is_empty() => true,
+                    _ => false,
+                },
+                ast::NoReturn(_) => false
             };
             if decl.inputs.is_empty()
                    && no_output
@@ -325,9 +328,12 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
         match i.node {
             ast::ItemFn(ref decl, _, _, ref generics, _) => {
                 let input_cnt = decl.inputs.len();
-                let no_output = match decl.output.node {
-                    ast::TyNil => true,
-                    _ => false
+                let no_output = match decl.output {
+                    ast::Return(ref ret_ty) => match ret_ty.node {
+                        ast::TyTup(ref tys) if tys.is_empty() => true,
+                        _ => false,
+                    },
+                    ast::NoReturn(_) => false
                 };
                 let tparm_cnt = generics.ty_params.len();
                 // NB: inadequate check, but we're running
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 1b1d1e9cace..f30a4325eb8 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -341,7 +341,7 @@ pub fn skip_ty<'v, V: Visitor<'v>>(_: &mut V, _: &'v Ty) {
 
 pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
     match typ.node {
-        TyUniq(ref ty) | TyVec(ref ty) | TyParen(ref ty) => {
+        TyVec(ref ty) | TyParen(ref ty) => {
             visitor.visit_ty(&**ty)
         }
         TyPtr(ref mutable_type) => {
@@ -360,7 +360,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             for argument in function_declaration.decl.inputs.iter() {
                 visitor.visit_ty(&*argument.ty)
             }
-            visitor.visit_ty(&*function_declaration.decl.output);
+            walk_fn_ret_ty(visitor, &function_declaration.decl.output);
             walk_ty_param_bounds(visitor, &function_declaration.bounds);
             walk_lifetime_decls(visitor, &function_declaration.lifetimes);
         }
@@ -368,7 +368,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             for argument in function_declaration.decl.inputs.iter() {
                 visitor.visit_ty(&*argument.ty)
             }
-            visitor.visit_ty(&*function_declaration.decl.output);
+            walk_fn_ret_ty(visitor, &function_declaration.decl.output);
             walk_ty_param_bounds(visitor, &function_declaration.bounds);
             walk_lifetime_decls(visitor, &function_declaration.lifetimes);
         }
@@ -376,7 +376,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             for argument in function_declaration.decl.inputs.iter() {
                 visitor.visit_ty(&*argument.ty)
             }
-            visitor.visit_ty(&*function_declaration.decl.output);
+            walk_fn_ret_ty(visitor, &function_declaration.decl.output);
             walk_lifetime_decls(visitor, &function_declaration.lifetimes);
         }
         TyPath(ref path, ref opt_bounds, id) => {
@@ -403,7 +403,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
         TyTypeof(ref expression) => {
             visitor.visit_expr(&**expression)
         }
-        TyNil | TyBot | TyInfer => {}
+        TyInfer => {}
     }
 }
 
@@ -538,12 +538,18 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics
     }
 }
 
+pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) {
+    if let Return(ref output_ty) = *ret_ty {
+        visitor.visit_ty(&**output_ty)
+    }
+}
+
 pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
     for argument in function_declaration.inputs.iter() {
         visitor.visit_pat(&*argument.pat);
         visitor.visit_ty(&*argument.ty)
     }
-    visitor.visit_ty(&*function_declaration.output)
+    walk_fn_ret_ty(visitor, &function_declaration.output)
 }
 
 // Note: there is no visit_method() method in the visitor, instead override
@@ -601,7 +607,7 @@ pub fn walk_ty_method<'v, V: Visitor<'v>>(visitor: &mut V, method_type: &'v Type
         visitor.visit_ty(&*argument_type.ty)
     }
     visitor.visit_generics(&method_type.generics);
-    visitor.visit_ty(&*method_type.decl.output);
+    walk_fn_ret_ty(visitor, &method_type.decl.output);
     for attr in method_type.attrs.iter() {
         visitor.visit_attribute(attr);
     }
diff --git a/src/test/compile-fail/deriving-primitive.rs b/src/test/compile-fail/deriving-primitive.rs
index 7d8741c98e2..1af0193ca47 100644
--- a/src/test/compile-fail/deriving-primitive.rs
+++ b/src/test/compile-fail/deriving-primitive.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(struct_variant)]
-
 use std::num::FromPrimitive;
 use std::int;
 
diff --git a/src/test/compile-fail/deriving-span-Clone-enum-struct-variant.rs b/src/test/compile-fail/deriving-span-Clone-enum-struct-variant.rs
index 58a9c72b8b1..1abafb84dd2 100644
--- a/src/test/compile-fail/deriving-span-Clone-enum-struct-variant.rs
+++ b/src/test/compile-fail/deriving-span-Clone-enum-struct-variant.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Clone-enum.rs b/src/test/compile-fail/deriving-span-Clone-enum.rs
index cf8345dbe7b..50badaeea00 100644
--- a/src/test/compile-fail/deriving-span-Clone-enum.rs
+++ b/src/test/compile-fail/deriving-span-Clone-enum.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Clone-struct.rs b/src/test/compile-fail/deriving-span-Clone-struct.rs
index cd53f5a1e8f..49530afec05 100644
--- a/src/test/compile-fail/deriving-span-Clone-struct.rs
+++ b/src/test/compile-fail/deriving-span-Clone-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Clone-tuple-struct.rs b/src/test/compile-fail/deriving-span-Clone-tuple-struct.rs
index 95798af49b2..27e281bb220 100644
--- a/src/test/compile-fail/deriving-span-Clone-tuple-struct.rs
+++ b/src/test/compile-fail/deriving-span-Clone-tuple-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Default-struct.rs b/src/test/compile-fail/deriving-span-Default-struct.rs
index 1da88f2e257..a75d909c06d 100644
--- a/src/test/compile-fail/deriving-span-Default-struct.rs
+++ b/src/test/compile-fail/deriving-span-Default-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Default-tuple-struct.rs b/src/test/compile-fail/deriving-span-Default-tuple-struct.rs
index cf0d9fb7443..8df6acd2704 100644
--- a/src/test/compile-fail/deriving-span-Default-tuple-struct.rs
+++ b/src/test/compile-fail/deriving-span-Default-tuple-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Hash-enum-struct-variant.rs b/src/test/compile-fail/deriving-span-Hash-enum-struct-variant.rs
index 49b4840ff8e..fb94799caba 100644
--- a/src/test/compile-fail/deriving-span-Hash-enum-struct-variant.rs
+++ b/src/test/compile-fail/deriving-span-Hash-enum-struct-variant.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Hash-enum.rs b/src/test/compile-fail/deriving-span-Hash-enum.rs
index 653dabfbc13..d4100badcdb 100644
--- a/src/test/compile-fail/deriving-span-Hash-enum.rs
+++ b/src/test/compile-fail/deriving-span-Hash-enum.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Hash-struct.rs b/src/test/compile-fail/deriving-span-Hash-struct.rs
index 46234f6e724..8b0ec01283c 100644
--- a/src/test/compile-fail/deriving-span-Hash-struct.rs
+++ b/src/test/compile-fail/deriving-span-Hash-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Hash-tuple-struct.rs b/src/test/compile-fail/deriving-span-Hash-tuple-struct.rs
index 5dbf4a0376a..8ed8350e557 100644
--- a/src/test/compile-fail/deriving-span-Hash-tuple-struct.rs
+++ b/src/test/compile-fail/deriving-span-Hash-tuple-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-PartialEq-enum-struct-variant.rs b/src/test/compile-fail/deriving-span-PartialEq-enum-struct-variant.rs
index 566585aa065..f9ce978a057 100644
--- a/src/test/compile-fail/deriving-span-PartialEq-enum-struct-variant.rs
+++ b/src/test/compile-fail/deriving-span-PartialEq-enum-struct-variant.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-PartialEq-enum.rs b/src/test/compile-fail/deriving-span-PartialEq-enum.rs
index 8a9771a0509..7756e9bfbb6 100644
--- a/src/test/compile-fail/deriving-span-PartialEq-enum.rs
+++ b/src/test/compile-fail/deriving-span-PartialEq-enum.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-PartialEq-struct.rs b/src/test/compile-fail/deriving-span-PartialEq-struct.rs
index de39e9bacd5..43685a5b0ef 100644
--- a/src/test/compile-fail/deriving-span-PartialEq-struct.rs
+++ b/src/test/compile-fail/deriving-span-PartialEq-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-PartialEq-tuple-struct.rs b/src/test/compile-fail/deriving-span-PartialEq-tuple-struct.rs
index 101461e39b7..b84b8b4a658 100644
--- a/src/test/compile-fail/deriving-span-PartialEq-tuple-struct.rs
+++ b/src/test/compile-fail/deriving-span-PartialEq-tuple-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-PartialOrd-enum-struct-variant.rs b/src/test/compile-fail/deriving-span-PartialOrd-enum-struct-variant.rs
index dd6c11d2b39..810f0f350f3 100644
--- a/src/test/compile-fail/deriving-span-PartialOrd-enum-struct-variant.rs
+++ b/src/test/compile-fail/deriving-span-PartialOrd-enum-struct-variant.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-PartialOrd-enum.rs b/src/test/compile-fail/deriving-span-PartialOrd-enum.rs
index 1b3d73a6f8b..7ae2bbf8eb5 100644
--- a/src/test/compile-fail/deriving-span-PartialOrd-enum.rs
+++ b/src/test/compile-fail/deriving-span-PartialOrd-enum.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-PartialOrd-struct.rs b/src/test/compile-fail/deriving-span-PartialOrd-struct.rs
index 2ef3b4dfe8a..c5b008da884 100644
--- a/src/test/compile-fail/deriving-span-PartialOrd-struct.rs
+++ b/src/test/compile-fail/deriving-span-PartialOrd-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-PartialOrd-tuple-struct.rs b/src/test/compile-fail/deriving-span-PartialOrd-tuple-struct.rs
index 303896737dc..f282943bba3 100644
--- a/src/test/compile-fail/deriving-span-PartialOrd-tuple-struct.rs
+++ b/src/test/compile-fail/deriving-span-PartialOrd-tuple-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-Rand-enum-struct-variant.rs b/src/test/compile-fail/deriving-span-Rand-enum-struct-variant.rs
index 79c38dcb4cc..c44abc2313a 100644
--- a/src/test/compile-fail/deriving-span-Rand-enum-struct-variant.rs
+++ b/src/test/compile-fail/deriving-span-Rand-enum-struct-variant.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Rand-enum.rs b/src/test/compile-fail/deriving-span-Rand-enum.rs
index 1e153a772c7..fc03b99983d 100644
--- a/src/test/compile-fail/deriving-span-Rand-enum.rs
+++ b/src/test/compile-fail/deriving-span-Rand-enum.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Rand-struct.rs b/src/test/compile-fail/deriving-span-Rand-struct.rs
index 2c223918773..36e1e521393 100644
--- a/src/test/compile-fail/deriving-span-Rand-struct.rs
+++ b/src/test/compile-fail/deriving-span-Rand-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Rand-tuple-struct.rs b/src/test/compile-fail/deriving-span-Rand-tuple-struct.rs
index 5d5a1372c13..ffa26061833 100644
--- a/src/test/compile-fail/deriving-span-Rand-tuple-struct.rs
+++ b/src/test/compile-fail/deriving-span-Rand-tuple-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Show-enum-struct-variant.rs b/src/test/compile-fail/deriving-span-Show-enum-struct-variant.rs
index 93f53dc73f7..fa1cfc3de5b 100644
--- a/src/test/compile-fail/deriving-span-Show-enum-struct-variant.rs
+++ b/src/test/compile-fail/deriving-span-Show-enum-struct-variant.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Show-enum.rs b/src/test/compile-fail/deriving-span-Show-enum.rs
index e61a62c2f6d..9b1dccf7df5 100644
--- a/src/test/compile-fail/deriving-span-Show-enum.rs
+++ b/src/test/compile-fail/deriving-span-Show-enum.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Show-struct.rs b/src/test/compile-fail/deriving-span-Show-struct.rs
index 3a48b3334b7..8acb6875d53 100644
--- a/src/test/compile-fail/deriving-span-Show-struct.rs
+++ b/src/test/compile-fail/deriving-span-Show-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Show-tuple-struct.rs b/src/test/compile-fail/deriving-span-Show-tuple-struct.rs
index 54806f322b3..bcbced125ef 100644
--- a/src/test/compile-fail/deriving-span-Show-tuple-struct.rs
+++ b/src/test/compile-fail/deriving-span-Show-tuple-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-TotalEq-enum-struct-variant.rs b/src/test/compile-fail/deriving-span-TotalEq-enum-struct-variant.rs
index 964e7d8c811..25add55ae4b 100644
--- a/src/test/compile-fail/deriving-span-TotalEq-enum-struct-variant.rs
+++ b/src/test/compile-fail/deriving-span-TotalEq-enum-struct-variant.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-TotalEq-enum.rs b/src/test/compile-fail/deriving-span-TotalEq-enum.rs
index 96e87ca2006..e58121f2cb0 100644
--- a/src/test/compile-fail/deriving-span-TotalEq-enum.rs
+++ b/src/test/compile-fail/deriving-span-TotalEq-enum.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-TotalEq-struct.rs b/src/test/compile-fail/deriving-span-TotalEq-struct.rs
index 784c766c057..0637c6e305c 100644
--- a/src/test/compile-fail/deriving-span-TotalEq-struct.rs
+++ b/src/test/compile-fail/deriving-span-TotalEq-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-TotalEq-tuple-struct.rs b/src/test/compile-fail/deriving-span-TotalEq-tuple-struct.rs
index 3dcff5f80ce..3a2cbb11f53 100644
--- a/src/test/compile-fail/deriving-span-TotalEq-tuple-struct.rs
+++ b/src/test/compile-fail/deriving-span-TotalEq-tuple-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-TotalOrd-enum-struct-variant.rs b/src/test/compile-fail/deriving-span-TotalOrd-enum-struct-variant.rs
index c16e64829dd..3b4f4e1080d 100644
--- a/src/test/compile-fail/deriving-span-TotalOrd-enum-struct-variant.rs
+++ b/src/test/compile-fail/deriving-span-TotalOrd-enum-struct-variant.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(Eq,PartialOrd,PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-TotalOrd-enum.rs b/src/test/compile-fail/deriving-span-TotalOrd-enum.rs
index 4b3f0ce52c7..02a55fdfbb2 100644
--- a/src/test/compile-fail/deriving-span-TotalOrd-enum.rs
+++ b/src/test/compile-fail/deriving-span-TotalOrd-enum.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(Eq,PartialOrd,PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-TotalOrd-struct.rs b/src/test/compile-fail/deriving-span-TotalOrd-struct.rs
index 56d62742378..7cf3ad57f47 100644
--- a/src/test/compile-fail/deriving-span-TotalOrd-struct.rs
+++ b/src/test/compile-fail/deriving-span-TotalOrd-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(Eq,PartialOrd,PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-TotalOrd-tuple-struct.rs b/src/test/compile-fail/deriving-span-TotalOrd-tuple-struct.rs
index 2330fdd8b89..7b8d1d3ecd0 100644
--- a/src/test/compile-fail/deriving-span-TotalOrd-tuple-struct.rs
+++ b/src/test/compile-fail/deriving-span-TotalOrd-tuple-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 #[deriving(Eq,PartialOrd,PartialEq)]
diff --git a/src/test/compile-fail/deriving-span-Zero-struct.rs b/src/test/compile-fail/deriving-span-Zero-struct.rs
index fb7759c6032..302fecd518b 100644
--- a/src/test/compile-fail/deriving-span-Zero-struct.rs
+++ b/src/test/compile-fail/deriving-span-Zero-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/deriving-span-Zero-tuple-struct.rs b/src/test/compile-fail/deriving-span-Zero-tuple-struct.rs
index 193e4b5c6b2..05b81ce3251 100644
--- a/src/test/compile-fail/deriving-span-Zero-tuple-struct.rs
+++ b/src/test/compile-fail/deriving-span-Zero-tuple-struct.rs
@@ -10,7 +10,6 @@
 
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
 
-#![feature(struct_variant)]
 extern crate rand;
 
 
diff --git a/src/test/compile-fail/dup-struct-enum-struct-variant.rs b/src/test/compile-fail/dup-struct-enum-struct-variant.rs
index 47b576b2b85..7ea114605ce 100644
--- a/src/test/compile-fail/dup-struct-enum-struct-variant.rs
+++ b/src/test/compile-fail/dup-struct-enum-struct-variant.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(struct_variant)]
-
 enum Foo { C { a: int, b: int } }
 struct C { a: int, b: int }         //~ ERROR error: duplicate definition of type or module `C`
 
diff --git a/src/test/compile-fail/gated-non-ascii-idents.rs b/src/test/compile-fail/gated-non-ascii-idents.rs
index 0634ba183a8..4cbb61d9853 100644
--- a/src/test/compile-fail/gated-non-ascii-idents.rs
+++ b/src/test/compile-fail/gated-non-ascii-idents.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(struct_variant)]
-
 extern crate bäz; //~ ERROR non-ascii idents
 
 use föö::bar; //~ ERROR non-ascii idents
diff --git a/src/test/compile-fail/issue-13624.rs b/src/test/compile-fail/issue-13624.rs
index 0c103515981..5b9ff06e9c9 100644
--- a/src/test/compile-fail/issue-13624.rs
+++ b/src/test/compile-fail/issue-13624.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(struct_variant)]
-
 mod a {
   pub enum Enum {
     EnumStructVariant { x: u8, y: u8, z: u8 }
diff --git a/src/test/compile-fail/issue-16939.rs b/src/test/compile-fail/issue-16939.rs
index 8e7a2a9db3d..e7d3d15e5a9 100644
--- a/src/test/compile-fail/issue-16939.rs
+++ b/src/test/compile-fail/issue-16939.rs
@@ -14,7 +14,7 @@
 // wrong arity.
 
 fn _foo<F: Fn()> (f: F) {
-    |t| f(t); //~ ERROR E0058
+    |t| f(t); //~ ERROR E0057
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-18252.rs b/src/test/compile-fail/issue-18252.rs
index c884f02892f..930e96f170e 100644
--- a/src/test/compile-fail/issue-18252.rs
+++ b/src/test/compile-fail/issue-18252.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(struct_variant)]
-
 enum Foo {
     Variant { x: uint }
 }
diff --git a/src/test/compile-fail/lint-dead-code-4.rs b/src/test/compile-fail/lint-dead-code-4.rs
index a698bf61f58..7c3242a6a25 100644
--- a/src/test/compile-fail/lint-dead-code-4.rs
+++ b/src/test/compile-fail/lint-dead-code-4.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(struct_variant)]
 #![allow(unused_variables)]
 #![allow(non_camel_case_types)]
 #![deny(dead_code)]
diff --git a/src/test/compile-fail/lint-dead-code-5.rs b/src/test/compile-fail/lint-dead-code-5.rs
index 1f0d91dcb3c..1a3bd82a981 100644
--- a/src/test/compile-fail/lint-dead-code-5.rs
+++ b/src/test/compile-fail/lint-dead-code-5.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(struct_variant)]
 #![allow(unused_variables)]
 #![deny(dead_code)]
 
diff --git a/src/test/compile-fail/lint-missing-doc.rs b/src/test/compile-fail/lint-missing-doc.rs
index f0b6abe28d3..365081aee1a 100644
--- a/src/test/compile-fail/lint-missing-doc.rs
+++ b/src/test/compile-fail/lint-missing-doc.rs
@@ -10,7 +10,6 @@
 
 // When denying at the crate level, be sure to not get random warnings from the
 // injected intrinsics by the compiler.
-#![feature(struct_variant)]
 #![feature(globs)]
 #![deny(missing_docs)]
 #![allow(dead_code)]
@@ -106,8 +105,7 @@ enum Baz {
 
 pub enum PubBaz { //~ ERROR: missing documentation
     PubBazA { //~ ERROR: missing documentation
-        pub a: int, //~ ERROR: missing documentation
-        b: int
+        a: int, //~ ERROR: missing documentation
     },
 }
 
@@ -116,15 +114,13 @@ pub enum PubBaz2 {
     /// dox
     PubBaz2A {
         /// dox
-        pub a: int,
-        b: int
+        a: int,
     },
 }
 
 #[allow(missing_docs)]
 pub enum PubBaz3 {
     PubBaz3A {
-        pub a: int,
         b: int
     },
 }
diff --git a/src/test/compile-fail/lint-raw-ptr-deriving.rs b/src/test/compile-fail/lint-raw-ptr-deriving.rs
index da43324d494..72632b56706 100644
--- a/src/test/compile-fail/lint-raw-ptr-deriving.rs
+++ b/src/test/compile-fail/lint-raw-ptr-deriving.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(struct_variant)]
 #![allow(dead_code)]
 #![deny(raw_pointer_deriving)]
 
diff --git a/src/test/compile-fail/lint-visible-private-types.rs b/src/test/compile-fail/lint-visible-private-types.rs
index 55ffdcd7f9f..373bcb1f859 100644
--- a/src/test/compile-fail/lint-visible-private-types.rs
+++ b/src/test/compile-fail/lint-visible-private-types.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(struct_variant)]
 #![deny(visible_private_types)]
 #![allow(dead_code)]
 #![crate_type="lib"]
@@ -57,8 +56,7 @@ struct Bar {
 pub enum Baz {
     Baz1(Private<int>), //~ ERROR private type in exported type signature
     Baz2 {
-        pub x: Private<int>, //~ ERROR private type in exported type signature
-        y: Private<int>
+        y: Private<int> //~ ERROR private type in exported type signature
     },
 }
 
diff --git a/src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs b/src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs
index 09916a11f72..120f092d732 100644
--- a/src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs
+++ b/src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // aux-build:namespaced_enums.rs
-#![feature(struct_variant, globs)]
+#![feature(globs)]
 
 extern crate namespaced_enums;
 
diff --git a/src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs b/src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs
index 1554d410070..a8f4e6ba090 100644
--- a/src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs
+++ b/src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs
@@ -7,7 +7,7 @@
 // <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.
-#![feature(struct_variant, globs)]
+#![feature(globs)]
 
 mod m2 {
     pub enum Foo {
diff --git a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
index c4d5d734a71..87fe50c8666 100644
--- a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
+++ b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
@@ -12,5 +12,5 @@ enum State { ST_NULL, ST_WHITESPACE }
 
 fn main() {
     [ST_NULL, ..(ST_WHITESPACE as uint)];
-    //~^ ERROR expected constant integer for repeat count, found variable
+    //~^ ERROR expected constant integer for repeat count, found non-constant expression
 }
diff --git a/src/test/compile-fail/non-exhaustive-pattern-witness.rs b/src/test/compile-fail/non-exhaustive-pattern-witness.rs
index b7ff3a18fcf..7f1204ceee8 100644
--- a/src/test/compile-fail/non-exhaustive-pattern-witness.rs
+++ b/src/test/compile-fail/non-exhaustive-pattern-witness.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(advanced_slice_patterns, struct_variant)]
+#![feature(advanced_slice_patterns)]
 
 struct Foo {
     first: bool,
diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs
index be79a7a915b..38fbb426fb1 100644
--- a/src/test/compile-fail/repeat_count.rs
+++ b/src/test/compile-fail/repeat_count.rs
@@ -13,8 +13,9 @@
 fn main() {
     let n = 1;
     let a = [0, ..n]; //~ ERROR expected constant integer for repeat count, found variable
-    let b = [0, ..()]; //~ ERROR expected positive integer for repeat count, found ()
-    //~^ ERROR: expected `uint`, found `()`
+    let b = [0, ..()];
+//~^ ERROR expected constant integer for repeat count, found non-constant expression
+//~^^ ERROR: expected `uint`, found `()`
     let c = [0, ..true]; //~ ERROR expected positive integer for repeat count, found boolean
     //~^ ERROR: expected `uint`, found `bool`
     let d = [0, ..0.5]; //~ ERROR expected positive integer for repeat count, found float
diff --git a/src/test/compile-fail/struct-like-enum-nonexhaustive.rs b/src/test/compile-fail/struct-like-enum-nonexhaustive.rs
index 8d1e5b46279..91709e2ea7d 100644
--- a/src/test/compile-fail/struct-like-enum-nonexhaustive.rs
+++ b/src/test/compile-fail/struct-like-enum-nonexhaustive.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(struct_variant)]
-
 enum A {
     B { x: Option<int> },
     C
diff --git a/src/test/compile-fail/gated-struct-enums.rs b/src/test/compile-fail/struct-variant-no-pub.rs
index f1bd9362bb7..15ed69083e0 100644
--- a/src/test/compile-fail/gated-struct-enums.rs
+++ b/src/test/compile-fail/struct-variant-no-pub.rs
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-enum A { B { foo: int } }
-//~^ ERROR: enum struct variants are experimental
+enum Foo {
+    Bar {
+        pub a: int //~ ERROR: `pub` is not allowed here
+    }
+}
 
 fn main() {}
-
diff --git a/src/test/compile-fail/struct-variant-privacy-xc.rs b/src/test/compile-fail/struct-variant-privacy-xc.rs
index 2d289c7f6cd..c58273361ad 100644
--- a/src/test/compile-fail/struct-variant-privacy-xc.rs
+++ b/src/test/compile-fail/struct-variant-privacy-xc.rs
@@ -9,8 +9,6 @@
 // except according to those terms.
 
 // aux-build:struct_variant_privacy.rs
-#![feature(struct_variant)]
-
 extern crate struct_variant_privacy;
 
 fn f(b: struct_variant_privacy::Bar) { //~ ERROR enum `Bar` is private
diff --git a/src/test/compile-fail/struct-variant-privacy.rs b/src/test/compile-fail/struct-variant-privacy.rs
index 53b8fdf71b7..bf404c27648 100644
--- a/src/test/compile-fail/struct-variant-privacy.rs
+++ b/src/test/compile-fail/struct-variant-privacy.rs
@@ -7,8 +7,6 @@
 // <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.
-#![feature(struct_variant)]
-
 mod foo {
     enum Bar {
         Baz { a: int }
diff --git a/src/test/compile-fail/unsized5.rs b/src/test/compile-fail/unsized5.rs
index 41196b60c8e..2f1eb35a426 100644
--- a/src/test/compile-fail/unsized5.rs
+++ b/src/test/compile-fail/unsized5.rs
@@ -7,7 +7,6 @@
 // <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.
-#![feature(struct_variant)]
 
 // Test `Sized?` types not allowed in fields (except the last one).
 
diff --git a/src/test/run-pass/concat.rs b/src/test/run-pass/concat.rs
index 21c247cc69e..d78f948edc5 100644
--- a/src/test/run-pass/concat.rs
+++ b/src/test/run-pass/concat.rs
@@ -15,12 +15,12 @@ pub fn main() {
     assert_eq!(concat!("qux", "quux",).to_string(), "quxquux".to_string());
 
     assert_eq!(
-        concat!(1, 2i, 3u, 4f32, 4.0, 'a', true, ()),
+        concat!(1, 2i, 3u, 4f32, 4.0, 'a', true),
         "12344.0atrue"
     );
 
     assert!(match "12344.0atrue" {
-        concat!(1, 2i, 3u, 4f32, 4.0, 'a', true, ()) => true,
+        concat!(1, 2i, 3u, 4f32, 4.0, 'a', true) => true,
         _ => false
     })
 }