about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure21
-rw-r--r--man/rustc.12
-rw-r--r--man/rustdoc.12
-rw-r--r--mk/main.mk32
-rw-r--r--src/doc/guide-tasks.md2
-rw-r--r--src/doc/guide.md32
-rw-r--r--src/doc/index.md8
-rw-r--r--src/etc/kate/rust.xml2
-rw-r--r--src/etc/licenseck.py1
-rw-r--r--src/liballoc/heap.rs29
-rw-r--r--src/libcore/fmt/rt.rs7
-rw-r--r--src/libcore/str.rs100
-rw-r--r--src/libcoretest/str.rs6
-rw-r--r--src/libnum/bigint.rs2
-rw-r--r--src/libnum/lib.rs5
-rw-r--r--src/librustc/diagnostics.rs7
-rw-r--r--src/librustc/lint/builtin.rs42
-rw-r--r--src/librustc/lint/context.rs1
-rw-r--r--src/librustc/metadata/decoder.rs4
-rw-r--r--src/librustc/metadata/tydecode.rs4
-rw-r--r--src/librustc/metadata/tyencode.rs2
-rw-r--r--src/librustc/middle/astencode.rs2
-rw-r--r--src/librustc/middle/def.rs4
-rw-r--r--src/librustc/middle/liveness.rs24
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc/middle/privacy.rs3
-rw-r--r--src/librustc/middle/resolve.rs18
-rw-r--r--src/librustc/middle/save/mod.rs2
-rw-r--r--src/librustc/middle/traits/util.rs4
-rw-r--r--src/librustc/middle/trans/_match.rs2
-rw-r--r--src/librustc/middle/trans/expr.rs12
-rw-r--r--src/librustc/middle/ty.rs10
-rw-r--r--src/librustc/middle/ty_fold.rs2
-rw-r--r--src/librustc/middle/typeck/astconv.rs6
-rw-r--r--src/librustc/middle/typeck/check/mod.rs4
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs2
-rw-r--r--src/librustc/middle/typeck/check/regionmanip.rs2
-rw-r--r--src/librustc/middle/typeck/collect.rs12
-rw-r--r--src/librustc/middle/typeck/infer/error_reporting.rs2
-rw-r--r--src/librustdoc/clean/inline.rs7
-rw-r--r--src/librustdoc/clean/mod.rs4
-rw-r--r--src/librustdoc/html/item_type.rs2
-rw-r--r--src/librustdoc/html/render.rs1
-rw-r--r--src/librustdoc/html/static/main.css14
-rw-r--r--src/librustdoc/html/static/main.js2
-rw-r--r--src/libserialize/json.rs12
-rw-r--r--src/libstd/io/net/mod.rs3
-rw-r--r--src/libstd/io/net/pipe.rs (renamed from src/libstd/io/net/unix.rs)4
-rw-r--r--src/libstd/io/test.rs2
-rw-r--r--src/libstd/macros.rs4
-rw-r--r--src/libsyntax/parse/parser.rs65
-rw-r--r--src/snapshots.txt9
-rw-r--r--src/test/auxiliary/static_priv_by_default.rs13
-rw-r--r--src/test/bench/shootout-pidigits.rs128
-rw-r--r--src/test/compile-fail/array-not-vector.rs16
-rw-r--r--src/test/compile-fail/issue-17283.rs37
-rw-r--r--src/test/compile-fail/lint-unnecessary-import-braces.rs21
-rw-r--r--src/test/compile-fail/liveness-unused.rs18
-rw-r--r--src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs4
-rw-r--r--src/test/compile-fail/regions-close-over-type-parameter-multiple.rs32
-rw-r--r--src/test/compile-fail/xcrate-private-by-default.rs20
-rw-r--r--src/test/run-pass/issue-17302.rs34
-rw-r--r--src/test/run-pass/regions-close-over-type-parameter-successfully.rs30
63 files changed, 560 insertions, 346 deletions
diff --git a/configure b/configure
index 3d8f0d863f5..9aa23e732ab 100755
--- a/configure
+++ b/configure
@@ -453,6 +453,8 @@ valopt datadir "${CFG_PREFIX}/share" "install data"
 valopt infodir "${CFG_PREFIX}/share/info" "install additional info"
 valopt mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
 
+valopt release-channel "source" "the name of the release channel to build"
+
 # On windows we just store the libraries in the bin directory because
 # there's no rpath. This is where the build system itself puts libraries;
 # --libdir is used to configure the installation directory.
@@ -481,6 +483,23 @@ CFG_BUILD=`echo "${CFG_BUILD}" | sed 's/-pc-mingw32/-w64-mingw32/g'`
 CFG_HOST=`echo "${CFG_HOST}" | sed 's/-pc-mingw32/-w64-mingw32/g'`
 CFG_TARGET=`echo "${CFG_TARGET}" | sed 's/-pc-mingw32/-w64-mingw32/g'`
 
+# Validate the release channel
+case "$CFG_RELEASE_CHANNEL" in
+    (source | nightly | beta | stable)
+	;;
+    (*)
+        err "release channel must be 'source', 'nightly', 'beta' or 'stable'"
+        ;;
+esac
+
+# Continue supporting the old --enable-nightly flag to transition the bots
+# XXX Remove me
+if [ $CFG_ENABLE_NIGHTLY -eq 1 ]
+then
+    CFG_RELEASE_CHANNEL=nightly
+    putvar CFG_RELEASE_CHANNEL
+fi
+
 step_msg "looking for build programs"
 
 probe_need CFG_PERL        perl
@@ -636,7 +655,7 @@ then
             # check that gcc, cc and g++ all point to the same compiler.
             # note that for xcode 5, g++ points to clang, not clang++
             if !((chk_cc gcc clang  && chk_cc g++ clang) ||
-                (chk_cc gcc gcc  &&( chk_cc g++ g++ || chk g++ gcc))) then
+                (chk_cc gcc gcc  &&( chk_cc g++ g++ || chk g++ gcc))); then
                 err "the gcc and g++ in your path point to different compilers.
     Check which versions are in your path with gcc --version and g++ --version.
     To resolve this problem, either fix your PATH  or run configure with --enable-clang"
diff --git a/man/rustc.1 b/man/rustc.1
index 00d698e611e..6b7243541c4 100644
--- a/man/rustc.1
+++ b/man/rustc.1
@@ -1,4 +1,4 @@
-.TH RUSTC "1" "March 2014" "rustc 0.12.0-pre" "User Commands"
+.TH RUSTC "1" "March 2014" "rustc 0.12.0" "User Commands"
 .SH NAME
 rustc \- The Rust compiler
 .SH SYNOPSIS
diff --git a/man/rustdoc.1 b/man/rustdoc.1
index 12e776b9861..e675aca38aa 100644
--- a/man/rustdoc.1
+++ b/man/rustdoc.1
@@ -1,4 +1,4 @@
-.TH RUSTDOC "1" "March 2014" "rustdoc 0.12.0-pre" "User Commands"
+.TH RUSTDOC "1" "March 2014" "rustdoc 0.12.0" "User Commands"
 .SH NAME
 rustdoc \- generate documentation from Rust source code
 .SH SYNOPSIS
diff --git a/mk/main.mk b/mk/main.mk
index 3d5d0b441f1..6667a29d4f9 100644
--- a/mk/main.mk
+++ b/mk/main.mk
@@ -14,22 +14,32 @@
 
 # The version number
 CFG_RELEASE_NUM=0.12.0
-CFG_RELEASE_LABEL=-pre
 
 CFG_FILENAME_EXTRA=4e7c5e5c
 
-ifndef CFG_ENABLE_NIGHTLY
-# This is the normal version string
-CFG_RELEASE=$(CFG_RELEASE_NUM)$(CFG_RELEASE_LABEL)
-CFG_PACKAGE_VERS=$(CFG_RELEASE)
-else
-# Modify the version label for nightly builds
-CFG_RELEASE=$(CFG_RELEASE_NUM)$(CFG_RELEASE_LABEL)-nightly
-# When building nightly distributables just reuse the same "rust-nightly" name
-# so when we upload we'll always override the previous nighly. This doesn't actually
-# impact the version reported by rustc - it's just for file naming.
+ifeq ($(CFG_RELEASE_CHANNEL),stable)
+# This is the normal semver version string, e.g. "0.12.0", "0.12.0-nightly"
+CFG_RELEASE=$(CFG_RELEASE_NUM)
+# This is the string used in dist artifact file names, e.g. "0.12.0", "nightly"
+CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)
+endif
+ifeq ($(CFG_RELEASE_CHANNEL),beta)
+CFG_RELEASE=$(CFG_RELEASE_NUM)-beta
+# When building beta/nightly distributables just reuse the same "beta"
+# name so when we upload we'll always override the previous
+# nighly. This doesn't actually impact the version reported by rustc -
+# it's just for file naming.
+CFG_PACKAGE_VERS=beta
+endif
+ifeq ($(CFG_RELEASE_CHANNEL),nightly)
+CFG_RELEASE=$(CFG_RELEASE_NUM)-nightly
 CFG_PACKAGE_VERS=nightly
 endif
+ifeq ($(CFG_RELEASE_CHANNEL),source)
+CFG_RELEASE=$(CFG_RELEASE_NUM)-pre
+CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-pre
+endif
+
 # The name of the package to use for creating tarballs, installers etc.
 CFG_PACKAGE_NAME=rust-$(CFG_PACKAGE_VERS)
 
diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md
index 95bcc9ca12b..4a978ccb92b 100644
--- a/src/doc/guide-tasks.md
+++ b/src/doc/guide-tasks.md
@@ -235,7 +235,7 @@ fn partial_sum(start: uint) -> f64 {
 }
 
 fn main() {
-    let mut futures = Vec::from_fn(1000, |ind| Future::spawn( proc() { partial_sum(ind) }));
+    let mut futures = Vec::from_fn(200, |ind| Future::spawn( proc() { partial_sum(ind) }));
 
     let mut final_res = 0f64;
     for ft in futures.iter_mut()  {
diff --git a/src/doc/guide.md b/src/doc/guide.md
index cf97cc3ab64..2f16c783446 100644
--- a/src/doc/guide.md
+++ b/src/doc/guide.md
@@ -29,8 +29,11 @@ $ curl -s https://static.rust-lang.org/rustup.sh | sudo sh
 (If you're concerned about `curl | sudo sh`, please keep reading. Disclaimer
 below.)
 
-If you're on Windows, please [download this .exe and run
-it](https://static.rust-lang.org/dist/rust-nightly-install.exe).
+If you're on Windows, please download either the [32-bit
+installer](https://static.rust-lang.org/dist/rust-nightly-i686-w64-mingw32.exe)
+or the [64-bit
+installer](https://static.rust-lang.org/dist/rust-nightly-x86_64-w64-mingw32.exe)
+and run it.
 
 If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay.
 Not every programming language is great for everyone. Just pass an argument to
@@ -185,8 +188,8 @@ Next up is this line:
 This line does all of the work in our little program. There are a number of
 details that are important here. The first is that it's indented with four
 spaces, not tabs. Please configure your editor of choice to insert four spaces
-with the tab key. We provide some sample configurations for various editors
-[here](https://github.com/rust-lang/rust/tree/master/src/etc).
+with the tab key. We provide some [sample configurations for various
+editors](https://github.com/rust-lang/rust/tree/master/src/etc).
 
 The second point is the `println!()` part. This is calling a Rust **macro**,
 which is how metaprogramming is done in Rust. If it were a function instead, it
@@ -392,14 +395,10 @@ By the way, in these examples, `i` indicates that the number is an integer.
 
 Rust is a statically typed language, which means that we specify our types up
 front. So why does our first example compile? Well, Rust has this thing called
-"[Hindley-Milner type
-inference](http://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system)",
-named after some really smart type theorists. If you clicked that link, don't
-be scared: what this means for you is that Rust will attempt to infer the types
-in your program, and it's pretty good at it. If it can infer the type, Rust
+"type inference." If it can figure out what the type of something is, Rust
 doesn't require you to actually type it out.
 
-We can add the type if we want to. Types come after a colon (`:`):
+We can add the type if we want to, though. Types come after a colon (`:`):
 
 ```{rust}
 let x: int = 5;
@@ -1281,15 +1280,15 @@ two main looping constructs: `for` and `while`.
 
 The `for` loop is used to loop a particular number of times. Rust's `for` loops
 work a bit differently than in other systems languages, however. Rust's `for`
-loop doesn't look like this C `for` loop:
+loop doesn't look like this "C style" `for` loop:
 
-```{ignore,c}
+```{c}
 for (x = 0; x < 10; x++) {
     printf( "%d\n", x );
 }
 ```
 
-It looks like this:
+Instead, it looks like this:
 
 ```{rust}
 for x in range(0i, 10i) {
@@ -1312,10 +1311,9 @@ valid for the loop body. Once the body is over, the next value is fetched from
 the iterator, and we loop another time. When there are no more values, the
 `for` loop is over.
 
-In our example, the `range` function is a function, provided by Rust, that
-takes a start and an end position, and gives an iterator over those values. The
-upper bound is exclusive, though, so our loop will print `0` through `9`, not
-`10`.
+In our example, `range` is a function that takes a start and an end position,
+and gives an iterator over those values. The upper bound is exclusive, though,
+so our loop will print `0` through `9`, not `10`.
 
 Rust does not have the "C style" `for` loop on purpose. Manually controlling
 each element of the loop is complicated and error prone, even for experienced C
diff --git a/src/doc/index.md b/src/doc/index.md
index 475c3b748db..f237bc2ddbc 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -86,10 +86,10 @@ There are questions that are asked quite often, and so we've made FAQs for them:
 
 # The standard library
 
-You can find function-level documentation for the entire standard library
-[here](std/index.html). There's a list of crates on the left with more specific
-sections, or you can use the search bar at the top to search for something if
-you know its name.
+We have [API documentation for the entire standard
+library](std/index.html). There's a list of crates on the left with more
+specific sections, or you can use the search bar at the top to search for
+something if you know its name.
 
 # External documentation
 
diff --git a/src/etc/kate/rust.xml b/src/etc/kate/rust.xml
index cf59f1454c1..2b80c0ff39f 100644
--- a/src/etc/kate/rust.xml
+++ b/src/etc/kate/rust.xml
@@ -7,7 +7,7 @@
 	<!ENTITY rustIdent "[a-zA-Z_][a-zA-Z_0-9]*">
 	<!ENTITY rustIntSuf "([iu](8|16|32|64)?)?">
 ]>
-<language name="Rust" version="0.12.0-pre" kateversion="2.4" section="Sources" extensions="*.rs" mimetype="text/x-rust" priority="15">
+<language name="Rust" version="0.12.0" kateversion="2.4" section="Sources" extensions="*.rs" mimetype="text/x-rust" priority="15">
 <highlighting>
 	<list name="fn">
 		<item> fn </item>
diff --git a/src/etc/licenseck.py b/src/etc/licenseck.py
index 328a2ff6c94..d1b115fc913 100644
--- a/src/etc/licenseck.py
+++ b/src/etc/licenseck.py
@@ -49,7 +49,6 @@ exceptions = [
     "test/bench/shootout-mandelbrot.rs", # BSD
     "test/bench/shootout-meteor.rs", # BSD
     "test/bench/shootout-nbody.rs", # BSD
-    "test/bench/shootout-pidigits.rs", # BSD
     "test/bench/shootout-regex-dna.rs", # BSD
     "test/bench/shootout-reverse-complement.rs", # BSD
     "test/bench/shootout-threadring.rs", # BSD
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index 51e1f64e006..349ae15eb32 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -10,9 +10,6 @@
 
 // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
 
-#[cfg(stage0, not(test))] use core::raw;
-#[cfg(stage0, not(test))] use util;
-
 /// Returns a pointer to `size` bytes of memory.
 ///
 /// Behavior is undefined if the requested size is 0 or the alignment is not a
@@ -111,21 +108,6 @@ unsafe fn exchange_free(ptr: *mut u8, size: uint, align: uint) {
     deallocate(ptr, size, align);
 }
 
-#[cfg(stage0, not(test))]
-#[lang="closure_exchange_malloc"]
-#[inline]
-#[allow(deprecated)]
-unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint,
-                                  align: uint) -> *mut u8 {
-    let total_size = util::get_box_size(size, align);
-    let p = allocate(total_size, 8);
-
-    let alloc = p as *mut raw::Box<()>;
-    (*alloc).drop_glue = drop_glue;
-
-    alloc as *mut u8
-}
-
 // The minimum alignment guaranteed by the architecture. This value is used to
 // add fast paths for low alignment values. In practice, the alignment is a
 // constant at the call site and the branch will be optimized out.
@@ -155,9 +137,6 @@ mod imp {
                       flags: c_int) -> *mut c_void;
         fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t,
                       flags: c_int) -> size_t;
-        #[cfg(stage0)]
-        fn je_dallocx(ptr: *mut c_void, flags: c_int);
-        #[cfg(not(stage0))]
         fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
         fn je_nallocx(size: size_t, flags: c_int) -> size_t;
         fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void,
@@ -209,14 +188,6 @@ mod imp {
     }
 
     #[inline]
-    #[cfg(stage0)]
-    pub unsafe fn deallocate(ptr: *mut u8, _size: uint, align: uint) {
-        let flags = align_to_flags(align);
-        je_dallocx(ptr as *mut c_void, flags)
-    }
-
-    #[inline]
-    #[cfg(not(stage0))]
     pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
         let flags = align_to_flags(align);
         je_sdallocx(ptr as *mut c_void, size as size_t, flags)
diff --git a/src/libcore/fmt/rt.rs b/src/libcore/fmt/rt.rs
index 59fbde88d8b..1c88eb6ddfa 100644
--- a/src/libcore/fmt/rt.rs
+++ b/src/libcore/fmt/rt.rs
@@ -14,13 +14,6 @@
 //! These definitions are similar to their `ct` equivalents, but differ in that
 //! these can be statically allocated and are slightly optimized for the runtime
 
-#[cfg(stage0)]
-#[doc(hidden)]
-pub enum Piece<'a> {
-    String(&'a str),
-    Argument(Argument<'a>),
-}
-
 #[doc(hidden)]
 pub struct Argument<'a> {
     pub position: Position,
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 6837f3b9af7..7e399902a4b 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -419,8 +419,76 @@ struct TwoWaySearcher {
     memory: uint
 }
 
-// This is the Two-Way search algorithm, which was introduced in the paper:
-// Crochemore, M., Perrin, D., 1991, Two-way string-matching, Journal of the ACM 38(3):651-675.
+/*
+    This is the Two-Way search algorithm, which was introduced in the paper:
+    Crochemore, M., Perrin, D., 1991, Two-way string-matching, Journal of the ACM 38(3):651-675.
+
+    Here's some background information.
+
+    A *word* is a string of symbols. The *length* of a word should be a familiar
+    notion, and here we denote it for any word x by |x|.
+    (We also allow for the possibility of the *empty word*, a word of length zero).
+
+    If x is any non-empty word, then an integer p with 0 < p <= |x| is said to be a
+    *period* for x iff for all i with 0 <= i <= |x| - p - 1, we have x[i] == x[i+p].
+    For example, both 1 and 2 are periods for the string "aa". As another example,
+    the only period of the string "abcd" is 4.
+
+    We denote by period(x) the *smallest* period of x (provided that x is non-empty).
+    This is always well-defined since every non-empty word x has at least one period,
+    |x|. We sometimes call this *the period* of x.
+
+    If u, v and x are words such that x = uv, where uv is the concatenation of u and
+    v, then we say that (u, v) is a *factorization* of x.
+
+    Let (u, v) be a factorization for a word x. Then if w is a non-empty word such
+    that both of the following hold
+
+      - either w is a suffix of u or u is a suffix of w
+      - either w is a prefix of v or v is a prefix of w
+
+    then w is said to be a *repetition* for the factorization (u, v).
+
+    Just to unpack this, there are four possibilities here. Let w = "abc". Then we
+    might have:
+
+      - w is a suffix of u and w is a prefix of v. ex: ("lolabc", "abcde")
+      - w is a suffix of u and v is a prefix of w. ex: ("lolabc", "ab")
+      - u is a suffix of w and w is a prefix of v. ex: ("bc", "abchi")
+      - u is a suffix of w and v is a prefix of w. ex: ("bc", "a")
+
+    Note that the word vu is a repetition for any factorization (u,v) of x = uv,
+    so every factorization has at least one repetition.
+
+    If x is a string and (u, v) is a factorization for x, then a *local period* for
+    (u, v) is an integer r such that there is some word w such that |w| = r and w is
+    a repetition for (u, v).
+
+    We denote by local_period(u, v) the smallest local period of (u, v). We sometimes
+    call this *the local period* of (u, v). Provided that x = uv is non-empty, this
+    is well-defined (because each non-empty word has at least one factorization, as
+    noted above).
+
+    It can be proven that the following is an equivalent definition of a local period
+    for a factorization (u, v): any positive integer r such that x[i] == x[i+r] for
+    all i such that |u| - r <= i <= |u| - 1 and such that both x[i] and x[i+r] are
+    defined. (i.e. i > 0 and i + r < |x|).
+
+    Using the above reformulation, it is easy to prove that
+
+        1 <= local_period(u, v) <= period(uv)
+
+    A factorization (u, v) of x such that local_period(u,v) = period(x) is called a
+    *critical factorization*.
+
+    The algorithm hinges on the following theorem, which is stated without proof:
+
+    **Critical Factorization Theorem** Any word x has at least one critical
+    factorization (u, v) such that |u| < period(x).
+
+    The purpose of maximal_suffix is to find such a critical factorization.
+
+*/
 impl TwoWaySearcher {
     fn new(needle: &[u8]) -> TwoWaySearcher {
         let (crit_pos1, period1) = TwoWaySearcher::maximal_suffix(needle, false);
@@ -436,15 +504,19 @@ impl TwoWaySearcher {
             period = period2;
         }
 
+        // This isn't in the original algorithm, as far as I'm aware.
         let byteset = needle.iter()
                             .fold(0, |a, &b| (1 << ((b & 0x3f) as uint)) | a);
 
-        // The logic here (calculating crit_pos and period, the final if statement to see which
-        // period to use for the TwoWaySearcher) is essentially an implementation of the
-        // "small-period" function from the paper (p. 670)
+        // A particularly readable explanation of what's going on here can be found
+        // in Crochemore and Rytter's book "Text Algorithms", ch 13. Specifically
+        // see the code for "Algorithm CP" on p. 323.
         //
-        // In the paper they check whether `needle.slice_to(crit_pos)` is a suffix of
-        // `needle.slice(crit_pos, crit_pos + period)`, which is precisely what this does
+        // What's going on is we have some critical factorization (u, v) of the
+        // needle, and we want to determine whether u is a suffix of
+        // v.slice_to(period). If it is, we use "Algorithm CP1". Otherwise we use
+        // "Algorithm CP2", which is optimized for when the period of the needle
+        // is large.
         if needle.slice_to(crit_pos) == needle.slice(period, period + crit_pos) {
             TwoWaySearcher {
                 crit_pos: crit_pos,
@@ -466,6 +538,11 @@ impl TwoWaySearcher {
         }
     }
 
+    // One of the main ideas of Two-Way is that we factorize the needle into
+    // two halves, (u, v), and begin trying to find v in the haystack by scanning
+    // left to right. If v matches, we try to match u by scanning right to left.
+    // How far we can jump when we encounter a mismatch is all based on the fact
+    // that (u, v) is a critical factorization for the needle.
     #[inline]
     fn next(&mut self, haystack: &[u8], needle: &[u8], long_period: bool) -> Option<(uint, uint)> {
         'search: loop {
@@ -479,6 +556,9 @@ impl TwoWaySearcher {
                     ((haystack[self.position + needle.len() - 1] & 0x3f)
                      as uint)) & 1 == 0 {
                 self.position += needle.len();
+                if !long_period {
+                    self.memory = 0;
+                }
                 continue 'search;
             }
 
@@ -517,9 +597,9 @@ impl TwoWaySearcher {
         }
     }
 
-    // returns (i, p) where i is the "critical position", the starting index of
-    // of maximal suffix, and p is the period of the suffix
-    // see p. 668 of the paper
+    // Computes a critical factorization (u, v) of `arr`.
+    // Specifically, returns (i, p), where i is the starting index of v in some
+    // critical factorization (u, v) and p = period(v)
     #[inline]
     fn maximal_suffix(arr: &[u8], reversed: bool) -> (uint, uint) {
         let mut left = -1; // Corresponds to i in the paper
diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs
index be2275dcd4a..51bd72ec014 100644
--- a/src/libcoretest/str.rs
+++ b/src/libcoretest/str.rs
@@ -26,6 +26,12 @@ fn strslice_issue_16589() {
     check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
 }
 
+#[test]
+fn strslice_issue_16878() {
+    assert!(!"1234567ah012345678901ah".contains("hah"));
+    assert!(!"00abc01234567890123456789abc".contains("bcabc"));
+}
+
 
 #[test]
 fn test_strslice_contains() {
diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs
index c97f9513fc3..3f91ce11915 100644
--- a/src/libnum/bigint.rs
+++ b/src/libnum/bigint.rs
@@ -19,6 +19,7 @@
 //! ## Example
 //!
 //! ```rust
+//! # #![allow(deprecated)]
 //! use num::bigint::BigUint;
 //! use std::num::{Zero, One};
 //! use std::mem::replace;
@@ -42,6 +43,7 @@
 //! It's easy to generate large random numbers:
 //!
 //! ```rust
+//! # #![allow(deprecated)]
 //! use num::bigint::{ToBigInt, RandBigInt};
 //! use std::rand;
 //!
diff --git a/src/libnum/lib.rs b/src/libnum/lib.rs
index f12279b20e8..17071d22dee 100644
--- a/src/libnum/lib.rs
+++ b/src/libnum/lib.rs
@@ -18,6 +18,7 @@
 //! approximate a square root to arbitrary precision:
 //!
 //! ```
+//! # #![allow(deprecated)]
 //! extern crate num;
 //!
 //! use num::bigint::BigInt;
@@ -46,7 +47,9 @@
 #![feature(default_type_params)]
 
 #![crate_name = "num"]
-#![experimental]
+#![deprecated = "This is now a cargo package located at: \
+                 https://github.com/rust-lang/num"]
+#![allow(deprecated)]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 079e01c6ed6..14cf07cd5e4 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -109,11 +109,6 @@ register_diagnostics!(
     E0092,
     E0093,
     E0094,
-    E0095,
-    E0096,
-    E0097,
-    E0098,
-    E0099,
     E0100,
     E0101,
     E0102,
@@ -153,7 +148,6 @@ register_diagnostics!(
     E0139,
     E0140,
     E0141,
-    E0142,
     E0143,
     E0144,
     E0145,
@@ -169,6 +163,5 @@ register_diagnostics!(
     E0157,
     E0158,
     E0159,
-    E0160,
     E0161
 )
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index eed41edac9d..836d355d55b 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -689,11 +689,7 @@ impl LintPass for UnusedResult {
             ast::StmtSemi(ref expr, _) => &**expr,
             _ => return
         };
-        let t = ty::expr_ty(cx.tcx, expr);
-        match ty::get(t).sty {
-            ty::ty_nil | ty::ty_bot | ty::ty_bool => return,
-            _ => {}
-        }
+
         match expr.node {
             ast::ExprRet(..) => return,
             _ => {}
@@ -702,6 +698,7 @@ impl LintPass for UnusedResult {
         let t = ty::expr_ty(cx.tcx, expr);
         let mut warned = false;
         match ty::get(t).sty {
+            ty::ty_nil | ty::ty_bot | ty::ty_bool => return,
             ty::ty_struct(did, _) |
             ty::ty_enum(did, _) => {
                 if ast_util::is_local(did) {
@@ -1107,6 +1104,41 @@ impl LintPass for UnnecessaryParens {
     }
 }
 
+declare_lint!(UNNECESSARY_IMPORT_BRACES, Allow,
+              "unnecessary braces around an imported item")
+
+pub struct UnnecessaryImportBraces;
+
+impl LintPass for UnnecessaryImportBraces {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNNECESSARY_IMPORT_BRACES)
+    }
+
+    fn check_view_item(&mut self, cx: &Context, view_item: &ast::ViewItem) {
+        match view_item.node {
+            ast::ViewItemUse(ref view_path) => {
+                match view_path.node {
+                    ast::ViewPathList(_, ref items, _) => {
+                        if items.len() == 1 {
+                            match items[0].node {
+                                ast::PathListIdent {ref name, ..} => {
+                                    let m = format!("braces around {} is unnecessary",
+                                                    token::get_ident(*name).get());
+                                    cx.span_lint(UNNECESSARY_IMPORT_BRACES, view_item.span,
+                                                 m.as_slice());
+                                },
+                                _ => ()
+                            }
+                        }
+                    }
+                    _ => ()
+                }
+            },
+            _ => ()
+        }
+    }
+}
+
 declare_lint!(UNUSED_UNSAFE, Warn,
               "unnecessary use of an `unsafe` block")
 
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index c75b57dcafa..e39685705df 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -183,6 +183,7 @@ impl LintStore {
                      NonSnakeCase,
                      NonUppercaseStatics,
                      UnnecessaryParens,
+                     UnnecessaryImportBraces,
                      UnusedUnsafe,
                      UnsafeBlock,
                      UnusedMut,
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index c7af7b24939..748e59b75ed 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -325,7 +325,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
             };
             DlDef(def::DefStaticMethod(did, provenance, fn_style))
         }
-        Type | ForeignType => DlDef(def::DefTy(did)),
+        Type | ForeignType => DlDef(def::DefTy(did, false)),
         Mod => DlDef(def::DefMod(did)),
         ForeignMod => DlDef(def::DefForeignMod(did)),
         StructVariant => {
@@ -337,7 +337,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
             DlDef(def::DefVariant(enum_did, did, false))
         }
         Trait => DlDef(def::DefTrait(did)),
-        Enum => DlDef(def::DefTy(did)),
+        Enum => DlDef(def::DefTy(did, true)),
         Impl => DlImpl(did),
         PublicField | InheritedField => DlField,
     }
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 53203663bb1..0e888b39b85 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -680,14 +680,14 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
     let builtin_bounds = parse_builtin_bounds(st, |x,y| conv(x,y));
 
     let mut param_bounds = ty::ParamBounds {
-        opt_region_bound: None,
+        region_bounds: Vec::new(),
         builtin_bounds: builtin_bounds,
         trait_bounds: Vec::new()
     };
     loop {
         match next(st) {
             'R' => {
-                param_bounds.opt_region_bound = Some(parse_region(st, |x, y| conv (x, y)));
+                param_bounds.region_bounds.push(parse_region(st, |x, y| conv (x, y)));
             }
             'I' => {
                 param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index cbf558b6b48..3ef1d15cf56 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -366,7 +366,7 @@ pub fn enc_existential_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::Exi
 pub fn enc_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
     enc_builtin_bounds(w, cx, &bs.builtin_bounds);
 
-    for &r in bs.opt_region_bound.iter() {
+    for &r in bs.region_bounds.iter() {
         mywrite!(w, "R");
         enc_region(w, cx, r);
     }
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 272b7111fb8..880445ff38d 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -454,7 +454,7 @@ impl tr for def::Def {
             def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
           },
           def::DefTrait(did) => def::DefTrait(did.tr(dcx)),
-          def::DefTy(did) => def::DefTy(did.tr(dcx)),
+          def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum),
           def::DefPrimTy(p) => def::DefPrimTy(p),
           def::DefTyParam(s, did, v) => def::DefTyParam(s, did.tr(dcx), v),
           def::DefBinding(nid, bm) => def::DefBinding(dcx.tr_id(nid), bm),
diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs
index 914cf451ebe..70a9b6c5337 100644
--- a/src/librustc/middle/def.rs
+++ b/src/librustc/middle/def.rs
@@ -25,7 +25,7 @@ pub enum Def {
     DefArg(ast::NodeId, ast::BindingMode),
     DefLocal(ast::NodeId, ast::BindingMode),
     DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */),
-    DefTy(ast::DefId),
+    DefTy(ast::DefId, bool /* is_enum */),
     DefTrait(ast::DefId),
     DefPrimTy(ast::PrimTy),
     DefTyParam(ParamSpace, ast::DefId, uint),
@@ -62,7 +62,7 @@ impl Def {
         match *self {
             DefFn(id, _) | DefStaticMethod(id, _, _) | DefMod(id) |
             DefForeignMod(id) | DefStatic(id, _) |
-            DefVariant(_, id, _) | DefTy(id) | DefTyParam(_, id, _) |
+            DefVariant(_, id, _) | DefTy(id, _) | DefTyParam(_, id, _) |
             DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => {
                 id
             }
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index aecfa36c108..fee6c77a799 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -131,8 +131,8 @@ enum LoopKind<'a> {
     LoopLoop,
     /// A `while` loop, with the given expression as condition.
     WhileLoop(&'a Expr),
-    /// A `for` loop.
-    ForLoop,
+    /// A `for` loop, with the given pattern to bind.
+    ForLoop(&'a Pat),
 }
 
 #[deriving(PartialEq)]
@@ -1024,8 +1024,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_loop(expr, WhileLoop(&**cond), &**blk, succ)
           }
 
-          ExprForLoop(_, ref head, ref blk, _) => {
-            let ln = self.propagate_through_loop(expr, ForLoop, &**blk, succ);
+          ExprForLoop(ref pat, ref head, ref blk, _) => {
+            let ln = self.propagate_through_loop(expr, ForLoop(&**pat), &**blk, succ);
             self.propagate_through_expr(&**head, ln)
           }
 
@@ -1355,7 +1355,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                expr.id, block_to_string(body));
 
         let cond_ln = match kind {
-            LoopLoop | ForLoop => ln,
+            LoopLoop => ln,
+            ForLoop(ref pat) => self.define_bindings_in_pat(*pat, ln),
             WhileLoop(ref cond) => self.propagate_through_expr(&**cond, ln),
         };
         let body_ln = self.with_loop_nodes(expr.id, succ, ln, |this| {
@@ -1367,7 +1368,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             first_merge = false;
 
             let new_cond_ln = match kind {
-                LoopLoop | ForLoop => ln,
+                LoopLoop => ln,
+                ForLoop(ref pat) => {
+                    self.define_bindings_in_pat(*pat, ln)
+                }
                 WhileLoop(ref cond) => {
                     self.propagate_through_expr(&**cond, ln)
                 }
@@ -1453,6 +1457,12 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
         visit::walk_expr(this, expr);
       }
 
+      ExprForLoop(ref pat, _, _, _) => {
+        this.pat_bindings(&**pat, |this, ln, var, sp, id| {
+            this.warn_about_unused(sp, id, ln, var);
+        });
+      }
+
       // no correctness conditions related to liveness
       ExprCall(..) | ExprMethodCall(..) | ExprIf(..) | ExprMatch(..) |
       ExprWhile(..) | ExprLoop(..) | ExprIndex(..) | ExprField(..) |
@@ -1461,7 +1471,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
       ExprAgain(..) | ExprLit(_) | ExprBlock(..) |
       ExprMac(..) | ExprAddrOf(..) | ExprStruct(..) | ExprRepeat(..) |
       ExprParen(..) | ExprFnBlock(..) | ExprProc(..) | ExprUnboxedFn(..) |
-      ExprPath(..) | ExprBox(..) | ExprForLoop(..) => {
+      ExprPath(..) | ExprBox(..) => {
         visit::walk_expr(this, expr);
       }
     }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 3e42ee9187c..4f9cc9c080f 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -531,7 +531,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
           def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
-          def::DefTrait(_) | def::DefTy(_) | def::DefPrimTy(_) |
+          def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
           def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
           def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) => {
               Ok(Rc::new(cmt_ {
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 56c785d3c25..0eb684fe18e 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -771,7 +771,8 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
             def::DefFn(..) => ck("function"),
             def::DefStatic(..) => ck("static"),
             def::DefVariant(..) => ck("variant"),
-            def::DefTy(..) => ck("type"),
+            def::DefTy(_, false) => ck("type"),
+            def::DefTy(_, true) => ck("enum"),
             def::DefTrait(..) => ck("trait"),
             def::DefStruct(..) => ck("struct"),
             def::DefMethod(_, Some(..)) => ck("trait method"),
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index d4fe3c265f5..861ac2ffe60 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -1252,7 +1252,7 @@ impl<'a> Resolver<'a> {
                                    sp);
 
                 name_bindings.define_type
-                    (DefTy(local_def(item.id)), sp, is_public);
+                    (DefTy(local_def(item.id), false), sp, is_public);
                 parent
             }
 
@@ -1264,7 +1264,7 @@ impl<'a> Resolver<'a> {
                                    sp);
 
                 name_bindings.define_type
-                    (DefTy(local_def(item.id)), sp, is_public);
+                    (DefTy(local_def(item.id), true), sp, is_public);
 
                 for variant in (*enum_definition).variants.iter() {
                     self.build_reduced_graph_for_variant(
@@ -1287,7 +1287,7 @@ impl<'a> Resolver<'a> {
                 let name_bindings = self.add_child(ident, parent.clone(), forbid, sp);
 
                 // Define a name in the type namespace.
-                name_bindings.define_type(DefTy(local_def(item.id)), sp, is_public);
+                name_bindings.define_type(DefTy(local_def(item.id), false), sp, is_public);
 
                 // If this is a newtype or unit-like struct, define a name
                 // in the value namespace as well
@@ -1732,7 +1732,7 @@ impl<'a> Resolver<'a> {
 
         match def {
           DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) |
-          DefTy(def_id) => {
+          DefTy(def_id, _) => {
             let type_def = child_name_bindings.type_def.borrow().clone();
             match type_def {
               Some(TypeNsDef { module_def: Some(module_def), .. }) => {
@@ -1823,7 +1823,7 @@ impl<'a> Resolver<'a> {
                                                   is_public,
                                                   DUMMY_SP)
           }
-          DefTy(_) => {
+          DefTy(..) => {
               debug!("(building reduced graph for external \
                       crate) building type {}", final_ident);
 
@@ -4320,7 +4320,7 @@ impl<'a> Resolver<'a> {
 
                         // If it's a typedef, give a note
                         match def {
-                            DefTy(_) => {
+                            DefTy(..) => {
                                 self.session.span_note(
                                                 trait_reference.path.span,
                                                 format!("`type` aliases cannot \
@@ -4381,7 +4381,7 @@ impl<'a> Resolver<'a> {
                 Some(ref t) => match t.node {
                     TyPath(ref path, None, path_id) => {
                         match this.resolve_path(id, path, TypeNS, true) {
-                            Some((DefTy(def_id), lp)) if this.structs.contains_key(&def_id) => {
+                            Some((DefTy(def_id, _), lp)) if this.structs.contains_key(&def_id) => {
                                 let def = DefStruct(def_id);
                                 debug!("(resolving struct) resolved `{}` to type {:?}",
                                        token::get_ident(path.segments
@@ -5440,7 +5440,7 @@ impl<'a> Resolver<'a> {
         if allowed == Everything {
             // Look for a field with the same name in the current self_type.
             match self.def_map.borrow().find(&node_id) {
-                 Some(&DefTy(did))
+                 Some(&DefTy(did, _))
                 | Some(&DefStruct(did))
                 | Some(&DefVariant(_, did, _)) => match self.structs.find(&did) {
                     None => {}
@@ -5582,7 +5582,7 @@ impl<'a> Resolver<'a> {
                         // structs, which wouldn't result in this error.)
                         match self.with_no_errors(|this|
                             this.resolve_path(expr.id, path, TypeNS, false)) {
-                            Some((DefTy(struct_id), _))
+                            Some((DefTy(struct_id, _), _))
                               if self.structs.contains_key(&struct_id) => {
                                 self.resolve_error(expr.span,
                                         format!("`{}` is a structure name, but \
diff --git a/src/librustc/middle/save/mod.rs b/src/librustc/middle/save/mod.rs
index fe066c732dd..37ba3b75f89 100644
--- a/src/librustc/middle/save/mod.rs
+++ b/src/librustc/middle/save/mod.rs
@@ -226,7 +226,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
             def::DefMod(_) |
             def::DefForeignMod(_) => Some(recorder::ModRef),
             def::DefStruct(_) => Some(recorder::StructRef),
-            def::DefTy(_) |
+            def::DefTy(..) |
             def::DefTrait(_) => Some(recorder::TypeRef),
             def::DefStatic(_, _) |
             def::DefBinding(_, _) |
diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs
index 11b954f2ba6..1eae4ac1932 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -250,9 +250,7 @@ pub fn search_trait_and_supertraits_from_bound(tcx: &ty::ctxt,
      * is the path to that trait/supertrait. Else `None`.
      */
 
-    for (bound_index, bound) in
-        transitive_bounds(tcx, &[caller_bound]).enumerate()
-    {
+    for bound in transitive_bounds(tcx, &[caller_bound]) {
         if test(bound.def_id) {
             let vtable_param = VtableParam { bound: bound };
             return Some(vtable_param);
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 3b670dc04fd..51023d03c23 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -557,7 +557,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let tcx = bcx.tcx();
 
     let mut found: Vec<Opt> = vec![];
-    for (i, br) in m.iter().enumerate() {
+    for br in m.iter() {
         let cur = *br.pats.get(col);
         let opt = match cur.node {
             ast::PatLit(ref l) => ConstantValue(ConstantExpr(&**l)),
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index af57d49d9d8..77712570185 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -1380,7 +1380,11 @@ pub fn trans_adt<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         assert_eq!(discr, 0);
 
         match ty::expr_kind(bcx.tcx(), &*base.expr) {
-            ty::LvalueExpr => {
+            ty::RvalueDpsExpr | ty::RvalueDatumExpr if !ty::type_needs_drop(bcx.tcx(), ty) => {
+                bcx = trans_into(bcx, &*base.expr, SaveIn(addr));
+            },
+            ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"),
+            _ => {
                 let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base"));
                 for &(i, t) in base.fields.iter() {
                     let datum = base_datum.get_element(
@@ -1389,11 +1393,7 @@ pub fn trans_adt<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                     let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i);
                     bcx = datum.store_to(bcx, dest);
                 }
-            },
-            ty::RvalueDpsExpr | ty::RvalueDatumExpr => {
-                bcx = trans_into(bcx, &*base.expr, SaveIn(addr));
-            },
-            ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr")
+            }
         }
     }
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index bd472195b95..09912b54583 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -1008,7 +1008,7 @@ pub enum type_err {
 /// as well as the existential type parameter in an object type.
 #[deriving(PartialEq, Eq, Hash, Clone, Show)]
 pub struct ParamBounds {
-    pub opt_region_bound: Option<ty::Region>,
+    pub region_bounds: Vec<ty::Region>,
     pub builtin_bounds: BuiltinBounds,
     pub trait_bounds: Vec<Rc<TraitRef>>
 }
@@ -1016,7 +1016,8 @@ pub struct ParamBounds {
 /// Bounds suitable for an existentially quantified type parameter
 /// such as those that appear in object types or closure types. The
 /// major difference between this case and `ParamBounds` is that
-/// general purpose trait bounds are omitted.
+/// general purpose trait bounds are omitted and there must be
+/// *exactly one* region.
 #[deriving(PartialEq, Eq, Hash, Clone, Show)]
 pub struct ExistentialBounds {
     pub region_bound: ty::Region,
@@ -3789,7 +3790,8 @@ pub fn ty_sort_string(cx: &ctxt, t: t) -> String {
         ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
         ty_box(_) => "Gc-ptr".to_string(),
         ty_uniq(_) => "box".to_string(),
-        ty_vec(_, _) => "vector".to_string(),
+        ty_vec(_, Some(_)) => "array".to_string(),
+        ty_vec(_, None) => "unsized array".to_string(),
         ty_ptr(_) => "*-ptr".to_string(),
         ty_rptr(_, _) => "&-ptr".to_string(),
         ty_bare_fn(_) => "extern fn".to_string(),
@@ -4864,7 +4866,7 @@ pub fn required_region_bounds(tcx: &ctxt,
         trait_bounds,
         |trait_ref| {
             let bounds = ty::bounds_for_trait_ref(tcx, &*trait_ref);
-            push_region_bounds(bounds.opt_region_bound.as_slice(),
+            push_region_bounds(bounds.region_bounds.as_slice(),
                                bounds.builtin_bounds,
                                &mut all_bounds);
             debug!("from {}: bounds={} all_bounds={}",
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 549f0daef81..48fa6f823b0 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -287,7 +287,7 @@ impl TypeFoldable for ty::ExistentialBounds {
 impl TypeFoldable for ty::ParamBounds {
     fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParamBounds {
         ty::ParamBounds {
-            opt_region_bound: self.opt_region_bound.fold_with(folder),
+            region_bounds: self.region_bounds.fold_with(folder),
             builtin_bounds: self.builtin_bounds.fold_with(folder),
             trait_bounds: self.trait_bounds.fold_with(folder),
         }
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index c46e95cf045..00678eb6380 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -438,7 +438,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
             // FIXME(#12938): This is a hack until we have full support for
             // DST.
             match a_def {
-                def::DefTy(did) | def::DefStruct(did)
+                def::DefTy(did, _) | def::DefStruct(did)
                         if Some(did) == this.tcx().lang_items.owned_box() => {
                     if path.segments
                            .iter()
@@ -462,7 +462,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                               "not enough type parameters supplied to `Box<T>`");
                     Some(ty::mk_err())
                 }
-                def::DefTy(did) | def::DefStruct(did)
+                def::DefTy(did, _) | def::DefStruct(did)
                         if Some(did) == this.tcx().lang_items.gc() => {
                     if path.segments
                            .iter()
@@ -833,7 +833,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                                      result.substs.clone(),
                                      bounds)
                     }
-                    def::DefTy(did) | def::DefStruct(did) => {
+                    def::DefTy(did, _) | def::DefStruct(did) => {
                         ast_path_to_ty(this, rscope, did, path).ty
                     }
                     def::DefTyParam(space, id, n) => {
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 12905763f52..2f5b6e1fa03 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -2005,7 +2005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let region_bounds =
             ty::required_region_bounds(
                 self.tcx(),
-                param_bound.opt_region_bound.as_slice(),
+                param_bound.region_bounds.as_slice(),
                 param_bound.builtin_bounds,
                 param_bound.trait_bounds.as_slice());
         for &r in region_bounds.iter() {
@@ -4937,7 +4937,7 @@ pub fn polytype_for_def(fcx: &FnCtxt,
         return polytype_for_def(fcx, sp, *inner);
       }
       def::DefTrait(_) |
-      def::DefTy(_) |
+      def::DefTy(..) |
       def::DefPrimTy(_) |
       def::DefTyParam(..)=> {
         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 37b77e872ca..a8f2a8f6f1d 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -1880,7 +1880,7 @@ fn param_must_outlive(rcx: &Rcx,
     let param_bound = param_env.bounds.get(param_ty.space, param_ty.idx);
     param_bounds =
         ty::required_region_bounds(rcx.tcx(),
-                                   param_bound.opt_region_bound.as_slice(),
+                                   param_bound.region_bounds.as_slice(),
                                    param_bound.builtin_bounds,
                                    param_bound.trait_bounds.as_slice());
 
diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs
index 60e502786ab..8bcbe4b7929 100644
--- a/src/librustc/middle/typeck/check/regionmanip.rs
+++ b/src/librustc/middle/typeck/check/regionmanip.rs
@@ -327,7 +327,7 @@ impl<'a, 'tcx> Wf<'a, 'tcx> {
 
                 // Inspect bounds on this type parameter for any
                 // region bounds.
-                for &r in type_param_def.bounds.opt_region_bound.iter() {
+                for &r in type_param_def.bounds.region_bounds.iter() {
                     self.stack.push((r, Some(ty)));
                     self.accumulate_from_ty(type_param_ty);
                     self.stack.pop().unwrap();
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index c7b4a78492b..dedb860967c 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -1044,7 +1044,7 @@ fn ty_generics_for_trait(ccx: &CrateCtxt,
         ident: special_idents::type_self,
         def_id: local_def(param_id),
         bounds: ty::ParamBounds {
-            opt_region_bound: None,
+            region_bounds: vec!(),
             builtin_bounds: ty::empty_builtin_bounds(),
             trait_bounds: vec!(self_trait_ref),
         },
@@ -1280,12 +1280,12 @@ fn conv_param_bounds(ccx: &CrateCtxt,
         .map(|b| instantiate_trait_ref(ccx, b, param_ty.to_ty(ccx.tcx)))
         .chain(unboxed_fn_ty_bounds)
         .collect();
-    let opt_region_bound =
-        astconv::compute_opt_region_bound(
-            ccx.tcx, span, builtin_bounds, region_bounds.as_slice(),
-            trait_bounds.as_slice());
+    let region_bounds: Vec<ty::Region> =
+        region_bounds.move_iter()
+        .map(|r| ast_region_to_region(ccx.tcx, r))
+        .collect();
     ty::ParamBounds {
-        opt_region_bound: opt_region_bound,
+        region_bounds: region_bounds,
         builtin_bounds: builtin_bounds,
         trait_bounds: trait_bounds,
     }
diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs
index 499740a78ef..af670f25e56 100644
--- a/src/librustc/middle/typeck/infer/error_reporting.rs
+++ b/src/librustc/middle/typeck/infer/error_reporting.rs
@@ -1235,7 +1235,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                         Some(&d) => d
                     };
                     match a_def {
-                        def::DefTy(did) | def::DefStruct(did) => {
+                        def::DefTy(did, _) | def::DefStruct(did) => {
                             let generics = ty::lookup_item_type(self.tcx, did).generics;
 
                             let expected =
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index ccff8afc50b..ccb01ca620e 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -87,7 +87,12 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
             ret.extend(build_impls(cx, tcx, did).into_iter());
             clean::StructItem(build_struct(cx, tcx, did))
         }
-        def::DefTy(did) => {
+        def::DefTy(did, false) => {
+            record_extern_fqn(cx, did, clean::TypeTypedef);
+            ret.extend(build_impls(cx, tcx, did).into_iter());
+            build_type(cx, tcx, did)
+        }
+        def::DefTy(did, true) => {
             record_extern_fqn(cx, did, clean::TypeEnum);
             ret.extend(build_impls(cx, tcx, did).into_iter());
             build_type(cx, tcx, did)
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index c42d8c79144..c03c56cd223 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1094,6 +1094,7 @@ pub enum TypeKind {
     TypeStruct,
     TypeTrait,
     TypeVariant,
+    TypeTypedef,
 }
 
 impl Primitive {
@@ -2049,7 +2050,8 @@ fn resolve_type(cx: &DocContext, path: Path,
 fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
     let (did, kind) = match def {
         def::DefFn(i, _) => (i, TypeFunction),
-        def::DefTy(i) => (i, TypeEnum),
+        def::DefTy(i, false) => (i, TypeTypedef),
+        def::DefTy(i, true) => (i, TypeEnum),
         def::DefTrait(i) => (i, TypeTrait),
         def::DefStruct(i) => (i, TypeStruct),
         def::DefMod(i) => (i, TypeModule),
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index f36c81f8f8d..6e240b0d8d4 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -45,7 +45,7 @@ impl ItemType {
         match *self {
             Module          => "mod",
             Struct          => "struct",
-            Enum            => "type",
+            Enum            => "enum",
             Function        => "fn",
             Typedef         => "type",
             Static          => "static",
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 169446b0ac0..a0c4283711e 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -308,6 +308,7 @@ pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: Path) ->
                 clean::TypeModule => item_type::Module,
                 clean::TypeStatic => item_type::Static,
                 clean::TypeVariant => item_type::Variant,
+                clean::TypeTypedef => item_type::Typedef,
             }))
         }).collect()
     }).unwrap_or(HashMap::new());
diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css
index 27d54f8ec9d..7eec634405b 100644
--- a/src/librustdoc/html/static/main.css
+++ b/src/librustdoc/html/static/main.css
@@ -229,6 +229,8 @@ nav.sub {
 .content .highlighted.enum { background-color: #b4d1b9; }
 .content .highlighted.struct { background-color: #e7b1a0; }
 .content .highlighted.fn { background-color: #c6afb3; }
+.content .highlighted.method { background-color: #c6afb3; }
+.content .highlighted.ffi { background-color: #c6afb3; }
 
 .docblock.short.nowrap {
     display: block;
@@ -336,11 +338,13 @@ a {
 p a { color: #4e8bca; }
 p a:hover { text-decoration: underline; }
 
-.content span.trait, .block a.current.trait { color: #ed9603; }
-.content span.mod, .block a.current.mod { color: #4d76ae; }
-.content span.enum, .block a.current.enum { color: #5e9766; }
-.content span.struct, .block a.current.struct { color: #e53700; }
-.content span.fn, .block a.current.fn { color: #8c6067; }
+.content span.trait, .content a.trait, .block a.current.trait { color: #ed9603; }
+.content span.mod, .content a.mod, block a.current.mod { color: #4d76ae; }
+.content span.enum, .content a.enum, .block a.current.enum { color: #5e9766; }
+.content span.struct, .content a.struct, .block a.current.struct { color: #e53700; }
+.content span.fn, .content a.fn, .block a.current.fn { color: #8c6067; }
+.content span.method, .content a.method, .block a.current.method { color: #8c6067; }
+.content span.ffi, .content a.ffi, .block a.current.ffi { color: #8c6067; }
 .content .fnname { color: #8c6067; }
 
 .search-input {
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index ad9557bf2c1..6992a966592 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -555,7 +555,7 @@
         // `rustdoc::html::item_type::ItemType` type in Rust.
         var itemTypes = ["mod",
                          "struct",
-                         "type",
+                         "enum",
                          "fn",
                          "type",
                          "static",
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs
index e9c3a2afb03..833c5cd0f98 100644
--- a/src/libserialize/json.rs
+++ b/src/libserialize/json.rs
@@ -234,6 +234,7 @@ pub enum ErrorCode {
     KeyMustBeAString,
     ExpectedColon,
     TrailingCharacters,
+    TrailingComma,
     InvalidEscape,
     InvalidUnicodeCodePoint,
     LoneLeadingSurrogateInHexEscape,
@@ -274,6 +275,7 @@ pub fn error_str(error: ErrorCode) -> &'static str {
         KeyMustBeAString => "key must be a string",
         ExpectedColon => "expected `:`",
         TrailingCharacters => "trailing characters",
+        TrailingComma => "trailing comma",
         InvalidEscape => "invalid escape",
         UnrecognizedHex => "invalid \\u escape (unrecognized hex)",
         NotFourDigit => "invalid \\u escape (not four digits)",
@@ -1681,7 +1683,11 @@ impl<T: Iterator<char>> Parser<T> {
     fn parse_object(&mut self, first: bool) -> JsonEvent {
         if self.ch_is('}') {
             if !first {
-                self.stack.pop();
+                if self.stack.is_empty() {
+                    return self.error_event(TrailingComma);
+                } else {
+                    self.stack.pop();
+                }
             }
             if self.stack.is_empty() {
                 self.state = ParseBeforeFinish;
@@ -2377,7 +2383,7 @@ mod tests {
                 F64Value, StringValue, NullValue, SyntaxError, Key, Index, Stack,
                 InvalidSyntax, InvalidNumber, EOFWhileParsingObject, EOFWhileParsingList,
                 EOFWhileParsingValue, EOFWhileParsingString, KeyMustBeAString, ExpectedColon,
-                TrailingCharacters};
+                TrailingCharacters, TrailingComma};
     use std::{i64, u64, f32, f64, io};
     use std::collections::TreeMap;
 
@@ -3379,6 +3385,7 @@ mod tests {
             }
         }
     }
+
     #[test]
     #[ignore(cfg(target_word_size = "32"))] // FIXME(#14064)
     fn test_read_object_streaming() {
@@ -3393,6 +3400,7 @@ mod tests {
         assert_eq!(last_event("{\"a\":1"),   Error(SyntaxError(EOFWhileParsingObject, 1, 7)));
         assert_eq!(last_event("{\"a\":1 1"), Error(SyntaxError(InvalidSyntax,         1, 8)));
         assert_eq!(last_event("{\"a\":1,"),  Error(SyntaxError(EOFWhileParsingObject, 1, 8)));
+        assert_eq!(last_event("{\"a\":1,}"), Error(SyntaxError(TrailingComma, 1, 8)));
 
         assert_stream_equal(
             "{}",
diff --git a/src/libstd/io/net/mod.rs b/src/libstd/io/net/mod.rs
index 54af83462ee..4bd998d5ed9 100644
--- a/src/libstd/io/net/mod.rs
+++ b/src/libstd/io/net/mod.rs
@@ -19,8 +19,7 @@ pub mod addrinfo;
 pub mod tcp;
 pub mod udp;
 pub mod ip;
-// FIXME(#12093) - this should not be called unix
-pub mod unix;
+pub mod pipe;
 
 fn to_rtio(ip: IpAddr) -> rtio::IpAddr {
     match ip {
diff --git a/src/libstd/io/net/unix.rs b/src/libstd/io/net/pipe.rs
index ea851d44531..bdd58b07d86 100644
--- a/src/libstd/io/net/unix.rs
+++ b/src/libstd/io/net/pipe.rs
@@ -46,7 +46,7 @@ impl UnixStream {
     ///
     /// ```rust
     /// # #![allow(unused_must_use)]
-    /// use std::io::net::unix::UnixStream;
+    /// use std::io::net::pipe::UnixStream;
     ///
     /// let server = Path::new("path/to/my/socket");
     /// let mut stream = UnixStream::connect(&server);
@@ -164,7 +164,7 @@ impl UnixListener {
     /// # fn main() {}
     /// # fn foo() {
     /// # #![allow(unused_must_use)]
-    /// use std::io::net::unix::UnixListener;
+    /// use std::io::net::pipe::UnixListener;
     /// use std::io::{Listener, Acceptor};
     ///
     /// let server = Path::new("/path/to/my/socket");
diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs
index 78d1a2f485a..cfc5fb982b8 100644
--- a/src/libstd/io/test.rs
+++ b/src/libstd/io/test.rs
@@ -34,7 +34,7 @@ macro_rules! iotest (
             use io::net::ip::*;
             use io::net::udp::*;
             #[cfg(unix)]
-            use io::net::unix::*;
+            use io::net::pipe::*;
             use io::timer::*;
             use io::process::*;
             use rt::running_on_valgrind;
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 0ebca006c4c..e1f2f43673f 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -434,8 +434,8 @@ pub mod builtin {
     /// # Example
     ///
     /// ```rust
-    /// let home: &'static str = env!("HOME");
-    /// println!("the home directory at the time of compiling was: {}", home);
+    /// let path: &'static str = env!("PATH");
+    /// println!("the $PATH variable at the time of compiling was: {}", path);
     /// ```
     #[macro_export]
     macro_rules! env( ($name:expr) => ({ /* compiler built-in */ }) )
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 0db1f2282a6..ea392c87723 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -88,14 +88,13 @@ use std::mem;
 use std::rc::Rc;
 use std::iter;
 
-#[allow(non_camel_case_types)]
-#[deriving(PartialEq)]
-pub enum restriction {
-    UNRESTRICTED,
-    RESTRICT_STMT_EXPR,
-    RESTRICT_NO_BAR_OP,
-    RESTRICT_NO_BAR_OR_DOUBLEBAR_OP,
-    RESTRICT_NO_STRUCT_LITERAL,
+bitflags! {
+    flags Restrictions: u8 {
+        static Unrestricted               = 0b0000,
+        static RestrictionStmtExpr        = 0b0001,
+        static RestrictionNoBarOp         = 0b0010,
+        static RestrictionNoStructLiteral = 0b0100
+    }
 }
 
 type ItemInfo = (Ident, Item_, Option<Vec<Attribute> >);
@@ -314,7 +313,7 @@ pub struct Parser<'a> {
     pub buffer_start: int,
     pub buffer_end: int,
     pub tokens_consumed: uint,
-    pub restriction: restriction,
+    pub restrictions: Restrictions,
     pub quote_depth: uint, // not (yet) related to the quasiquoter
     pub reader: Box<Reader+'a>,
     pub interner: Rc<token::IdentInterner>,
@@ -383,7 +382,7 @@ impl<'a> Parser<'a> {
             buffer_start: 0,
             buffer_end: 0,
             tokens_consumed: 0,
-            restriction: UNRESTRICTED,
+            restrictions: Unrestricted,
             quote_depth: 0,
             obsolete_set: HashSet::new(),
             mod_path_stack: Vec::new(),
@@ -2189,7 +2188,7 @@ impl<'a> Parser<'a> {
                     if self.token == token::LBRACE {
                         // This is a struct literal, unless we're prohibited
                         // from parsing struct literals here.
-                        if self.restriction != RESTRICT_NO_STRUCT_LITERAL {
+                        if !self.restrictions.contains(RestrictionNoStructLiteral) {
                             // It's a struct literal.
                             self.bump();
                             let mut fields = Vec::new();
@@ -2651,12 +2650,9 @@ impl<'a> Parser<'a> {
 
         // Prevent dynamic borrow errors later on by limiting the
         // scope of the borrows.
-        match (&self.token, &self.restriction) {
-            (&token::BINOP(token::OR), &RESTRICT_NO_BAR_OP) => return lhs,
-            (&token::BINOP(token::OR),
-                &RESTRICT_NO_BAR_OR_DOUBLEBAR_OP) => return lhs,
-            (&token::OROR, &RESTRICT_NO_BAR_OR_DOUBLEBAR_OP) => return lhs,
-            _ => { }
+        if self.token == token::BINOP(token::OR) &&
+            self.restrictions.contains(RestrictionNoBarOp) {
+            return lhs;
         }
 
         let cur_opt = token_to_binop(&self.token);
@@ -2696,15 +2692,16 @@ impl<'a> Parser<'a> {
     pub fn parse_assign_expr(&mut self) -> P<Expr> {
         let lo = self.span.lo;
         let lhs = self.parse_binops();
+        let restrictions = self.restrictions & RestrictionNoStructLiteral;
         match self.token {
           token::EQ => {
               self.bump();
-              let rhs = self.parse_expr();
+              let rhs = self.parse_expr_res(restrictions);
               self.mk_expr(lo, rhs.span.hi, ExprAssign(lhs, rhs))
           }
           token::BINOPEQ(op) => {
               self.bump();
-              let rhs = self.parse_expr();
+              let rhs = self.parse_expr_res(restrictions);
               let aop = match op {
                   token::PLUS =>    BiAdd,
                   token::MINUS =>   BiSub,
@@ -2730,7 +2727,7 @@ impl<'a> Parser<'a> {
     /// Parse an 'if' expression ('if' token already eaten)
     pub fn parse_if_expr(&mut self) -> P<Expr> {
         let lo = self.last_span.lo;
-        let cond = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL);
+        let cond = self.parse_expr_res(RestrictionNoStructLiteral);
         let thn = self.parse_block();
         let mut els: Option<P<Expr>> = None;
         let mut hi = thn.span.hi;
@@ -2791,7 +2788,7 @@ impl<'a> Parser<'a> {
         let lo = self.last_span.lo;
         let pat = self.parse_pat();
         self.expect_keyword(keywords::In);
-        let expr = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL);
+        let expr = self.parse_expr_res(RestrictionNoStructLiteral);
         let loop_block = self.parse_block();
         let hi = self.span.hi;
 
@@ -2800,7 +2797,7 @@ impl<'a> Parser<'a> {
 
     pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>) -> P<Expr> {
         let lo = self.last_span.lo;
-        let cond = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL);
+        let cond = self.parse_expr_res(RestrictionNoStructLiteral);
         let body = self.parse_block();
         let hi = body.span.hi;
         return self.mk_expr(lo, hi, ExprWhile(cond, body, opt_ident));
@@ -2815,7 +2812,7 @@ impl<'a> Parser<'a> {
 
     fn parse_match_expr(&mut self) -> P<Expr> {
         let lo = self.last_span.lo;
-        let discriminant = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL);
+        let discriminant = self.parse_expr_res(RestrictionNoStructLiteral);
         self.commit_expr_expecting(&*discriminant, token::LBRACE);
         let mut arms: Vec<Arm> = Vec::new();
         while self.token != token::RBRACE {
@@ -2834,7 +2831,7 @@ impl<'a> Parser<'a> {
             guard = Some(self.parse_expr());
         }
         self.expect(&token::FAT_ARROW);
-        let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
+        let expr = self.parse_expr_res(RestrictionStmtExpr);
 
         let require_comma =
             !classify::expr_is_simple_block(&*expr)
@@ -2856,15 +2853,15 @@ impl<'a> Parser<'a> {
 
     /// Parse an expression
     pub fn parse_expr(&mut self) -> P<Expr> {
-        return self.parse_expr_res(UNRESTRICTED);
+        return self.parse_expr_res(Unrestricted);
     }
 
-    /// Parse an expression, subject to the given restriction
-    pub fn parse_expr_res(&mut self, r: restriction) -> P<Expr> {
-        let old = self.restriction;
-        self.restriction = r;
+    /// Parse an expression, subject to the given restrictions
+    pub fn parse_expr_res(&mut self, r: Restrictions) -> P<Expr> {
+        let old = self.restrictions;
+        self.restrictions = r;
         let e = self.parse_assign_expr();
-        self.restriction = old;
+        self.restrictions = old;
         return e;
     }
 
@@ -3153,9 +3150,9 @@ impl<'a> Parser<'a> {
                     self.look_ahead(2, |t| {
                         *t != token::COMMA && *t != token::RBRACKET
                     }) {
-                let start = self.parse_expr_res(RESTRICT_NO_BAR_OP);
+                let start = self.parse_expr_res(RestrictionNoBarOp);
                 self.eat(&token::DOTDOT);
-                let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
+                let end = self.parse_expr_res(RestrictionNoBarOp);
                 pat = PatRange(start, end);
             } else if is_plain_ident(&self.token) && !can_be_enum_or_struct {
                 let id = self.parse_ident();
@@ -3441,7 +3438,7 @@ impl<'a> Parser<'a> {
                     check_expected_item(self, found_attrs);
 
                     // Remainder are line-expr stmts.
-                    let e = self.parse_expr_res(RESTRICT_STMT_EXPR);
+                    let e = self.parse_expr_res(RestrictionStmtExpr);
                     P(spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID)))
                 }
             }
@@ -3450,7 +3447,7 @@ impl<'a> Parser<'a> {
 
     /// Is this expression a successfully-parsed statement?
     fn expr_is_complete(&mut self, e: &Expr) -> bool {
-        self.restriction == RESTRICT_STMT_EXPR &&
+        self.restrictions.contains(RestrictionStmtExpr) &&
             !classify::expr_requires_semi_to_be_stmt(e)
     }
 
diff --git a/src/snapshots.txt b/src/snapshots.txt
index d2a1fd11597..86fa0a51f90 100644
--- a/src/snapshots.txt
+++ b/src/snapshots.txt
@@ -1,3 +1,12 @@
+S 2014-09-16 828e075
+  winnt-x86_64 ce1e9d7f6967bfa368853e7c968e1626cc319951
+  winnt-i386 a8bd994666dfe683a5d7922c7998500255780724
+  linux-x86_64 88ff474db96c6ffc5c1dc7a43442cbe1cd88c8a2
+  linux-i386 7a731891f726c8a0590b142a4e8924c5e8b22e8d
+  freebsd-x86_64 e67a56f76484f775cd4836dedb2d1069ab5d7921
+  macos-i386 f48023648a77e89086f4a2b39d76b09e4fff032d
+  macos-x86_64 2ad6457b2b3036f87eae7581d64ee5341a07fb06
+
 S 2014-09-10 6faa4f3
   winnt-x86_64 939eb546469cb936441cff3b6f2478f562f77c46
   winnt-i386 cfe4f8b519bb9d62588f9310a8f94bc919d5423b
diff --git a/src/test/auxiliary/static_priv_by_default.rs b/src/test/auxiliary/static_priv_by_default.rs
index b756eb2b582..6951ed729b2 100644
--- a/src/test/auxiliary/static_priv_by_default.rs
+++ b/src/test/auxiliary/static_priv_by_default.rs
@@ -24,6 +24,7 @@ mod foo {
     pub fn b() {}
     pub struct c;
     pub enum d {}
+    pub type e = int;
 
     pub struct A(());
 
@@ -36,6 +37,7 @@ mod foo {
     pub fn reexported_b() {}
     pub struct reexported_c;
     pub enum reexported_d {}
+    pub type reexported_e = int;
 }
 
 pub mod bar {
@@ -43,14 +45,17 @@ pub mod bar {
     pub use foo::reexported_b as f;
     pub use foo::reexported_c as g;
     pub use foo::reexported_d as h;
+    pub use foo::reexported_e as i;
 }
 
 pub static a: int = 0;
 pub fn b() {}
 pub struct c;
 pub enum d {}
+pub type e = int;
 
-static i: int = 0;
-fn j() {}
-struct k;
-enum l {}
+static j: int = 0;
+fn k() {}
+struct l;
+enum m {}
+type n = int;
diff --git a/src/test/bench/shootout-pidigits.rs b/src/test/bench/shootout-pidigits.rs
deleted file mode 100644
index d22633b3412..00000000000
--- a/src/test/bench/shootout-pidigits.rs
+++ /dev/null
@@ -1,128 +0,0 @@
-// The Computer Language Benchmarks Game
-// http://benchmarksgame.alioth.debian.org/
-//
-// contributed by the Rust Project Developers
-
-// Copyright (c) 2013-2014 The Rust Project Developers
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-// - Redistributions of source code must retain the above copyright
-//   notice, this list of conditions and the following disclaimer.
-//
-// - Redistributions in binary form must reproduce the above copyright
-//   notice, this list of conditions and the following disclaimer in
-//   the documentation and/or other materials provided with the
-//   distribution.
-//
-// - Neither the name of "The Computer Language Benchmarks Game" nor
-//   the name of "The Computer Language Shootout Benchmarks" nor the
-//   names of its contributors may be used to endorse or promote
-//   products derived from this software without specific prior
-//   written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-// OF THE POSSIBILITY OF SUCH DAMAGE.
-
-extern crate num;
-
-use std::from_str::FromStr;
-use std::num::One;
-use std::num::Zero;
-use std::num::FromPrimitive;
-use num::Integer;
-use num::bigint::BigInt;
-
-struct Context {
-    numer: BigInt,
-    accum: BigInt,
-    denom: BigInt,
-}
-
-impl Context {
-    fn new() -> Context {
-        Context {
-            numer: One::one(),
-            accum: Zero::zero(),
-            denom: One::one(),
-        }
-    }
-
-    fn from_int(i: int) -> BigInt {
-        FromPrimitive::from_int(i).unwrap()
-    }
-
-    fn extract_digit(&self) -> int {
-        if self.numer > self.accum {return -1;}
-        let (q, r) =
-            (self.numer * Context::from_int(3) + self.accum)
-            .div_rem(&self.denom);
-        if r + self.numer >= self.denom {return -1;}
-        q.to_int().unwrap()
-    }
-
-    fn next_term(&mut self, k: int) {
-        let y2 = Context::from_int(k * 2 + 1);
-        self.accum = (self.accum + (self.numer << 1)) * y2;
-        self.numer = self.numer * Context::from_int(k);
-        self.denom = self.denom * y2;
-    }
-
-    fn eliminate_digit(&mut self, d: int) {
-        let d = Context::from_int(d);
-        let ten = Context::from_int(10);
-        self.accum = (self.accum - self.denom * d) * ten;
-        self.numer = self.numer * ten;
-    }
-}
-
-fn pidigits(n: int) {
-    let mut k = 0;
-    let mut context = Context::new();
-
-    for i in range(1, n + 1) {
-        let mut d;
-        loop {
-            k += 1;
-            context.next_term(k);
-            d = context.extract_digit();
-            if d != -1 {break;}
-        }
-
-        print!("{}", d);
-        if i % 10 == 0 {print!("\t:{}\n", i);}
-
-        context.eliminate_digit(d);
-    }
-
-    let m = n % 10;
-    if m != 0 {
-        for _ in range(m, 10) { print!(" "); }
-        print!("\t:{}\n", n);
-    }
-}
-
-fn main() {
-    let args = std::os::args();
-    let args = args.as_slice();
-    let n = if args.len() < 2 {
-        512
-    } else {
-        FromStr::from_str(args[1].as_slice()).unwrap()
-    };
-    pidigits(n);
-}
diff --git a/src/test/compile-fail/array-not-vector.rs b/src/test/compile-fail/array-not-vector.rs
new file mode 100644
index 00000000000..79d4ada41e8
--- /dev/null
+++ b/src/test/compile-fail/array-not-vector.rs
@@ -0,0 +1,16 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let _x: int = [1i, 2, 3]; //~ ERROR expected int, found array
+
+    let x: &[int] = &[1, 2, 3];
+    let _y: &int = x; //~ ERROR expected int, found unsized array
+}
diff --git a/src/test/compile-fail/issue-17283.rs b/src/test/compile-fail/issue-17283.rs
new file mode 100644
index 00000000000..122c1f08395
--- /dev/null
+++ b/src/test/compile-fail/issue-17283.rs
@@ -0,0 +1,37 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the parser does not attempt to parse struct literals
+// within assignments in if expressions.
+
+struct Foo {
+    foo: uint
+}
+
+fn main() {
+    let x = 1u;
+    let y: Foo;
+
+    // `x { ... }` should not be interpreted as a struct literal here
+    if x = x {
+        //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ())
+        println!("{}", x);
+    }
+    // Explicit parentheses on the left should match behavior of above
+    if (x = x) {
+        //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ())
+        println!("{}", x);
+    }
+    // The struct literal interpretation is fine with explicit parentheses on the right
+    if y = (Foo { foo: x }) {
+        //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ())
+        println!("{}", x);
+    }
+}
diff --git a/src/test/compile-fail/lint-unnecessary-import-braces.rs b/src/test/compile-fail/lint-unnecessary-import-braces.rs
new file mode 100644
index 00000000000..c44918d9879
--- /dev/null
+++ b/src/test/compile-fail/lint-unnecessary-import-braces.rs
@@ -0,0 +1,21 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(unnecessary_import_braces)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+use test::{A}; //~ ERROR braces around A is unnecessary
+
+mod test {
+    pub struct A;
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs
index 68dbacaae5c..41a30e23b22 100644
--- a/src/test/compile-fail/liveness-unused.rs
+++ b/src/test/compile-fail/liveness-unused.rs
@@ -82,5 +82,23 @@ fn f4b() -> int {
     }
 }
 
+fn f5a() {
+    for x in range(1i, 10) { }
+    //~^ ERROR unused variable: `x`
+}
+
+fn f5b() {
+    for (x, _) in [1i, 2, 3].iter().enumerate() { }
+    //~^ ERROR unused variable: `x`
+}
+
+fn f5c() {
+    for (_, x) in [1i, 2, 3].iter().enumerate() {
+    //~^ ERROR unused variable: `x`
+        continue;
+        std::os::set_exit_status(*x); //~ WARNING unreachable statement
+    }
+}
+
 fn main() {
 }
diff --git a/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs b/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs
index 40cff3e466b..6b3c92e0028 100644
--- a/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs
+++ b/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs
@@ -35,10 +35,10 @@ fn test<
     'a,
     'b,
     A:IsStatic,
-    B:Is<'a>+Is2<'b>,    //~ ERROR ambiguous lifetime bound
+    B:Is<'a>+Is2<'b>, // OK in a parameter, but not an object type.
     C:'b+Is<'a>+Is2<'b>,
     D:Is<'a>+Is2<'static>,
-    E:'a+'b //~ ERROR only a single explicit lifetime bound is permitted
+    E:'a+'b           // OK in a parameter, but not an object type.
 >() { }
 
 fn main() { }
diff --git a/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs b/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs
new file mode 100644
index 00000000000..cec785c6e96
--- /dev/null
+++ b/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs
@@ -0,0 +1,32 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Various tests where we over type parameters with multiple lifetime
+// bounds.
+
+trait SomeTrait { fn get(&self) -> int; }
+
+fn make_object_good1<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'a> {
+    // A outlives 'a AND 'b...
+    box v as Box<SomeTrait+'a> // ...hence this type is safe.
+}
+
+fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'b> {
+    // A outlives 'a AND 'b...
+    box v as Box<SomeTrait+'b> // ...hence this type is safe.
+}
+
+fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
+    // A outlives 'a AND 'b...but not 'c.
+    box v as Box<SomeTrait+'a> //~ ERROR mismatched types
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/xcrate-private-by-default.rs b/src/test/compile-fail/xcrate-private-by-default.rs
index 70b2ea87ac1..43be96965d0 100644
--- a/src/test/compile-fail/xcrate-private-by-default.rs
+++ b/src/test/compile-fail/xcrate-private-by-default.rs
@@ -20,22 +20,26 @@ fn main() {
     static_priv_by_default::b;
     static_priv_by_default::c;
     foo::<static_priv_by_default::d>();
+    foo::<static_priv_by_default::e>();
 
     // publicly re-exported items should be available
     static_priv_by_default::bar::e;
     static_priv_by_default::bar::f;
     static_priv_by_default::bar::g;
     foo::<static_priv_by_default::bar::h>();
+    foo::<static_priv_by_default::bar::i>();
 
     // private items at the top should be inaccessible
-    static_priv_by_default::i;
-    //~^ ERROR: static `i` is private
     static_priv_by_default::j;
-    //~^ ERROR: function `j` is private
+    //~^ ERROR: static `j` is private
     static_priv_by_default::k;
-    //~^ ERROR: struct `k` is private
-    foo::<static_priv_by_default::l>();
-    //~^ ERROR: type `l` is private
+    //~^ ERROR: function `k` is private
+    static_priv_by_default::l;
+    //~^ ERROR: struct `l` is private
+    foo::<static_priv_by_default::m>();
+    //~^ ERROR: enum `m` is private
+    foo::<static_priv_by_default::n>();
+    //~^ ERROR: type `n` is private
 
     // public items in a private mod should be inaccessible
     static_priv_by_default::foo::a;
@@ -45,5 +49,7 @@ fn main() {
     static_priv_by_default::foo::c;
     //~^ ERROR: struct `c` is private
     foo::<static_priv_by_default::foo::d>();
-    //~^ ERROR: type `d` is private
+    //~^ ERROR: enum `d` is private
+    foo::<static_priv_by_default::foo::e>();
+    //~^ ERROR: type `e` is private
 }
diff --git a/src/test/run-pass/issue-17302.rs b/src/test/run-pass/issue-17302.rs
new file mode 100644
index 00000000000..50583c7d127
--- /dev/null
+++ b/src/test/run-pass/issue-17302.rs
@@ -0,0 +1,34 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+static mut DROPPED: [bool, ..2] = [false, false];
+
+struct A(uint);
+struct Foo { _a: A, _b: int }
+
+impl Drop for A {
+    fn drop(&mut self) {
+        let A(i) = *self;
+        unsafe { DROPPED[i] = true; }
+    }
+}
+
+fn main() {
+    {
+        Foo {
+            _a: A(0),
+            ..Foo { _a: A(1), _b: 2 }
+        };
+    }
+    unsafe {
+        assert!(DROPPED[0]);
+        assert!(DROPPED[1]);
+    }
+}
diff --git a/src/test/run-pass/regions-close-over-type-parameter-successfully.rs b/src/test/run-pass/regions-close-over-type-parameter-successfully.rs
new file mode 100644
index 00000000000..5dba80ad38a
--- /dev/null
+++ b/src/test/run-pass/regions-close-over-type-parameter-successfully.rs
@@ -0,0 +1,30 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// A test where we (successfully) close over a reference into
+// an object.
+
+trait SomeTrait { fn get(&self) -> int; }
+
+impl<'a> SomeTrait for &'a int {
+    fn get(&self) -> int {
+        **self
+    }
+}
+
+fn make_object<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
+    box v as Box<SomeTrait+'a>
+}
+
+fn main() {
+    let i: int = 22;
+    let obj = make_object(&i);
+    assert_eq!(22, obj.get());
+}