about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-06-13 20:57:30 +0000
committerbors <bors@rust-lang.org>2014-06-13 20:57:30 +0000
commit63dcc9a4df50680686bee852e82a52fbc59b3c27 (patch)
tree2a5a941e0da26795babf286edf77f9f225bc906d
parente7f11f20e5e72a3b22863a9913df94303321a5ce (diff)
parentb7af25060a1b0451cb06085ba5893980bc4e5333 (diff)
downloadrust-63dcc9a4df50680686bee852e82a52fbc59b3c27.tar.gz
rust-63dcc9a4df50680686bee852e82a52fbc59b3c27.zip
auto merge of #14867 : alexcrichton/rust/rollup, r=alexcrichton
-rwxr-xr-xconfigure73
-rw-r--r--mk/stage0.mk4
-rw-r--r--src/libcollections/treemap.rs2
-rw-r--r--src/libcore/any.rs18
-rw-r--r--src/libcore/intrinsics.rs14
-rw-r--r--src/libcore/mem.rs25
-rw-r--r--src/libnative/io/c_win32.rs25
-rw-r--r--src/librustc/driver/driver.rs3
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/middle/dead.rs60
-rw-r--r--src/librustc/middle/intrinsicck.rs155
-rw-r--r--src/librustc/middle/resolve_lifetime.rs8
-rw-r--r--src/librustc/middle/trans/base.rs6
-rw-r--r--src/librustc/middle/trans/intrinsic.rs40
-rw-r--r--src/librustc/middle/ty.rs23
-rw-r--r--src/librustc/middle/typeck/astconv.rs1
-rw-r--r--src/librustc/middle/typeck/check/mod.rs6
-rw-r--r--src/librustc/middle/typeck/infer/error_reporting.rs4
-rw-r--r--src/librustc/plugin/load.rs6
-rw-r--r--src/librustc/util/ppaux.rs2
-rw-r--r--src/librustdoc/clean/mod.rs3
-rw-r--r--src/librustdoc/plugins.rs7
-rw-r--r--src/librustrt/mutex.rs78
-rw-r--r--src/librustrt/unwind.rs2
-rw-r--r--src/libstd/dynamic_lib.rs5
-rw-r--r--src/libstd/io/fs.rs271
-rw-r--r--src/libstd/io/mod.rs51
-rw-r--r--src/libstd/rt/backtrace.rs8
-rw-r--r--src/libsync/mutex.rs11
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/ast_util.rs1
-rw-r--r--src/libsyntax/ext/build.rs31
-rw-r--r--src/libsyntax/ext/bytes.rs14
-rw-r--r--src/libsyntax/ext/env.rs2
-rw-r--r--src/libsyntax/ext/format.rs2
-rw-r--r--src/libsyntax/ext/quote.rs9
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs3
-rw-r--r--src/libsyntax/fold.rs1
-rw-r--r--src/libsyntax/parse/lexer/mod.rs39
-rw-r--r--src/libsyntax/parse/mod.rs3
-rw-r--r--src/libsyntax/parse/parser.rs144
-rw-r--r--src/libsyntax/parse/token.rs103
-rw-r--r--src/libsyntax/print/pprust.rs38
-rw-r--r--src/libsyntax/visit.rs2
-rw-r--r--src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs4
-rw-r--r--src/test/compile-fail/hygienic-label-1.rs2
-rw-r--r--src/test/compile-fail/hygienic-label-2.rs2
-rw-r--r--src/test/compile-fail/hygienic-label-3.rs2
-rw-r--r--src/test/compile-fail/hygienic-label-4.rs2
-rw-r--r--src/test/compile-fail/issue-14845.rs24
-rw-r--r--src/test/compile-fail/issue-7013.rs2
-rw-r--r--src/test/compile-fail/kindck-copy.rs8
-rw-r--r--src/test/compile-fail/kindck-send.rs10
-rw-r--r--src/test/compile-fail/regions-name-static.rs2
-rw-r--r--src/test/compile-fail/trait-bounds-cant-coerce.rs6
-rw-r--r--src/test/compile-fail/trait-bounds-sugar.rs8
-rw-r--r--src/test/compile-fail/transmute-different-sizes.rs29
-rw-r--r--src/test/compile-fail/transmute-type-parameters.rs48
-rw-r--r--src/test/pretty/path-type-bounds.rs6
-rw-r--r--src/test/run-fail/fail-macro-any.rs2
-rw-r--r--src/test/run-pass-fulldeps/quote-tokens.rs12
-rw-r--r--src/test/run-pass/alignment-gep-tup-like-1.rs2
-rw-r--r--src/test/run-pass/as-precedence.rs18
-rw-r--r--src/test/run-pass/capturing-logging.rs2
-rw-r--r--src/test/run-pass/close-over-big-then-small-data.rs4
-rw-r--r--src/test/run-pass/issue-14837.rs20
-rw-r--r--src/test/run-pass/loop-label-shadowing.rs19
-rw-r--r--src/test/run-pass/trait-bounds-basic.rs10
-rw-r--r--src/test/run-pass/trait-bounds-in-arc.rs14
-rw-r--r--src/test/run-pass/trait-cast.rs6
-rw-r--r--src/test/run-pass/trait-contravariant-self.rs6
71 files changed, 1165 insertions, 411 deletions
diff --git a/configure b/configure
index fe29e488316..3a306085c77 100755
--- a/configure
+++ b/configure
@@ -416,7 +416,6 @@ opt mingw-cross 0 "cross-compile for win32 using mingw"
 opt clang 0 "prefer clang to gcc for building the runtime"
 opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
 opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
-opt pax-flags 0 "apply PaX flags to rustc binaries (required for GRSecurity/PaX-patched kernels)"
 opt inject-std-version 1 "inject the current compiler version of libstd into programs"
 opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
 opt rpath 1 "build rpaths into rustc itself"
@@ -518,12 +517,6 @@ then
     fi
 fi
 
-if [ "$CFG_OSTYPE" = "unknown-linux-gnu" ]
-then
-    probe CFG_PAXCTL           paxctl /sbin/paxctl
-    probe CFG_ZCAT             zcat
-fi
-
 step_msg "looking for target specific programs"
 
 probe CFG_ADB        adb
@@ -546,51 +539,6 @@ then
     fi
 fi
 
-if [ "$CFG_OSTYPE" = "unknown-linux-gnu" ]
-then
-    if [ ! -z "$CFG_ENABLE_PAX_FLAGS" -a -z "$CFG_PAXCTL" ]
-    then
-        err "enabled PaX markings but no paxctl binary found"
-    fi
-
-    if [ -z "$CFG_DISABLE_PAX_FLAGS" ]
-    then
-        # GRSecurity/PaX detection. This can be very flaky.
-        GRSEC_DETECTED=
-
-        # /dev/grsec only exists if CONFIG_GRKERNSEC_NO_RBAC is not set.
-        # /proc/sys/kernel/grsecurity is not available if ÇONFIG_GRKERNSEC_SYSCTL is not set.
-        if [ -e /dev/grsec -o -d /proc/sys/kernel/grsecurity ]
-        then
-            GRSEC_DETECTED=1
-        # /proc/config.gz is normally only available to root, and only if CONFIG_IKCONFIG_PROC has been set.
-        elif [ -r /proc/config.gz -a ! -z "$CFG_ZCAT" ]
-        then
-            if "$CFG_ZCAT" /proc/config.gz | grep --quiet "CONFIG_GRKERNSEC=y"
-            then
-                GRSEC_DETECTED=1
-            fi
-        # Flaky.
-        elif grep --quiet grsec /proc/version
-        then
-            GRSEC_DETECTED=1
-        fi
-
-        if [ ! -z "$GRSEC_DETECTED" ]
-        then
-            step_msg "GRSecurity: yes"
-            if [ ! -z "$CFG_PAXCTL" ]
-            then
-                CFG_ENABLE_PAX_FLAGS=1
-            else
-                warn "GRSecurity kernel detected but no paxctl binary found: not setting CFG_ENABLE_PAX_FLAGS"
-            fi
-        else
-            step_msg "GRSecurity: no"
-        fi
-    fi
-fi
-
 BIN_SUF=
 if [ "$CFG_OSTYPE" = "pc-mingw32" ] || [ "$CFG_OSTYPE" = "w64-mingw32" ]
 then
@@ -942,8 +890,25 @@ then
     msg "git: submodule sync"
     "${CFG_GIT}" submodule sync
 
+    msg "git: submodule init"
+    "${CFG_GIT}" submodule init
+
+    # Disable submodules that we're not using
+    if [ ! -z "${CFG_LLVM_ROOT}" ]; then
+        msg "git: submodule deinit src/llvm"
+        "${CFG_GIT}" submodule deinit src/llvm
+    fi
+    if [ ! -z "${CFG_JEMALLOC_ROOT}" ]; then
+        msg "git: submodule deinit src/jemalloc"
+        "${CFG_GIT}" submodule deinit src/jemalloc
+    fi
+    if [ ! -z "${CFG_LIBUV_ROOT}" ]; then
+        msg "git: submodule deinit src/libuv"
+        "${CFG_GIT}" submodule deinit src/libuv
+    fi
+
     msg "git: submodule update"
-    "${CFG_GIT}" submodule update --init
+    "${CFG_GIT}" submodule update
     need_ok "git failed"
 
     msg "git: submodule foreach sync"
@@ -951,7 +916,7 @@ then
     need_ok "git failed"
 
     msg "git: submodule foreach update"
-    "${CFG_GIT}" submodule update --init --recursive
+    "${CFG_GIT}" submodule update --recursive
     need_ok "git failed"
 
     # NB: this is just for the sake of getting the submodule SHA1 values
diff --git a/mk/stage0.mk b/mk/stage0.mk
index 080e733724d..972cfecea71 100644
--- a/mk/stage0.mk
+++ b/mk/stage0.mk
@@ -18,10 +18,6 @@ ifdef CFG_ENABLE_LOCAL_RUST
 	$(Q)$(S)src/etc/local_stage0.sh $(CFG_BUILD) $(CFG_LOCAL_RUST_ROOT) rustlib
 else
 	$(Q)$(CFG_PYTHON) $(S)src/etc/get-snapshot.py $(CFG_BUILD) $(SNAPSHOT_FILE)
-ifdef CFG_ENABLE_PAX_FLAGS
-	@$(call E, apply PaX flags: $@)
-	@"$(CFG_PAXCTL)" -cm "$@"
-endif
 endif
 	$(Q)touch $@
 
diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs
index b59caa9375e..086b073a9c4 100644
--- a/src/libcollections/treemap.rs
+++ b/src/libcollections/treemap.rs
@@ -761,7 +761,7 @@ pub struct IntersectionItems<'a, T> {
     b: Peekable<&'a T, SetItems<'a, T>>,
 }
 
-/// Lazy iterator producing elements in the set intersection (in-order)
+/// Lazy iterator producing elements in the set union (in-order)
 pub struct UnionItems<'a, T> {
     a: Peekable<&'a T, SetItems<'a, T>>,
     b: Peekable<&'a T, SetItems<'a, T>>,
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index 2a03eacf13c..2657cd53483 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Traits for dynamic typing of any type (through runtime reflection)
+//! Traits for dynamic typing of any `'static` type (through runtime reflection)
 //!
 //! This module implements the `Any` trait, which enables dynamic typing
-//! of any type, through runtime reflection.
+//! of any `'static` type through runtime reflection.
 //!
 //! `Any` itself can be used to get a `TypeId`, and has more features when used as a trait object.
 //! As `&Any` (a borrowed trait object), it has the `is` and `as_ref` methods, to test if the
@@ -32,8 +32,10 @@ pub enum Void { }
 // Any trait
 ///////////////////////////////////////////////////////////////////////////////
 
-/// The `Any` trait is implemented by all types, and can be used as a trait object
-/// for dynamic typing
+/// The `Any` trait is implemented by all `'static` types, and can be used for dynamic typing
+///
+/// Every type with no non-`'static` references implements `Any`, so `Any` can be used as a trait
+/// object to emulate the effects dynamic typing.
 pub trait Any {
     /// Get the `TypeId` of `self`
     fn get_type_id(&self) -> TypeId;
@@ -261,6 +263,14 @@ mod tests {
         let s = format!("{}", b);
         assert_eq!(s.as_slice(), "&Any");
     }
+
+    #[test]
+    fn any_fixed_vec() {
+        let test = [0u, ..8];
+        let test = &test as &Any;
+        assert!(test.is::<[uint, ..8]>());
+        assert!(!test.is::<[uint, ..10]>());
+    }
 }
 
 #[cfg(test)]
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index d61416a68e0..33f2a49d6d5 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -307,6 +307,20 @@ extern "rust-intrinsic" {
     /// `forget` is unsafe because the caller is responsible for
     /// ensuring the argument is deallocated already.
     pub fn forget<T>(_: T) -> ();
+
+    /// Unsafely transforms a value of one type into a value of another type.
+    ///
+    /// Both types must have the same size and alignment, and this guarantee
+    /// is enforced at compile-time.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::mem;
+    ///
+    /// let v: &[u8] = unsafe { mem::transmute("L") };
+    /// assert!(v == [76u8]);
+    /// ```
     pub fn transmute<T,U>(e: T) -> U;
 
     /// Returns `true` if a type requires drop glue.
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 8933c95350d..237efcd0096 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -17,6 +17,8 @@ use ptr;
 use intrinsics;
 use intrinsics::{bswap16, bswap32, bswap64};
 
+pub use intrinsics::transmute;
+
 /// Returns the size of a type in bytes.
 #[inline]
 #[stable]
@@ -412,29 +414,6 @@ pub fn drop<T>(_x: T) { }
 #[stable]
 pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing) }
 
-/// Unsafely transforms a value of one type into a value of another type.
-///
-/// Both types must have the same size and alignment, and this guarantee is
-/// enforced at compile-time.
-///
-/// # Example
-///
-/// ```rust
-/// use std::mem;
-///
-/// let v: &[u8] = unsafe { mem::transmute("L") };
-/// assert!(v == [76u8]);
-/// ```
-#[inline]
-#[unstable = "this function will be modified to reject invocations of it which \
-              cannot statically prove that T and U are the same size. For \
-              example, this function, as written today, will be rejected in \
-              the future because the size of T and U cannot be statically \
-              known to be the same"]
-pub unsafe fn transmute<T, U>(thing: T) -> U {
-    intrinsics::transmute(thing)
-}
-
 /// Interprets `src` as `&U`, and then reads `src` without moving the contained
 /// value.
 ///
diff --git a/src/libnative/io/c_win32.rs b/src/libnative/io/c_win32.rs
index e855b8bd4f2..1b6525c6e38 100644
--- a/src/libnative/io/c_win32.rs
+++ b/src/libnative/io/c_win32.rs
@@ -77,15 +77,20 @@ pub mod compat {
         fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID;
     }
 
-    // store_func() is idempotent, so using relaxed ordering for the atomics should be enough.
-    // This way, calling a function in this compatibility layer (after it's loaded) shouldn't
-    // be any slower than a regular DLL call.
-    unsafe fn store_func<T: Copy>(ptr: *mut T, module: &str, symbol: &str, fallback: T) {
+    // store_func() is idempotent, so using relaxed ordering for the atomics
+    // should be enough.  This way, calling a function in this compatibility
+    // layer (after it's loaded) shouldn't be any slower than a regular DLL
+    // call.
+    unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) {
         let module = module.to_utf16().append_one(0);
         symbol.with_c_str(|symbol| {
             let handle = GetModuleHandleW(module.as_ptr());
-            let func: Option<T> = transmute(GetProcAddress(handle, symbol));
-            atomic_store_relaxed(ptr, func.unwrap_or(fallback))
+            let func: uint = transmute(GetProcAddress(handle, symbol));
+            atomic_store_relaxed(ptr, if func == 0 {
+                fallback
+            } else {
+                func
+            })
         })
     }
 
@@ -109,10 +114,10 @@ pub mod compat {
 
                 extern "system" fn thunk($($argname: $argtype),*) -> $rettype {
                     unsafe {
-                        ::io::c::compat::store_func(&mut ptr,
-                                                             stringify!($module),
-                                                             stringify!($symbol),
-                                                             fallback);
+                        ::io::c::compat::store_func(&mut ptr as *mut _ as *mut uint,
+                                                    stringify!($module),
+                                                    stringify!($symbol),
+                                                    fallback as uint);
                         ::std::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
                     }
                 }
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 880c1d6d510..2268ce84365 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -333,6 +333,9 @@ pub fn phase_3_run_analysis_passes(sess: Session,
             time(time_passes, "privacy checking", maps, |(a, b)|
                  middle::privacy::check_crate(&ty_cx, &exp_map2, a, b, krate));
 
+    time(time_passes, "intrinsic checking", (), |_|
+         middle::intrinsicck::check_crate(&ty_cx, krate));
+
     time(time_passes, "effect checking", (), |_|
          middle::effect::check_crate(&ty_cx, krate));
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index f79aaa40d21..1e39aaa3a5f 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -85,6 +85,7 @@ pub mod middle {
     pub mod dependency_format;
     pub mod weak_lang_items;
     pub mod save;
+    pub mod intrinsicck;
 }
 
 pub mod front {
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 834dc43ee6e..aa74614b78c 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -55,6 +55,11 @@ struct MarkSymbolVisitor<'a> {
     live_symbols: Box<HashSet<ast::NodeId>>,
 }
 
+#[deriving(Clone)]
+struct MarkSymbolVisitorContext {
+    struct_has_extern_repr: bool
+}
+
 impl<'a> MarkSymbolVisitor<'a> {
     fn new(tcx: &'a ty::ctxt,
            worklist: Vec<ast::NodeId>) -> MarkSymbolVisitor<'a> {
@@ -170,48 +175,61 @@ impl<'a> MarkSymbolVisitor<'a> {
     }
 
     fn visit_node(&mut self, node: &ast_map::Node) {
+        let ctxt = MarkSymbolVisitorContext {
+            struct_has_extern_repr: false
+        };
         match *node {
             ast_map::NodeItem(item) => {
                 match item.node {
-                    ast::ItemStruct(struct_def, _) => {
+                    ast::ItemStruct(..) => {
                         let has_extern_repr = item.attrs.iter().fold(attr::ReprAny, |acc, attr| {
                             attr::find_repr_attr(self.tcx.sess.diagnostic(), attr, acc)
                         }) == attr::ReprExtern;
-                        let live_fields = struct_def.fields.iter().filter(|f| {
-                            has_extern_repr || match f.node.kind {
-                                ast::NamedField(_, ast::Public) => true,
-                                _ => false
-                            }
+
+                        visit::walk_item(self, &*item, MarkSymbolVisitorContext {
+                            struct_has_extern_repr: has_extern_repr,
+                            ..(ctxt)
                         });
-                        self.live_symbols.extend(live_fields.map(|f| f.node.id));
-                        visit::walk_item(self, &*item, ());
                     }
                     ast::ItemFn(..)
-                    | ast::ItemTy(..)
                     | ast::ItemEnum(..)
+                    | ast::ItemTy(..)
                     | ast::ItemStatic(..) => {
-                        visit::walk_item(self, &*item, ());
+                        visit::walk_item(self, &*item, ctxt);
                     }
                     _ => ()
                 }
             }
             ast_map::NodeTraitMethod(trait_method) => {
-                visit::walk_trait_method(self, &*trait_method, ());
+                visit::walk_trait_method(self, &*trait_method, ctxt);
             }
             ast_map::NodeMethod(method) => {
-                visit::walk_block(self, &*method.body, ());
+                visit::walk_block(self, &*method.body, ctxt);
             }
             ast_map::NodeForeignItem(foreign_item) => {
-                visit::walk_foreign_item(self, &*foreign_item, ());
+                visit::walk_foreign_item(self, &*foreign_item, ctxt);
             }
             _ => ()
         }
     }
 }
 
-impl<'a> Visitor<()> for MarkSymbolVisitor<'a> {
+impl<'a> Visitor<MarkSymbolVisitorContext> for MarkSymbolVisitor<'a> {
+
+    fn visit_struct_def(&mut self, def: &ast::StructDef, _: ast::Ident, _: &ast::Generics,
+                        _: ast::NodeId, ctxt: MarkSymbolVisitorContext) {
+        let live_fields = def.fields.iter().filter(|f| {
+            ctxt.struct_has_extern_repr || match f.node.kind {
+                ast::NamedField(_, ast::Public) => true,
+                _ => false
+            }
+        });
+        self.live_symbols.extend(live_fields.map(|f| f.node.id));
+
+        visit::walk_struct_def(self, def, ctxt);
+    }
 
-    fn visit_expr(&mut self, expr: &ast::Expr, _: ()) {
+    fn visit_expr(&mut self, expr: &ast::Expr, ctxt: MarkSymbolVisitorContext) {
         match expr.node {
             ast::ExprMethodCall(..) => {
                 self.lookup_and_handle_method(expr.id, expr.span);
@@ -222,10 +240,10 @@ impl<'a> Visitor<()> for MarkSymbolVisitor<'a> {
             _ => ()
         }
 
-        visit::walk_expr(self, expr, ())
+        visit::walk_expr(self, expr, ctxt);
     }
 
-    fn visit_pat(&mut self, pat: &ast::Pat, _: ()) {
+    fn visit_pat(&mut self, pat: &ast::Pat, ctxt: MarkSymbolVisitorContext) {
         match pat.node {
             ast::PatStruct(_, ref fields, _) => {
                 self.handle_field_pattern_match(pat, fields.as_slice());
@@ -233,15 +251,15 @@ impl<'a> Visitor<()> for MarkSymbolVisitor<'a> {
             _ => ()
         }
 
-        visit::walk_pat(self, pat, ())
+        visit::walk_pat(self, pat, ctxt);
     }
 
-    fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId, _: ()) {
+    fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId, ctxt: MarkSymbolVisitorContext) {
         self.lookup_and_handle_definition(&id);
-        visit::walk_path(self, path, ());
+        visit::walk_path(self, path, ctxt);
     }
 
-    fn visit_item(&mut self, _: &ast::Item, _: ()) {
+    fn visit_item(&mut self, _: &ast::Item, _: MarkSymbolVisitorContext) {
         // Do not recurse into items. These items will be added to the
         // worklist and recursed into manually if necessary.
     }
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
new file mode 100644
index 00000000000..93913f84271
--- /dev/null
+++ b/src/librustc/middle/intrinsicck.rs
@@ -0,0 +1,155 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use metadata::csearch;
+use middle::def::DefFn;
+use middle::subst::Subst;
+use middle::ty::{TransmuteRestriction, ctxt, ty_bare_fn};
+use middle::ty;
+
+use syntax::abi::RustIntrinsic;
+use syntax::ast::DefId;
+use syntax::ast;
+use syntax::ast_map::NodeForeignItem;
+use syntax::codemap::Span;
+use syntax::parse::token;
+use syntax::visit::Visitor;
+use syntax::visit;
+
+fn type_size_is_affected_by_type_parameters(tcx: &ty::ctxt, typ: ty::t)
+                                            -> bool {
+    let mut result = false;
+    ty::maybe_walk_ty(typ, |typ| {
+        match ty::get(typ).sty {
+            ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_ptr(_) |
+            ty::ty_rptr(..) | ty::ty_bare_fn(..) | ty::ty_closure(..) => {
+                false
+            }
+            ty::ty_param(_) => {
+                result = true;
+                // No need to continue; we now know the result.
+                false
+            }
+            ty::ty_enum(did, ref substs) => {
+                for enum_variant in (*ty::enum_variants(tcx, did)).iter() {
+                    for argument_type in enum_variant.args.iter() {
+                        let argument_type = argument_type.subst(tcx, substs);
+                        result = result ||
+                            type_size_is_affected_by_type_parameters(
+                                tcx,
+                                argument_type);
+                    }
+                }
+
+                // Don't traverse substitutions.
+                false
+            }
+            ty::ty_struct(did, ref substs) => {
+                for field in ty::struct_fields(tcx, did, substs).iter() {
+                    result = result ||
+                        type_size_is_affected_by_type_parameters(tcx,
+                                                                 field.mt.ty);
+                }
+
+                // Don't traverse substitutions.
+                false
+            }
+            _ => true,
+        }
+    });
+    result
+}
+
+struct IntrinsicCheckingVisitor<'a> {
+    tcx: &'a ctxt,
+}
+
+impl<'a> IntrinsicCheckingVisitor<'a> {
+    fn def_id_is_transmute(&self, def_id: DefId) -> bool {
+        if def_id.krate == ast::LOCAL_CRATE {
+            match self.tcx.map.get(def_id.node) {
+                NodeForeignItem(ref item) => {
+                    token::get_ident(item.ident) ==
+                        token::intern_and_get_ident("transmute")
+                }
+                _ => false,
+            }
+        } else {
+            match csearch::get_item_path(self.tcx, def_id).last() {
+                None => false,
+                Some(ref last) => {
+                    token::get_name(last.name()) ==
+                        token::intern_and_get_ident("transmute")
+                }
+            }
+        }
+    }
+
+    fn check_transmute(&self, span: Span, from: ty::t, to: ty::t) {
+        if type_size_is_affected_by_type_parameters(self.tcx, from) {
+            self.tcx.sess.span_err(span,
+                                   "cannot transmute from a type that \
+                                    contains type parameters");
+        }
+        if type_size_is_affected_by_type_parameters(self.tcx, to) {
+            self.tcx.sess.span_err(span,
+                                   "cannot transmute to a type that contains \
+                                    type parameters");
+        }
+
+        let restriction = TransmuteRestriction {
+            span: span,
+            from: from,
+            to: to,
+        };
+        self.tcx.transmute_restrictions.borrow_mut().push(restriction);
+    }
+}
+
+impl<'a> Visitor<()> for IntrinsicCheckingVisitor<'a> {
+    fn visit_expr(&mut self, expr: &ast::Expr, (): ()) {
+        match expr.node {
+            ast::ExprPath(..) => {
+                match ty::resolve_expr(self.tcx, expr) {
+                    DefFn(did, _) if self.def_id_is_transmute(did) => {
+                        let typ = ty::node_id_to_type(self.tcx, expr.id);
+                        match ty::get(typ).sty {
+                            ty_bare_fn(ref bare_fn_ty)
+                                    if bare_fn_ty.abi == RustIntrinsic => {
+                                let from = *bare_fn_ty.sig.inputs.get(0);
+                                let to = bare_fn_ty.sig.output;
+                                self.check_transmute(expr.span, from, to);
+                            }
+                            _ => {
+                                self.tcx
+                                    .sess
+                                    .span_bug(expr.span,
+                                              "transmute wasn't a bare fn?!");
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+
+        visit::walk_expr(self, expr, ());
+    }
+}
+
+pub fn check_crate(tcx: &ctxt, krate: &ast::Crate) {
+    let mut visitor = IntrinsicCheckingVisitor {
+        tcx: tcx,
+    };
+
+    visit::walk_crate(&mut visitor, krate, ());
+}
+
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index f416686efd8..8ff5331cec2 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -165,7 +165,7 @@ impl<'a, 'b> Visitor<Scope<'a>> for LifetimeContext<'b> {
     fn visit_lifetime_ref(&mut self,
                           lifetime_ref: &ast::Lifetime,
                           scope: Scope<'a>) {
-        if lifetime_ref.name == special_idents::statik.name {
+        if lifetime_ref.name == special_idents::static_lifetime.name {
             self.insert_lifetime(lifetime_ref, DefStaticRegion);
             return;
         }
@@ -330,7 +330,7 @@ impl<'a> LifetimeContext<'a> {
                                lifetime_ref: &ast::Lifetime) {
         self.sess.span_err(
             lifetime_ref.span,
-            format!("use of undeclared lifetime name `'{}`",
+            format!("use of undeclared lifetime name `{}`",
                     token::get_name(lifetime_ref.name)).as_slice());
     }
 
@@ -338,7 +338,7 @@ impl<'a> LifetimeContext<'a> {
         for i in range(0, lifetimes.len()) {
             let lifetime_i = lifetimes.get(i);
 
-            let special_idents = [special_idents::statik];
+            let special_idents = [special_idents::static_lifetime];
             for lifetime in lifetimes.iter() {
                 if special_idents.iter().any(|&i| i.name == lifetime.name) {
                     self.sess.span_err(
@@ -354,7 +354,7 @@ impl<'a> LifetimeContext<'a> {
                 if lifetime_i.name == lifetime_j.name {
                     self.sess.span_err(
                         lifetime_j.span,
-                        format!("lifetime name `'{}` declared twice in \
+                        format!("lifetime name `{}` declared twice in \
                                 the same scope",
                                 token::get_name(lifetime_j.name)).as_slice());
                 }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 3e15d5a1a61..14c8d5454aa 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -59,6 +59,7 @@ use middle::trans::expr;
 use middle::trans::foreign;
 use middle::trans::glue;
 use middle::trans::inline;
+use middle::trans::intrinsic;
 use middle::trans::machine;
 use middle::trans::machine::{llalign_of_min, llsize_of, llsize_of_real};
 use middle::trans::meth;
@@ -2329,6 +2330,11 @@ pub fn trans_crate(krate: ast::Crate,
 
     let ccx = CrateContext::new(llmod_id.as_slice(), tcx, exp_map2,
                                 Sha256::new(), link_meta, reachable);
+
+    // First, verify intrinsics.
+    intrinsic::check_intrinsics(&ccx);
+
+    // Next, translate the module.
     {
         let _icx = push_ctxt("text");
         trans_mod(&ccx, &krate.module);
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index 5f37365e743..648a2c335e6 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -390,7 +390,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
                     ast_map::NodeExpr(e) => e.span,
                     _ => fail!("transmute has non-expr arg"),
                 };
-                ccx.sess().span_fatal(sp,
+                ccx.sess().span_bug(sp,
                     format!("transmute called on types with different sizes: \
                              {} ({} bit{}) to \
                              {} ({} bit{})",
@@ -564,3 +564,41 @@ pub fn trans_intrinsic(ccx: &CrateContext,
     }
     fcx.cleanup();
 }
+
+/// Performs late verification that intrinsics are used correctly. At present,
+/// the only intrinsic that needs such verification is `transmute`.
+pub fn check_intrinsics(ccx: &CrateContext) {
+    for transmute_restriction in ccx.tcx
+                                    .transmute_restrictions
+                                    .borrow()
+                                    .iter() {
+        let llfromtype = type_of::sizing_type_of(ccx,
+                                                 transmute_restriction.from);
+        let lltotype = type_of::sizing_type_of(ccx,
+                                               transmute_restriction.to);
+        let from_type_size = machine::llbitsize_of_real(ccx, llfromtype);
+        let to_type_size = machine::llbitsize_of_real(ccx, lltotype);
+        if from_type_size != to_type_size {
+            ccx.sess()
+               .span_err(transmute_restriction.span,
+                format!("transmute called on types with different sizes: \
+                         {} ({} bit{}) to {} ({} bit{})",
+                        ty_to_str(ccx.tcx(), transmute_restriction.from),
+                        from_type_size as uint,
+                        if from_type_size == 1 {
+                            ""
+                        } else {
+                            "s"
+                        },
+                        ty_to_str(ccx.tcx(), transmute_restriction.to),
+                        to_type_size as uint,
+                        if to_type_size == 1 {
+                            ""
+                        } else {
+                            "s"
+                        }).as_slice());
+        }
+    }
+    ccx.sess().abort_if_errors();
+}
+
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index e3d94c73bb4..02300fccdae 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -235,6 +235,17 @@ pub enum AutoRef {
     AutoBorrowObj(Region, ast::Mutability),
 }
 
+/// A restriction that certain types must be the same size. The use of
+/// `transmute` gives rise to these restrictions.
+pub struct TransmuteRestriction {
+    /// The span from whence the restriction comes.
+    pub span: Span,
+    /// The type being transmuted from.
+    pub from: t,
+    /// The type being transmuted to.
+    pub to: t,
+}
+
 /// The data structure to keep track of all the information that typechecker
 /// generates so that so that it can be reused and doesn't have to be redone
 /// later on.
@@ -357,6 +368,11 @@ pub struct ctxt {
 
     pub node_lint_levels: RefCell<HashMap<(ast::NodeId, lint::Lint),
                                           (lint::Level, lint::LintSource)>>,
+
+    /// The types that must be asserted to be the same size for `transmute`
+    /// to be valid. We gather up these restrictions in the intrinsicck pass
+    /// and check them in trans.
+    pub transmute_restrictions: RefCell<Vec<TransmuteRestriction>>,
 }
 
 pub enum tbox_flag {
@@ -1118,6 +1134,7 @@ pub fn mk_ctxt(s: Session,
         vtable_map: RefCell::new(FnvHashMap::new()),
         dependency_formats: RefCell::new(HashMap::new()),
         node_lint_levels: RefCell::new(HashMap::new()),
+        transmute_restrictions: RefCell::new(Vec::new()),
     }
 }
 
@@ -2711,8 +2728,7 @@ pub fn pat_ty(cx: &ctxt, pat: &ast::Pat) -> t {
 //
 // NB (2): This type doesn't provide type parameter substitutions; e.g. if you
 // ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
-// instead of "fn(t) -> T with T = int". If this isn't what you want, see
-// expr_ty_params_and_ty() below.
+// instead of "fn(t) -> T with T = int".
 pub fn expr_ty(cx: &ctxt, expr: &ast::Expr) -> t {
     return node_id_to_type(cx, expr.id);
 }
@@ -4514,9 +4530,10 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
             ty_uniq(_) => {
                 byte!(10);
             }
-            ty_vec(m, Some(_)) => {
+            ty_vec(m, Some(n)) => {
                 byte!(11);
                 mt(&mut state, m);
+                n.hash(&mut state);
                 1u8.hash(&mut state);
             }
             ty_vec(m, None) => {
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 83c5be23816..f380004fb08 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -724,6 +724,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                                  .collect();
                 ty::mk_tup(tcx, flds)
             }
+            ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
             ast::TyBareFn(ref bf) => {
                 if bf.decl.variadic && bf.abi != abi::C {
                     tcx.sess.span_err(ast_ty.span,
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 544990d19a5..b9933fed296 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3099,9 +3099,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                         /* this cast is only allowed from &[T] to *T or
                         &T to *T. */
                         match (&ty::get(te).sty, &ty::get(t_1).sty) {
-                            (&ty::ty_rptr(_, mt1), &ty::ty_ptr(mt2))
-                            if types_compatible(fcx, e.span,
-                                                mt1.ty, mt2.ty) => {
+                            (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
+                             &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
+                            if types_compatible(fcx, e.span, mt1, mt2) => {
                                 /* this case is allowed */
                             }
                             _ => {
diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs
index bcd66ed4d66..4d396ed4f6e 100644
--- a/src/librustc/middle/typeck/infer/error_reporting.rs
+++ b/src/librustc/middle/typeck/infer/error_reporting.rs
@@ -1140,6 +1140,7 @@ impl<'a> Rebuilder<'a> {
                     }
                     ast::TyTup(new_tys)
                 }
+                ast::TyParen(ref typ) => ast::TyParen(build_to(*typ, to)),
                 ref other => other.clone()
             };
             box(GC) ast::Ty { id: from.id, node: new_node, span: from.span }
@@ -1505,7 +1506,8 @@ impl LifeGiver {
     fn give_lifetime(&self) -> ast::Lifetime {
         let mut lifetime;
         loop {
-            let s = num_to_str(self.counter.get());
+            let mut s = String::from_str("'");
+            s.push_str(num_to_str(self.counter.get()).as_slice());
             if !self.taken.contains(&s) {
                 lifetime = name_to_dummy_lifetime(
                                     token::str_to_ident(s.as_slice()).name);
diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs
index 97ffcf279ae..7d74b8c7296 100644
--- a/src/librustc/plugin/load.rs
+++ b/src/librustc/plugin/load.rs
@@ -126,9 +126,11 @@ impl<'a> PluginLoader<'a> {
         };
 
         unsafe {
-            let registrar: PluginRegistrarFun =
+            let registrar =
                 match lib.symbol(symbol.as_slice()) {
-                    Ok(registrar) => registrar,
+                    Ok(registrar) => {
+                        mem::transmute::<*u8,PluginRegistrarFun>(registrar)
+                    }
                     // again fatal if we can't register macros
                     Err(err) => self.sess.span_fatal(vi.span, err.as_slice())
                 };
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 31994d08d23..80f3508d0cd 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -162,7 +162,7 @@ pub fn bound_region_to_str(cx: &ctxt,
 
     match br {
         BrNamed(_, name) => {
-            format!("{}'{}{}", prefix, token::get_name(name), space_str)
+            format!("{}{}{}", prefix, token::get_name(name), space_str)
         }
         BrAnon(_) => prefix.to_string(),
         BrFresh(_) => prefix.to_string(),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index dd6cc978ae7..7e68be09f1d 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -60,7 +60,7 @@ impl<T: Clean<U>, U> Clean<VecPerParamSpace<U>> for VecPerParamSpace<T> {
     }
 }
 
-impl<T: Clean<U>, U> Clean<U> for Gc<T> {
+impl<T: 'static + Clean<U>, U> Clean<U> for Gc<T> {
     fn clean(&self) -> U {
         (**self).clean()
     }
@@ -1198,6 +1198,7 @@ impl Clean<Type> for ast::Ty {
             TyClosure(ref c, region) => Closure(box c.clean(), region.clean()),
             TyProc(ref c) => Proc(box c.clean()),
             TyBareFn(ref barefn) => BareFunction(box barefn.clean()),
+            TyParen(ref ty) => ty.clean(),
             TyBot => Bottom,
             ref x => fail!("Unimplemented type {:?}", x),
         }
diff --git a/src/librustdoc/plugins.rs b/src/librustdoc/plugins.rs
index fee1d63a274..e5bced8038b 100644
--- a/src/librustdoc/plugins.rs
+++ b/src/librustdoc/plugins.rs
@@ -12,6 +12,7 @@ use clean;
 
 use dl = std::dynamic_lib;
 use serialize::json;
+use std::mem;
 use std::string::String;
 
 pub type PluginJson = Option<(String, json::Json)>;
@@ -45,9 +46,11 @@ impl PluginManager {
         let x = self.prefix.join(libname(name));
         let lib_result = dl::DynamicLibrary::open(Some(&x));
         let lib = lib_result.unwrap();
-        let plugin = unsafe { lib.symbol("rustdoc_plugin_entrypoint") }.unwrap();
+        unsafe {
+            let plugin = lib.symbol("rustdoc_plugin_entrypoint").unwrap();
+            self.callbacks.push(mem::transmute::<*u8,PluginCallback>(plugin));
+        }
         self.dylibs.push(lib);
-        self.callbacks.push(plugin);
     }
 
     /// Load a normal Rust function as a plugin.
diff --git a/src/librustrt/mutex.rs b/src/librustrt/mutex.rs
index eec19e9d5db..3fece698a1d 100644
--- a/src/librustrt/mutex.rs
+++ b/src/librustrt/mutex.rs
@@ -115,6 +115,18 @@ impl StaticNativeMutex {
     ///     // critical section...
     /// } // automatically unlocked in `_guard`'s destructor
     /// ```
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe because it will not function correctly if this
+    /// mutex has been *moved* since it was last used. The mutex can move an
+    /// arbitrary number of times before its first usage, but once a mutex has
+    /// been used once it is no longer allowed to move (or otherwise it invokes
+    /// undefined behavior).
+    ///
+    /// Additionally, this type does not take into account any form of
+    /// scheduling model. This will unconditionally block the *os thread* which
+    /// is not always desired.
     pub unsafe fn lock<'a>(&'a self) -> LockGuard<'a> {
         self.inner.lock();
 
@@ -123,6 +135,10 @@ impl StaticNativeMutex {
 
     /// Attempts to acquire the lock. The value returned is `Some` if
     /// the attempt succeeded.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock`.
     pub unsafe fn trylock<'a>(&'a self) -> Option<LockGuard<'a>> {
         if self.inner.trylock() {
             Some(LockGuard { lock: self })
@@ -135,6 +151,12 @@ impl StaticNativeMutex {
     ///
     /// These needs to be paired with a call to `.unlock_noguard`. Prefer using
     /// `.lock`.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock`. Additionally, this
+    /// does not guarantee that the mutex will ever be unlocked, and it is
+    /// undefined to drop an already-locked mutex.
     pub unsafe fn lock_noguard(&self) { self.inner.lock() }
 
     /// Attempts to acquire the lock without creating a
@@ -143,12 +165,22 @@ impl StaticNativeMutex {
     ///
     /// If `true` is returned, this needs to be paired with a call to
     /// `.unlock_noguard`. Prefer using `.trylock`.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock_noguard`.
     pub unsafe fn trylock_noguard(&self) -> bool {
         self.inner.trylock()
     }
 
     /// Unlocks the lock. This assumes that the current thread already holds the
     /// lock.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock`. Additionally, it
+    /// is not guaranteed that this is unlocking a previously locked mutex. It
+    /// is undefined to unlock an unlocked mutex.
     pub unsafe fn unlock_noguard(&self) { self.inner.unlock() }
 
     /// Block on the internal condition variable.
@@ -156,9 +188,19 @@ impl StaticNativeMutex {
     /// This function assumes that the lock is already held. Prefer
     /// using `LockGuard.wait` since that guarantees that the lock is
     /// held.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock`. Additionally, this
+    /// is unsafe because the mutex may not be currently locked.
     pub unsafe fn wait_noguard(&self) { self.inner.wait() }
 
     /// Signals a thread in `wait` to wake up
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock`. Additionally, this
+    /// is unsafe because the mutex may not be currently locked.
     pub unsafe fn signal_noguard(&self) { self.inner.signal() }
 
     /// This function is especially unsafe because there are no guarantees made
@@ -181,6 +223,7 @@ impl NativeMutex {
     /// already hold the lock.
     ///
     /// # Example
+    ///
     /// ```rust
     /// use std::rt::mutex::NativeMutex;
     /// unsafe {
@@ -192,12 +235,22 @@ impl NativeMutex {
     ///     } // automatically unlocked in `_guard`'s destructor
     /// }
     /// ```
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::lock`.
     pub unsafe fn lock<'a>(&'a self) -> LockGuard<'a> {
         self.inner.lock()
     }
 
     /// Attempts to acquire the lock. The value returned is `Some` if
     /// the attempt succeeded.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::trylock`.
     pub unsafe fn trylock<'a>(&'a self) -> Option<LockGuard<'a>> {
         self.inner.trylock()
     }
@@ -206,6 +259,11 @@ impl NativeMutex {
     ///
     /// These needs to be paired with a call to `.unlock_noguard`. Prefer using
     /// `.lock`.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::lock_noguard`.
     pub unsafe fn lock_noguard(&self) { self.inner.lock_noguard() }
 
     /// Attempts to acquire the lock without creating a
@@ -214,12 +272,22 @@ impl NativeMutex {
     ///
     /// If `true` is returned, this needs to be paired with a call to
     /// `.unlock_noguard`. Prefer using `.trylock`.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::trylock_noguard`.
     pub unsafe fn trylock_noguard(&self) -> bool {
         self.inner.trylock_noguard()
     }
 
     /// Unlocks the lock. This assumes that the current thread already holds the
     /// lock.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::unlock_noguard`.
     pub unsafe fn unlock_noguard(&self) { self.inner.unlock_noguard() }
 
     /// Block on the internal condition variable.
@@ -227,9 +295,19 @@ impl NativeMutex {
     /// This function assumes that the lock is already held. Prefer
     /// using `LockGuard.wait` since that guarantees that the lock is
     /// held.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::wait_noguard`.
     pub unsafe fn wait_noguard(&self) { self.inner.wait_noguard() }
 
     /// Signals a thread in `wait` to wake up
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::signal_noguard`.
     pub unsafe fn signal_noguard(&self) { self.inner.signal_noguard() }
 }
 
diff --git a/src/librustrt/unwind.rs b/src/librustrt/unwind.rs
index f7475db1552..aebed5a8829 100644
--- a/src/librustrt/unwind.rs
+++ b/src/librustrt/unwind.rs
@@ -73,7 +73,6 @@ use libc::c_void;
 
 use local::Local;
 use task::{Task, Result};
-use exclusive::Exclusive;
 
 use uw = libunwind;
 
@@ -88,7 +87,6 @@ struct Exception {
 }
 
 pub type Callback = fn(msg: &Any:Send, file: &'static str, line: uint);
-type Queue = Exclusive<Vec<Callback>>;
 
 // Variables used for invoking callbacks when a task starts to unwind.
 //
diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs
index fa6efc8a4b1..76dbfa8c29e 100644
--- a/src/libstd/dynamic_lib.rs
+++ b/src/libstd/dynamic_lib.rs
@@ -134,7 +134,7 @@ impl DynamicLibrary {
     }
 
     /// Access the value at the symbol of the dynamic library
-    pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, String> {
+    pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*T, String> {
         // This function should have a lifetime constraint of 'a on
         // T but that feature is still unimplemented
 
@@ -158,6 +158,7 @@ mod test {
     use super::*;
     use prelude::*;
     use libc;
+    use mem;
 
     #[test]
     #[ignore(cfg(windows))] // FIXME #8818
@@ -174,7 +175,7 @@ mod test {
         let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
             match libm.symbol("cos") {
                 Err(error) => fail!("Could not load function cos: {}", error),
-                Ok(cosine) => cosine
+                Ok(cosine) => mem::transmute::<*u8, _>(cosine)
             }
         };
 
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
index c29c82ab2e9..10dfec0f566 100644
--- a/src/libstd/io/fs.rs
+++ b/src/libstd/io/fs.rs
@@ -52,9 +52,11 @@ fs::unlink(&path);
 use c_str::ToCStr;
 use clone::Clone;
 use collections::Collection;
+use io::standard_error;
 use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
 use io::{IoResult, IoError, FileStat, SeekStyle, Seek, Writer, Reader};
 use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
+use io::UpdateIoError;
 use io;
 use iter::Iterator;
 use kinds::Send;
@@ -67,6 +69,7 @@ use result::{Err, Ok};
 use rt::rtio::LocalIo;
 use rt::rtio;
 use slice::ImmutableVector;
+use string::String;
 use vec::Vec;
 
 /// Unconstrained file access type that exposes read and write operations
@@ -128,25 +131,29 @@ impl File {
     pub fn open_mode(path: &Path,
                      mode: FileMode,
                      access: FileAccess) -> IoResult<File> {
-        let mode = match mode {
+        let rtio_mode = match mode {
             Open => rtio::Open,
             Append => rtio::Append,
             Truncate => rtio::Truncate,
         };
-        let access = match access {
+        let rtio_access = match access {
             Read => rtio::Read,
             Write => rtio::Write,
             ReadWrite => rtio::ReadWrite,
         };
-        LocalIo::maybe_raise(|io| {
-            io.fs_open(&path.to_c_str(), mode, access).map(|fd| {
+        let err = LocalIo::maybe_raise(|io| {
+            io.fs_open(&path.to_c_str(), rtio_mode, rtio_access).map(|fd| {
                 File {
                     path: path.clone(),
                     fd: fd,
                     last_nread: -1
                 }
             })
-        }).map_err(IoError::from_rtio_error)
+        }).map_err(IoError::from_rtio_error);
+        err.update_err("couldn't open file", |e| {
+            format!("{}; path={}; mode={}; access={}", e, path.display(),
+                mode_string(mode), access_string(access))
+        })
     }
 
     /// Attempts to open a file in read-only mode. This function is equivalent to
@@ -185,6 +192,7 @@ impl File {
     /// ```
     pub fn create(path: &Path) -> IoResult<File> {
         File::open_mode(path, Truncate, Write)
+            .update_desc("couldn't create file")
     }
 
     /// Returns the original path which was used to open this file.
@@ -196,7 +204,9 @@ impl File {
     /// device. This will flush any internal buffers necessary to perform this
     /// operation.
     pub fn fsync(&mut self) -> IoResult<()> {
-        self.fd.fsync().map_err(IoError::from_rtio_error)
+        let err = self.fd.fsync().map_err(IoError::from_rtio_error);
+        err.update_err("couldn't fsync file",
+                       |e| format!("{}; path={}", e, self.path.display()))
     }
 
     /// This function is similar to `fsync`, except that it may not synchronize
@@ -204,7 +214,9 @@ impl File {
     /// must synchronize content, but don't need the metadata on disk. The goal
     /// of this method is to reduce disk operations.
     pub fn datasync(&mut self) -> IoResult<()> {
-        self.fd.datasync().map_err(IoError::from_rtio_error)
+        let err = self.fd.datasync().map_err(IoError::from_rtio_error);
+        err.update_err("couldn't datasync file",
+                       |e| format!("{}; path={}", e, self.path.display()))
     }
 
     /// Either truncates or extends the underlying file, updating the size of
@@ -216,7 +228,10 @@ impl File {
     /// will be extended to `size` and have all of the intermediate data filled
     /// in with 0s.
     pub fn truncate(&mut self, size: i64) -> IoResult<()> {
-        self.fd.truncate(size).map_err(IoError::from_rtio_error)
+        let err = self.fd.truncate(size).map_err(IoError::from_rtio_error);
+        err.update_err("couldn't truncate file", |e| {
+            format!("{}; path={}; size={}", e, self.path.display(), size)
+        })
     }
 
     /// Tests whether this stream has reached EOF.
@@ -229,10 +244,12 @@ impl File {
 
     /// Queries information about the underlying file.
     pub fn stat(&mut self) -> IoResult<FileStat> {
-        match self.fd.fstat() {
+        let err = match self.fd.fstat() {
             Ok(s) => Ok(from_rtio(s)),
             Err(e) => Err(IoError::from_rtio_error(e)),
-        }
+        };
+        err.update_err("couldn't fstat file",
+                       |e| format!("{}; path={}", e, self.path.display()))
     }
 }
 
@@ -258,9 +275,11 @@ impl File {
 /// user lacks permissions to remove the file, or if some other filesystem-level
 /// error occurs.
 pub fn unlink(path: &Path) -> IoResult<()> {
-    LocalIo::maybe_raise(|io| {
+    let err = LocalIo::maybe_raise(|io| {
         io.fs_unlink(&path.to_c_str())
-    }).map_err(IoError::from_rtio_error)
+    }).map_err(IoError::from_rtio_error);
+    err.update_err("couldn't unlink path",
+                   |e| format!("{}; path={}", e, path.display()))
 }
 
 /// Given a path, query the file system to get information about a file,
@@ -285,10 +304,12 @@ pub fn unlink(path: &Path) -> IoResult<()> {
 /// to perform a `stat` call on the given path or if there is no entry in the
 /// filesystem at the provided path.
 pub fn stat(path: &Path) -> IoResult<FileStat> {
-    match LocalIo::maybe_raise(|io| io.fs_stat(&path.to_c_str())) {
+    let err = match LocalIo::maybe_raise(|io| io.fs_stat(&path.to_c_str())) {
         Ok(s) => Ok(from_rtio(s)),
         Err(e) => Err(IoError::from_rtio_error(e)),
-    }
+    };
+    err.update_err("couldn't stat path",
+                   |e| format!("{}; path={}", e, path.display()))
 }
 
 /// Perform the same operation as the `stat` function, except that this
@@ -300,10 +321,12 @@ pub fn stat(path: &Path) -> IoResult<FileStat> {
 ///
 /// See `stat`
 pub fn lstat(path: &Path) -> IoResult<FileStat> {
-    match LocalIo::maybe_raise(|io| io.fs_lstat(&path.to_c_str())) {
+    let err = match LocalIo::maybe_raise(|io| io.fs_lstat(&path.to_c_str())) {
         Ok(s) => Ok(from_rtio(s)),
         Err(e) => Err(IoError::from_rtio_error(e)),
-    }
+    };
+    err.update_err("couldn't lstat path",
+                   |e| format!("{}; path={}", e, path.display()))
 }
 
 fn from_rtio(s: rtio::FileStat) -> FileStat {
@@ -359,9 +382,12 @@ fn from_rtio(s: rtio::FileStat) -> FileStat {
 /// permissions to view the contents, or if some other intermittent I/O error
 /// occurs.
 pub fn rename(from: &Path, to: &Path) -> IoResult<()> {
-    LocalIo::maybe_raise(|io| {
+    let err = LocalIo::maybe_raise(|io| {
         io.fs_rename(&from.to_c_str(), &to.to_c_str())
-    }).map_err(IoError::from_rtio_error)
+    }).map_err(IoError::from_rtio_error);
+    err.update_err("couldn't rename path", |e| {
+        format!("{}; from={}; to={}", e, from.display(), to.display())
+    })
 }
 
 /// Copies the contents of one file to another. This function will also
@@ -393,12 +419,17 @@ pub fn rename(from: &Path, to: &Path) -> IoResult<()> {
 /// ensured to not exist, there is nothing preventing the destination from
 /// being created and then destroyed by this operation.
 pub fn copy(from: &Path, to: &Path) -> IoResult<()> {
+    fn update_err<T>(result: IoResult<T>, from: &Path, to: &Path) -> IoResult<T> {
+        result.update_err("couldn't copy path",
+            |e| format!("{}; from={}; to={}", e, from.display(), to.display()))
+    }
+
     if !from.is_file() {
-        return Err(IoError {
+        return update_err(Err(IoError {
             kind: io::MismatchedFileTypeForOperation,
             desc: "the source path is not an existing file",
-            detail: None,
-        })
+            detail: None
+        }), from, to)
     }
 
     let mut reader = try!(File::open(from));
@@ -409,12 +440,12 @@ pub fn copy(from: &Path, to: &Path) -> IoResult<()> {
         let amt = match reader.read(buf) {
             Ok(n) => n,
             Err(ref e) if e.kind == io::EndOfFile => { break }
-            Err(e) => return Err(e)
+            Err(e) => return update_err(Err(e), from, to)
         };
         try!(writer.write(buf.slice_to(amt)));
     }
 
-    chmod(to, try!(from.stat()).perm)
+    chmod(to, try!(update_err(from.stat(), from, to)).perm)
 }
 
 /// Changes the permission mode bits found on a file or a directory. This
@@ -439,33 +470,45 @@ pub fn copy(from: &Path, to: &Path) -> IoResult<()> {
 /// Some possible error situations are not having the permission to
 /// change the attributes of a file or the file not existing.
 pub fn chmod(path: &Path, mode: io::FilePermission) -> IoResult<()> {
-    LocalIo::maybe_raise(|io| {
+    let err = LocalIo::maybe_raise(|io| {
         io.fs_chmod(&path.to_c_str(), mode.bits() as uint)
-    }).map_err(IoError::from_rtio_error)
+    }).map_err(IoError::from_rtio_error);
+    err.update_err("couldn't chmod path", |e| {
+        format!("{}; path={}; mode={}", e, path.display(), mode)
+    })
 }
 
 /// Change the user and group owners of a file at the specified path.
 pub fn chown(path: &Path, uid: int, gid: int) -> IoResult<()> {
-    LocalIo::maybe_raise(|io| {
+    let err = LocalIo::maybe_raise(|io| {
         io.fs_chown(&path.to_c_str(), uid, gid)
-    }).map_err(IoError::from_rtio_error)
+    }).map_err(IoError::from_rtio_error);
+    err.update_err("couldn't chown path", |e| {
+        format!("{}; path={}; uid={}; gid={}", e, path.display(), uid, gid)
+    })
 }
 
 /// Creates a new hard link on the filesystem. The `dst` path will be a
 /// link pointing to the `src` path. Note that systems often require these
 /// two paths to both be located on the same filesystem.
 pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
-    LocalIo::maybe_raise(|io| {
+    let err = LocalIo::maybe_raise(|io| {
         io.fs_link(&src.to_c_str(), &dst.to_c_str())
-    }).map_err(IoError::from_rtio_error)
+    }).map_err(IoError::from_rtio_error);
+    err.update_err("couldn't link path", |e| {
+        format!("{}; src={}; dest={}", e, src.display(), dst.display())
+    })
 }
 
 /// Creates a new symbolic link on the filesystem. The `dst` path will be a
 /// symlink pointing to the `src` path.
 pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
-    LocalIo::maybe_raise(|io| {
+    let err = LocalIo::maybe_raise(|io| {
         io.fs_symlink(&src.to_c_str(), &dst.to_c_str())
-    }).map_err(IoError::from_rtio_error)
+    }).map_err(IoError::from_rtio_error);
+    err.update_err("couldn't symlink path", |e| {
+        format!("{}; src={}; dest={}", e, src.display(), dst.display())
+    })
 }
 
 /// Reads a symlink, returning the file that the symlink points to.
@@ -475,9 +518,11 @@ pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
 /// This function will return an error on failure. Failure conditions include
 /// reading a file that does not exist or reading a file which is not a symlink.
 pub fn readlink(path: &Path) -> IoResult<Path> {
-    LocalIo::maybe_raise(|io| {
+    let err = LocalIo::maybe_raise(|io| {
         Ok(Path::new(try!(io.fs_readlink(&path.to_c_str()))))
-    }).map_err(IoError::from_rtio_error)
+    }).map_err(IoError::from_rtio_error);
+    err.update_err("couldn't resolve symlink for path",
+                   |e| format!("{}; path={}", e, path.display()))
 }
 
 /// Create a new, empty directory at the provided path
@@ -498,9 +543,12 @@ pub fn readlink(path: &Path) -> IoResult<Path> {
 /// This call will return an error if the user lacks permissions to make a new
 /// directory at the provided path, or if the directory already exists.
 pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> {
-    LocalIo::maybe_raise(|io| {
+    let err = LocalIo::maybe_raise(|io| {
         io.fs_mkdir(&path.to_c_str(), mode.bits() as uint)
-    }).map_err(IoError::from_rtio_error)
+    }).map_err(IoError::from_rtio_error);
+    err.update_err("couldn't create directory", |e| {
+        format!("{}; path={}; mode={}", e, path.display(), mode)
+    })
 }
 
 /// Remove an existing, empty directory
@@ -520,9 +568,11 @@ pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> {
 /// This call will return an error if the user lacks permissions to remove the
 /// directory at the provided path, or if the directory isn't empty.
 pub fn rmdir(path: &Path) -> IoResult<()> {
-    LocalIo::maybe_raise(|io| {
+    let err = LocalIo::maybe_raise(|io| {
         io.fs_rmdir(&path.to_c_str())
-    }).map_err(IoError::from_rtio_error)
+    }).map_err(IoError::from_rtio_error);
+    err.update_err("couldn't remove directory",
+                   |e| format!("{}; path={}", e, path.display()))
 }
 
 /// Retrieve a vector containing all entries within a provided directory
@@ -557,11 +607,13 @@ pub fn rmdir(path: &Path) -> IoResult<()> {
 /// permissions to view the contents or if the `path` points at a non-directory
 /// file
 pub fn readdir(path: &Path) -> IoResult<Vec<Path>> {
-    LocalIo::maybe_raise(|io| {
+    let err = LocalIo::maybe_raise(|io| {
         Ok(try!(io.fs_readdir(&path.to_c_str(), 0)).move_iter().map(|a| {
             Path::new(a)
         }).collect())
-    }).map_err(IoError::from_rtio_error)
+    }).map_err(IoError::from_rtio_error);
+    err.update_err("couldn't read directory",
+                   |e| format!("{}; path={}", e, path.display()))
 }
 
 /// Returns an iterator which will recursively walk the directory structure
@@ -569,7 +621,11 @@ pub fn readdir(path: &Path) -> IoResult<Vec<Path>> {
 /// perform iteration in some top-down order.  The contents of unreadable
 /// subdirectories are ignored.
 pub fn walk_dir(path: &Path) -> IoResult<Directories> {
-    Ok(Directories { stack: try!(readdir(path)) })
+    Ok(Directories {
+        stack: try!(readdir(path).update_err("couldn't walk directory",
+                                             |e| format!("{}; path={}",
+                                                         e, path.display())))
+    })
 }
 
 /// An iterator which walks over a directory
@@ -582,7 +638,12 @@ impl Iterator<Path> for Directories {
         match self.stack.pop() {
             Some(path) => {
                 if path.is_dir() {
-                    match readdir(&path) {
+                    let result = readdir(&path)
+                        .update_err("couldn't advance Directories iterator",
+                                    |e| format!("{}; path={}",
+                                                e, path.display()));
+
+                    match result {
                         Ok(dirs) => { self.stack.push_all_move(dirs); }
                         Err(..) => {}
                     }
@@ -614,7 +675,11 @@ pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> {
     for c in comps {
         curpath.push(c);
 
-        match mkdir(&curpath, mode) {
+        let result = mkdir(&curpath, mode)
+            .update_err("couldn't recursively mkdir",
+                        |e| format!("{}; path={}", e, path.display()));
+
+        match result {
             Err(mkdir_err) => {
                 // already exists ?
                 if try!(stat(&curpath)).kind != io::TypeDirectory {
@@ -639,8 +704,20 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> {
     let mut rm_stack = Vec::new();
     rm_stack.push(path.clone());
 
+    fn rmdir_failed(err: &IoError, path: &Path) -> String {
+        format!("rmdir_recursive failed; path={}; cause={}",
+                path.display(), err)
+    }
+
+    fn update_err<T>(err: IoResult<T>, path: &Path) -> IoResult<T> {
+        err.update_err("couldn't recursively rmdir",
+                       |e| rmdir_failed(e, path))
+    }
+
     while !rm_stack.is_empty() {
-        let children = try!(readdir(rm_stack.last().unwrap()));
+        let children = try!(readdir(rm_stack.last().unwrap())
+            .update_detail(|e| rmdir_failed(e, path)));
+
         let mut has_child_dir = false;
 
         // delete all regular files in the way and push subdirs
@@ -648,17 +725,17 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> {
         for child in children.move_iter() {
             // FIXME(#12795) we should use lstat in all cases
             let child_type = match cfg!(windows) {
-                true => try!(stat(&child)).kind,
-                false => try!(lstat(&child)).kind
+                true => try!(update_err(stat(&child), path)),
+                false => try!(update_err(lstat(&child), path))
             };
 
-            if child_type == io::TypeDirectory {
+            if child_type.kind == io::TypeDirectory {
                 rm_stack.push(child);
                 has_child_dir = true;
             } else {
                 // we can carry on safely if the file is already gone
                 // (eg: deleted by someone else since readdir)
-                match unlink(&child) {
+                match update_err(unlink(&child), path) {
                     Ok(()) => (),
                     Err(ref e) if e.kind == io::FileNotFound => (),
                     Err(e) => return Err(e)
@@ -668,7 +745,8 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> {
 
         // if no subdir was found, let's pop and delete
         if !has_child_dir {
-            match rmdir(&rm_stack.pop().unwrap()) {
+            let result = update_err(rmdir(&rm_stack.pop().unwrap()), path);
+            match result {
                 Ok(()) => (),
                 Err(ref e) if e.kind == io::FileNotFound => (),
                 Err(e) => return Err(e)
@@ -685,35 +763,50 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> {
 /// be in milliseconds.
 // FIXME(#10301) these arguments should not be u64
 pub fn change_file_times(path: &Path, atime: u64, mtime: u64) -> IoResult<()> {
-    LocalIo::maybe_raise(|io| {
+    let err = LocalIo::maybe_raise(|io| {
         io.fs_utime(&path.to_c_str(), atime, mtime)
-    }).map_err(IoError::from_rtio_error)
+    }).map_err(IoError::from_rtio_error);
+    err.update_err("couldn't change_file_times",
+                   |e| format!("{}; path={}", e, path.display()))
 }
 
 impl Reader for File {
     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
-        match self.fd.read(buf) {
+        fn update_err<T>(result: IoResult<T>, file: &File) -> IoResult<T> {
+            result.update_err("couldn't read file",
+                              |e| format!("{}; path={}",
+                                          e, file.path.display()))
+        }
+
+        let result = update_err(self.fd.read(buf)
+                                    .map_err(IoError::from_rtio_error), self);
+
+        match result {
             Ok(read) => {
                 self.last_nread = read;
                 match read {
-                    0 => Err(io::standard_error(io::EndOfFile)),
+                    0 => update_err(Err(standard_error(io::EndOfFile)), self),
                     _ => Ok(read as uint)
                 }
             },
-            Err(e) => Err(IoError::from_rtio_error(e)),
+            Err(e) => Err(e)
         }
     }
 }
 
 impl Writer for File {
     fn write(&mut self, buf: &[u8]) -> IoResult<()> {
-        self.fd.write(buf).map_err(IoError::from_rtio_error)
+        let err = self.fd.write(buf).map_err(IoError::from_rtio_error);
+        err.update_err("couldn't write to file",
+                       |e| format!("{}; path={}", e, self.path.display()))
     }
 }
 
 impl Seek for File {
     fn tell(&self) -> IoResult<u64> {
-        self.fd.tell().map_err(IoError::from_rtio_error)
+        let err = self.fd.tell().map_err(IoError::from_rtio_error);
+        err.update_err("couldn't retrieve file cursor (`tell`)",
+                       |e| format!("{}; path={}", e, self.path.display()))
     }
 
     fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
@@ -722,14 +815,16 @@ impl Seek for File {
             SeekCur => rtio::SeekCur,
             SeekEnd => rtio::SeekEnd,
         };
-        match self.fd.seek(pos, style) {
+        let err = match self.fd.seek(pos, style) {
             Ok(_) => {
                 // successful seek resets EOF indicator
                 self.last_nread = -1;
                 Ok(())
             }
             Err(e) => Err(IoError::from_rtio_error(e)),
-        }
+        };
+        err.update_err("couldn't seek in file",
+                       |e| format!("{}; path={}", e, self.path.display()))
     }
 }
 
@@ -779,6 +874,22 @@ impl path::Path {
     }
 }
 
+fn mode_string(mode: FileMode) -> &'static str {
+    match mode {
+        super::Open => "open",
+        super::Append => "append",
+        super::Truncate => "truncate"
+    }
+}
+
+fn access_string(access: FileAccess) -> &'static str {
+    match access {
+        super::Read => "read",
+        super::Write => "write",
+        super::ReadWrite => "readwrite"
+    }
+}
+
 #[cfg(test)]
 #[allow(unused_imports)]
 mod test {
@@ -801,6 +912,14 @@ mod test {
         }
     ) )
 
+    macro_rules! error( ($e:expr, $s:expr) => (
+        match $e {
+            Ok(val) => fail!("Should have been an error, was {:?}", val),
+            Err(ref err) => assert!(err.to_str().as_slice().contains($s.as_slice()),
+                                    format!("`{}` did not contain `{}`", err, $s))
+        }
+    ) )
+
     struct TempDir(Path);
 
     impl TempDir {
@@ -856,13 +975,25 @@ mod test {
         let tmpdir = tmpdir();
         let filename = &tmpdir.join("file_that_does_not_exist.txt");
         let result = File::open_mode(filename, Open, Read);
-        assert!(result.is_err());
+
+        error!(result, "couldn't open file");
+        if cfg!(unix) {
+            error!(result, "no such file or directory");
+        }
+        error!(result, format!("path={}; mode=open; access=read", filename.display()));
     })
 
     iotest!(fn file_test_iounlinking_invalid_path_should_raise_condition() {
         let tmpdir = tmpdir();
         let filename = &tmpdir.join("file_another_file_that_does_not_exist.txt");
-        assert!(unlink(filename).is_err());
+
+        let result = unlink(filename);
+
+        error!(result, "couldn't unlink path");
+        if cfg!(unix) {
+            error!(result, "no such file or directory");
+        }
+        error!(result, format!("path={}", filename.display()));
     })
 
     iotest!(fn file_test_io_non_positional_read() {
@@ -1091,6 +1222,22 @@ mod test {
         assert!(dir.is_dir())
     })
 
+    iotest!(fn recursive_mkdir_failure() {
+        let tmpdir = tmpdir();
+        let dir = tmpdir.join("d1");
+        let file = dir.join("f1");
+
+        check!(mkdir_recursive(&dir, io::UserRWX));
+        check!(File::create(&file));
+
+        let result = mkdir_recursive(&file, io::UserRWX);
+
+        error!(result, "couldn't recursively mkdir");
+        error!(result, "couldn't create directory");
+        error!(result, "mode=FilePermission { bits: 448 }");
+        error!(result, format!("path={}", file.display()));
+    })
+
     iotest!(fn recursive_mkdir_slash() {
         check!(mkdir_recursive(&Path::new("/"), io::UserRWX));
     })
@@ -1147,6 +1294,12 @@ mod test {
     iotest!(fn copy_file_does_not_exist() {
         let from = Path::new("test/nonexistent-bogus-path");
         let to = Path::new("test/other-bogus-path");
+
+        error!(copy(&from, &to),
+            format!("couldn't copy path (the source path is not an \
+                    existing file; from={}; to={})",
+                    from.display(), to.display()));
+
         match copy(&from, &to) {
             Ok(..) => fail!(),
             Err(..) => {
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index a1e0fa88978..a7f84899a62 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -232,7 +232,7 @@ use owned::Box;
 use result::{Ok, Err, Result};
 use rt::rtio;
 use slice::{Vector, MutableVector, ImmutableVector};
-use str::{StrSlice, StrAllocating};
+use str::{Str, StrSlice, StrAllocating};
 use str;
 use string::String;
 use uint;
@@ -309,6 +309,7 @@ impl IoError {
     /// struct is filled with an allocated string describing the error
     /// in more detail, retrieved from the operating system.
     pub fn from_errno(errno: uint, detail: bool) -> IoError {
+
         #[cfg(windows)]
         fn get_err(errno: i32) -> (IoErrorKind, &'static str) {
             match errno {
@@ -388,8 +389,8 @@ impl IoError {
         IoError {
             kind: kind,
             desc: desc,
-            detail: if detail {
-                Some(os::error_string(errno))
+            detail: if detail && kind == OtherIoError {
+                Some(os::error_string(errno).as_slice().chars().map(|c| c.to_lowercase()).collect())
             } else {
                 None
             },
@@ -420,10 +421,13 @@ impl IoError {
 
 impl fmt::Show for IoError {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(fmt, "{}", self.desc));
-        match self.detail {
-            Some(ref s) => write!(fmt, " ({})", *s),
-            None => Ok(())
+        match *self {
+            IoError { kind: OtherIoError, desc: "unknown error", detail: Some(ref detail) } =>
+                write!(fmt, "{}", detail),
+            IoError { detail: None, desc, .. } =>
+                write!(fmt, "{}", desc),
+            IoError { detail: Some(ref detail), desc, .. } =>
+                write!(fmt, "{} ({})", desc, detail)
         }
     }
 }
@@ -484,6 +488,37 @@ pub enum IoErrorKind {
     NoProgress,
 }
 
+/// A trait that lets you add a `detail` to an IoError easily
+trait UpdateIoError<T> {
+    /// Returns an IoError with updated description and detail
+    fn update_err(self, desc: &'static str, detail: |&IoError| -> String) -> Self;
+
+    /// Returns an IoError with updated detail
+    fn update_detail(self, detail: |&IoError| -> String) -> Self;
+
+    /// Returns an IoError with update description
+    fn update_desc(self, desc: &'static str) -> Self;
+}
+
+impl<T> UpdateIoError<T> for IoResult<T> {
+    fn update_err(self, desc: &'static str, detail: |&IoError| -> String) -> IoResult<T> {
+        self.map_err(|mut e| {
+            let detail = detail(&e);
+            e.desc = desc;
+            e.detail = Some(detail);
+            e
+        })
+    }
+
+    fn update_detail(self, detail: |&IoError| -> String) -> IoResult<T> {
+        self.map_err(|mut e| { e.detail = Some(detail(&e)); e })
+    }
+
+    fn update_desc(self, desc: &'static str) -> IoResult<T> {
+        self.map_err(|mut e| { e.desc = desc; e })
+    }
+}
+
 static NO_PROGRESS_LIMIT: uint = 1000;
 
 /// A trait for objects which are byte-oriented streams. Readers are defined by
@@ -1577,7 +1612,7 @@ pub fn standard_error(kind: IoErrorKind) -> IoError {
         ConnectionAborted => "connection aborted",
         NotConnected => "not connected",
         BrokenPipe => "broken pipe",
-        PathAlreadyExists => "file exists",
+        PathAlreadyExists => "file already exists",
         PathDoesntExist => "no such file",
         MismatchedFileTypeForOperation => "mismatched file type",
         ResourceUnavailable => "resource unavailable",
diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs
index a1372b51d47..e2a963c5a87 100644
--- a/src/libstd/rt/backtrace.rs
+++ b/src/libstd/rt/backtrace.rs
@@ -873,12 +873,12 @@ mod imp {
             Err(..) => return Ok(()),
         };
 
-        macro_rules! sym( ($e:expr, $t:ident) => (
-            match unsafe { lib.symbol::<$t>($e) } {
-                Ok(f) => f,
+        macro_rules! sym( ($e:expr, $t:ident) => (unsafe {
+            match lib.symbol($e) {
+                Ok(f) => mem::transmute::<*u8, $t>(f),
                 Err(..) => return Ok(())
             }
-        ) )
+        }) )
 
         // Fetch the symbols necessary from dbghelp.dll
         let SymFromAddr = sym!("SymFromAddr", SymFromAddrFn);
diff --git a/src/libsync/mutex.rs b/src/libsync/mutex.rs
index 6b9ff3cf052..ef558d3f924 100644
--- a/src/libsync/mutex.rs
+++ b/src/libsync/mutex.rs
@@ -97,7 +97,14 @@ pub static NATIVE_BLOCKED: uint = 1 << 2;
 /// drop(guard); // unlock the lock
 /// ```
 pub struct Mutex {
-    lock: StaticMutex,
+    // Note that this static mutex is in a *box*, not inlined into the struct
+    // itself. This is done for memory safety reasons with the usage of a
+    // StaticNativeMutex inside the static mutex above. Once a native mutex has
+    // been used once, its address can never change (it can't be moved). This
+    // mutex type can be safely moved at any time, so to ensure that the native
+    // mutex is used correctly we box the inner lock to give it a constant
+    // address.
+    lock: Box<StaticMutex>,
 }
 
 #[deriving(PartialEq, Show)]
@@ -458,7 +465,7 @@ impl Mutex {
     /// Creates a new mutex in an unlocked state ready for use.
     pub fn new() -> Mutex {
         Mutex {
-            lock: StaticMutex {
+            lock: box StaticMutex {
                 state: atomics::AtomicUint::new(0),
                 flavor: Unsafe::new(Unlocked),
                 green_blocker: Unsafe::new(0),
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 941078b158b..b8e08dab722 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -784,6 +784,8 @@ pub enum Ty_ {
     TyUnboxedFn(Gc<UnboxedFnTy>),
     TyTup(Vec<P<Ty>> ),
     TyPath(Path, Option<OwnedSlice<TyParamBound>>, NodeId), // for #7264; see above
+    // No-op; kept solely so that we can pretty-print faithfully
+    TyParen(P<Ty>),
     TyTypeof(Gc<Expr>),
     // TyInfer means the type should be inferred instead of it having been
     // specified. This can appear anywhere in a type.
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index fcddbfa9a89..8e0a2218ea3 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -737,6 +737,7 @@ pub fn get_inner_tys(ty: P<Ty>) -> Vec<P<Ty>> {
         | ast::TyUniq(ty)
         | ast::TyFixedLengthVec(ty, _) => vec!(ty),
         ast::TyTup(ref tys) => tys.clone(),
+        ast::TyParen(ty) => get_inner_tys(ty),
         _ => Vec::new()
     }
 }
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 148b653b61c..4ef7796c454 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -85,6 +85,7 @@ pub trait AstBuilder {
                       typ: P<ast::Ty>,
                       ex: Gc<ast::Expr>)
                       -> Gc<ast::Stmt>;
+    fn stmt_item(&self, sp: Span, item: Gc<ast::Item>) -> Gc<ast::Stmt>;
 
     // blocks
     fn block(&self, span: Span, stmts: Vec<Gc<ast::Stmt>>,
@@ -239,6 +240,14 @@ pub trait AstBuilder {
                 vi: Vec<ast::ViewItem>,
                 items: Vec<Gc<ast::Item>>) -> Gc<ast::Item>;
 
+    fn item_static(&self,
+                   span: Span,
+                   name: Ident,
+                   ty: P<ast::Ty>,
+                   mutbl: ast::Mutability,
+                   expr: Gc<ast::Expr>)
+                   -> Gc<ast::Item>;
+
     fn item_ty_poly(&self,
                     span: Span,
                     name: Ident,
@@ -484,11 +493,19 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         box(GC) respan(sp, ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID))
     }
 
-    fn block(&self, span: Span, stmts: Vec<Gc<ast::Stmt>>,
-             expr: Option<Gc<Expr>>) -> P<ast::Block> {
+    fn block(&self,
+             span: Span,
+             stmts: Vec<Gc<ast::Stmt>>,
+             expr: Option<Gc<Expr>>)
+             -> P<ast::Block> {
         self.block_all(span, Vec::new(), stmts, expr)
     }
 
+    fn stmt_item(&self, sp: Span, item: Gc<ast::Item>) -> Gc<ast::Stmt> {
+        let decl = respan(sp, ast::DeclItem(item));
+        box(GC) respan(sp, ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID))
+    }
+
     fn block_expr(&self, expr: Gc<ast::Expr>) -> P<ast::Block> {
         self.block_all(expr.span, Vec::new(), Vec::new(), Some(expr))
     }
@@ -942,6 +959,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         )
     }
 
+    fn item_static(&self,
+                   span: Span,
+                   name: Ident,
+                   ty: P<ast::Ty>,
+                   mutbl: ast::Mutability,
+                   expr: Gc<ast::Expr>)
+                   -> Gc<ast::Item> {
+        self.item(span, name, Vec::new(), ast::ItemStatic(ty, mutbl, expr))
+    }
+
     fn item_ty_poly(&self, span: Span, name: Ident, ty: P<ast::Ty>,
                     generics: Generics) -> Gc<ast::Item> {
         self.item(span, name, Vec::new(), ast::ItemTy(ty, generics))
diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs
index b2088d2bc82..b87a25d4a44 100644
--- a/src/libsyntax/ext/bytes.rs
+++ b/src/libsyntax/ext/bytes.rs
@@ -94,6 +94,18 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     }
 
     let e = cx.expr_vec_slice(sp, bytes);
-    let e = quote_expr!(cx, { static BYTES: &'static [u8] = $e; BYTES});
+    let ty = cx.ty(sp, ast::TyVec(cx.ty_ident(sp, cx.ident_of("u8"))));
+    let lifetime = cx.lifetime(sp, cx.ident_of("'static").name);
+    let item = cx.item_static(sp,
+                              cx.ident_of("BYTES"),
+                              cx.ty_rptr(sp,
+                                         ty,
+                                         Some(lifetime),
+                                         ast::MutImmutable),
+                              ast::MutImmutable,
+                              e);
+    let e = cx.expr_block(cx.block(sp,
+                                   vec!(cx.stmt_item(sp, item)),
+                                   Some(cx.expr_ident(sp, cx.ident_of("BYTES")))));
     MacExpr::new(e)
 }
diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs
index d1a4d2f3ee3..9ef7241ca24 100644
--- a/src/libsyntax/ext/env.rs
+++ b/src/libsyntax/ext/env.rs
@@ -43,7 +43,7 @@ pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                                                         cx.ident_of("str")),
                                                    Some(cx.lifetime(sp,
                                                         cx.ident_of(
-                                                            "static").name)),
+                                                            "'static").name)),
                                                    ast::MutImmutable))))
       }
       Some(s) => {
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index d3b73cbe33a..cfce4b1e0fc 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -465,7 +465,7 @@ impl<'a, 'b> Context<'a, 'b> {
                     self.ecx.ident_of("rt"),
                     self.ecx.ident_of("Piece")),
                 vec!(self.ecx.lifetime(self.fmtsp,
-                                       self.ecx.ident_of("static").name)),
+                                       self.ecx.ident_of("'static").name)),
                 Vec::new()
             ), None);
         let ty = ast::TyFixedLengthVec(
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 185924f704c..4f1e2ab356e 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -358,9 +358,8 @@ pub fn expand_quote_item(cx: &mut ExtCtxt,
                          sp: Span,
                          tts: &[ast::TokenTree])
                          -> Box<base::MacResult> {
-    let e_attrs = cx.expr_vec_ng(sp);
-    let expanded = expand_parse_call(cx, sp, "parse_item",
-                                    vec!(e_attrs), tts);
+    let expanded = expand_parse_call(cx, sp, "parse_item_with_outer_attributes",
+                                    vec!(), tts);
     base::MacExpr::new(expanded)
 }
 
@@ -368,9 +367,7 @@ pub fn expand_quote_pat(cx: &mut ExtCtxt,
                         sp: Span,
                         tts: &[ast::TokenTree])
                         -> Box<base::MacResult> {
-    let e_refutable = cx.expr_lit(sp, ast::LitBool(true));
-    let expanded = expand_parse_call(cx, sp, "parse_pat",
-                                    vec!(e_refutable), tts);
+    let expanded = expand_parse_call(cx, sp, "parse_pat", vec!(), tts);
     base::MacExpr::new(expanded)
 }
 
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index c4990255719..72c578b8769 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -73,8 +73,7 @@ impl<'a> MacResult for ParserAnyMacro<'a> {
         let mut ret = SmallVector::zero();
         loop {
             let mut parser = self.parser.borrow_mut();
-            let attrs = parser.parse_outer_attributes();
-            match parser.parse_item(attrs) {
+            match parser.parse_item_with_outer_attributes() {
                 Some(item) => ret.push(item),
                 None => break
             }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index d8c7ffe4db7..d61a79e4e80 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -192,6 +192,7 @@ pub trait Folder {
                 })
             }
             TyTup(ref tys) => TyTup(tys.iter().map(|&ty| self.fold_ty(ty)).collect()),
+            TyParen(ref ty) => TyParen(self.fold_ty(*ty)),
             TyPath(ref path, ref bounds, id) => {
                 let id = self.new_id(id);
                 TyPath(self.fold_path(path),
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index bb23fe50bd9..459cb6d31ed 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -757,19 +757,34 @@ impl<'a> StringReader<'a> {
                 while ident_continue(self.curr) {
                     self.bump();
                 }
+
+                // Include the leading `'` in the real identifier, for macro
+                // expansion purposes. See #12512 for the gory details of why
+                // this is necessary.
                 let ident = self.with_str_from(start, |lifetime_name| {
-                    str_to_ident(lifetime_name)
+                    str_to_ident(format!("'{}", lifetime_name).as_slice())
                 });
-                let tok = &token::IDENT(ident, false);
-
-                if token::is_keyword(token::keywords::Self, tok) {
-                    self.err_span(start, self.last_pos,
-                               "invalid lifetime name: 'self \
-                                is no longer a special lifetime");
-                } else if token::is_any_keyword(tok) &&
-                    !token::is_keyword(token::keywords::Static, tok) {
-                    self.err_span(start, self.last_pos,
-                               "invalid lifetime name");
+
+                // Conjure up a "keyword checking ident" to make sure that
+                // the lifetime name is not a keyword.
+                let keyword_checking_ident =
+                    self.with_str_from(start, |lifetime_name| {
+                        str_to_ident(lifetime_name)
+                    });
+                let keyword_checking_token =
+                    &token::IDENT(keyword_checking_ident, false);
+                if token::is_keyword(token::keywords::Self,
+                                     keyword_checking_token) {
+                    self.err_span(start,
+                                  self.last_pos,
+                                  "invalid lifetime name: 'self \
+                                   is no longer a special lifetime");
+                } else if token::is_any_keyword(keyword_checking_token) &&
+                    !token::is_keyword(token::keywords::Static,
+                                       keyword_checking_token) {
+                    self.err_span(start,
+                                  self.last_pos,
+                                  "invalid lifetime name");
                 }
                 return token::LIFETIME(ident);
             }
@@ -1128,7 +1143,7 @@ mod test {
 
     #[test] fn lifetime_name() {
         assert_eq!(setup(&mk_sh(), "'abc".to_string()).next_token().tok,
-                   token::LIFETIME(token::str_to_ident("abc")));
+                   token::LIFETIME(token::str_to_ident("'abc")));
     }
 
     #[test] fn raw_string() {
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 88746d145b6..1ebcbc8a7d1 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -117,8 +117,7 @@ pub fn parse_item_from_source_str(name: String,
                                   sess: &ParseSess)
                                   -> Option<Gc<ast::Item>> {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
-    let attrs = p.parse_outer_attributes();
-    maybe_aborted(p.parse_item(attrs),p)
+    maybe_aborted(p.parse_item_with_outer_attributes(),p)
 }
 
 pub fn parse_meta_from_source_str(name: String,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 437b06e3df6..d11d303059f 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -51,7 +51,7 @@ use ast::{TokenTree, TraitMethod, TraitRef, TTDelim, TTSeq, TTTok};
 use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox};
 use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
 use ast::{TyTypeof, TyInfer, TypeMethod};
-use ast::{TyNil, TyParam, TyParamBound, TyPath, TyPtr, TyRptr};
+use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyRptr};
 use ast::{TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq};
 use ast::{UnboxedFnTy, UnboxedFnTyParamBound, UnnamedField, UnsafeBlock};
 use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
@@ -105,7 +105,7 @@ pub enum PathParsingMode {
     /// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`
     LifetimeAndTypesWithColons,
     /// A path with a lifetime and type parameters with bounds before the last
-    /// set of type parameters only; e.g. `foo::bar<'a>::Baz:X+Y<T>` This
+    /// set of type parameters only; e.g. `foo::bar<'a>::Baz+X+Y<T>` This
     /// form does not use extra double colons.
     LifetimeAndTypesAndBounds,
 }
@@ -1015,7 +1015,14 @@ impl<'a> Parser<'a> {
         };
 
         let (inputs, variadic) = self.parse_fn_args(false, false);
-        let (_, bounds) = self.parse_optional_ty_param_bounds(false);
+        let bounds = {
+            if self.eat(&token::COLON) {
+                let (_, bounds) = self.parse_ty_param_bounds(false);
+                Some(bounds)
+            } else {
+                None
+            }
+        };
         let (ret_style, ret_ty) = self.parse_ret_ty();
         let decl = P(FnDecl {
             inputs: inputs,
@@ -1083,7 +1090,14 @@ impl<'a> Parser<'a> {
             (is_unboxed, inputs)
         };
 
-        let (region, bounds) = self.parse_optional_ty_param_bounds(true);
+        let (region, bounds) = {
+            if self.eat(&token::COLON) {
+                let (region, bounds) = self.parse_ty_param_bounds(true);
+                (region, Some(bounds))
+            } else {
+                (None, None)
+            }
+        };
 
         let (return_style, output) = self.parse_ret_ty();
         let decl = P(FnDecl {
@@ -1227,7 +1241,7 @@ impl<'a> Parser<'a> {
     // parse a possibly mutable type
     pub fn parse_mt(&mut self) -> MutTy {
         let mutbl = self.parse_mutability();
-        let t = self.parse_ty(false);
+        let t = self.parse_ty(true);
         MutTy { ty: t, mutbl: mutbl }
     }
 
@@ -1238,7 +1252,7 @@ impl<'a> Parser<'a> {
         let mutbl = self.parse_mutability();
         let id = self.parse_ident();
         self.expect(&token::COLON);
-        let ty = self.parse_ty(false);
+        let ty = self.parse_ty(true);
         let hi = ty.span.hi;
         ast::TypeField {
             ident: id,
@@ -1261,7 +1275,7 @@ impl<'a> Parser<'a> {
                     })
                 )
             } else {
-                (Return, self.parse_ty(false))
+                (Return, self.parse_ty(true))
             }
         } else {
             let pos = self.span.lo;
@@ -1276,10 +1290,11 @@ impl<'a> Parser<'a> {
         }
     }
 
-    // parse a type.
-    // Useless second parameter for compatibility with quasiquote macros.
-    // Bleh!
-    pub fn parse_ty(&mut self, _: bool) -> P<Ty> {
+    /// Parse a type.
+    ///
+    /// The second parameter specifies whether the `+` binary operator is
+    /// allowed in the type grammar.
+    pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
         maybe_whole!(no_clone self, NtTy);
 
         let lo = self.span.lo;
@@ -1293,12 +1308,12 @@ impl<'a> Parser<'a> {
                 // (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(false));
+                let mut ts = vec!(self.parse_ty(true));
                 let mut one_tuple = false;
                 while self.token == token::COMMA {
                     self.bump();
                     if self.token != token::RPAREN {
-                        ts.push(self.parse_ty(false));
+                        ts.push(self.parse_ty(true));
                     }
                     else {
                         one_tuple = true;
@@ -1307,17 +1322,17 @@ impl<'a> Parser<'a> {
 
                 if ts.len() == 1 && !one_tuple {
                     self.expect(&token::RPAREN);
-                    return *ts.get(0)
+                    TyParen(*ts.get(0))
+                } else {
+                    let t = TyTup(ts);
+                    self.expect(&token::RPAREN);
+                    t
                 }
-
-                let t = TyTup(ts);
-                self.expect(&token::RPAREN);
-                t
             }
         } else if self.token == token::AT {
             // MANAGED POINTER
             self.bump();
-            TyBox(self.parse_ty(false))
+            TyBox(self.parse_ty(plus_allowed))
         } else if self.token == token::TILDE {
             // OWNED POINTER
             self.bump();
@@ -1326,7 +1341,7 @@ impl<'a> Parser<'a> {
                     self.obsolete(self.last_span, ObsoleteOwnedVector),
                 _ => self.obsolete(self.last_span, ObsoleteOwnedType),
             };
-            TyUniq(self.parse_ty(false))
+            TyUniq(self.parse_ty(true))
         } else if self.token == token::BINOP(token::STAR) {
             // STAR POINTER (bare pointer?)
             self.bump();
@@ -1334,7 +1349,7 @@ impl<'a> Parser<'a> {
         } else if self.token == token::LBRACKET {
             // VECTOR
             self.expect(&token::LBRACKET);
-            let t = self.parse_ty(false);
+            let t = self.parse_ty(true);
 
             // Parse the `, ..e` in `[ int, ..e ]`
             // where `e` is a const expression
@@ -1377,10 +1392,15 @@ impl<'a> Parser<'a> {
         } else if self.token == token::MOD_SEP
             || is_ident_or_path(&self.token) {
             // NAMED TYPE
+            let mode = if plus_allowed {
+                LifetimeAndTypesAndBounds
+            } else {
+                LifetimeAndTypesWithoutColons
+            };
             let PathAndBounds {
                 path,
                 bounds
-            } = self.parse_path(LifetimeAndTypesAndBounds);
+            } = self.parse_path(mode);
             TyPath(path, bounds, ast::DUMMY_NODE_ID)
         } else if self.eat(&token::UNDERSCORE) {
             // TYPE TO BE INFERRED
@@ -1438,7 +1458,7 @@ impl<'a> Parser<'a> {
                                    special_idents::invalid)
         };
 
-        let t = self.parse_ty(false);
+        let t = self.parse_ty(true);
 
         Arg {
             ty: t,
@@ -1456,7 +1476,7 @@ impl<'a> Parser<'a> {
     pub fn parse_fn_block_arg(&mut self) -> Arg {
         let pat = self.parse_pat();
         let t = if self.eat(&token::COLON) {
-            self.parse_ty(false)
+            self.parse_ty(true)
         } else {
             P(Ty {
                 id: ast::DUMMY_NODE_ID,
@@ -1611,9 +1631,19 @@ impl<'a> Parser<'a> {
             }
         }
 
-        // Next, parse a colon and bounded type parameters, if applicable.
+        // Next, parse a plus and bounded type parameters, if applicable.
+        //
+        // NOTE(stage0, pcwalton): Remove `token::COLON` after a snapshot.
         let bounds = if mode == LifetimeAndTypesAndBounds {
-            let (_, bounds) = self.parse_optional_ty_param_bounds(false);
+            let bounds = {
+                if self.eat(&token::BINOP(token::PLUS)) ||
+                        self.eat(&token::COLON) {
+                    let (_, bounds) = self.parse_ty_param_bounds(false);
+                    Some(bounds)
+                } else {
+                    None
+                }
+            };
             bounds
         } else {
             None
@@ -2438,7 +2468,7 @@ impl<'a> Parser<'a> {
             }
             None => {
                 if as_prec > min_prec && self.eat_keyword(keywords::As) {
-                    let rhs = self.parse_ty(true);
+                    let rhs = self.parse_ty(false);
                     let _as = self.mk_expr(lhs.span.lo,
                                            rhs.span.hi,
                                            ExprCast(lhs, rhs));
@@ -3067,7 +3097,9 @@ impl<'a> Parser<'a> {
             node: TyInfer,
             span: mk_sp(lo, lo),
         });
-        if self.eat(&token::COLON) { ty = self.parse_ty(false); }
+        if self.eat(&token::COLON) {
+            ty = self.parse_ty(true);
+        }
         let init = self.parse_initializer();
         box(GC) ast::Local {
             ty: ty,
@@ -3095,7 +3127,7 @@ impl<'a> Parser<'a> {
         }
         let name = self.parse_ident();
         self.expect(&token::COLON);
-        let ty = self.parse_ty(false);
+        let ty = self.parse_ty(true);
         spanned(lo, self.last_span.hi, ast::StructField_ {
             kind: NamedField(name, pr),
             id: ast::DUMMY_NODE_ID,
@@ -3427,7 +3459,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    // matches optbounds = ( ( : ( boundseq )? )? )
+    // matches bounds    = ( boundseq )?
     // where   boundseq  = ( bound + boundseq ) | bound
     // and     bound     = 'static | ty
     // Returns "None" if there's no colon (e.g. "T");
@@ -3439,20 +3471,16 @@ impl<'a> Parser<'a> {
     // AST doesn't support arbitrary lifetimes in bounds on type parameters. In
     // the future, this flag should be removed, and the return value of this
     // function should be Option<~[TyParamBound]>
-    fn parse_optional_ty_param_bounds(&mut self, allow_any_lifetime: bool)
-        -> (Option<ast::Lifetime>, Option<OwnedSlice<TyParamBound>>)
-    {
-        if !self.eat(&token::COLON) {
-            return (None, None);
-        }
-
+    fn parse_ty_param_bounds(&mut self, allow_any_lifetime: bool)
+                             -> (Option<ast::Lifetime>,
+                                 OwnedSlice<TyParamBound>) {
         let mut ret_lifetime = None;
         let mut result = vec!();
         loop {
             match self.token {
                 token::LIFETIME(lifetime) => {
                     let lifetime_interned_string = token::get_ident(lifetime);
-                    if lifetime_interned_string.equiv(&("static")) {
+                    if lifetime_interned_string.equiv(&("'static")) {
                         result.push(StaticRegionTyParamBound);
                         if allow_any_lifetime && ret_lifetime.is_none() {
                             ret_lifetime = Some(ast::Lifetime {
@@ -3489,7 +3517,7 @@ impl<'a> Parser<'a> {
             }
         }
 
-        return (ret_lifetime, Some(OwnedSlice::from_vec(result)));
+        return (ret_lifetime, OwnedSlice::from_vec(result));
     }
 
     // matches typaram = type? IDENT optbounds ( EQ ty )?
@@ -3497,13 +3525,20 @@ impl<'a> Parser<'a> {
         let sized = self.parse_sized();
         let span = self.span;
         let ident = self.parse_ident();
-        let (_, opt_bounds) = self.parse_optional_ty_param_bounds(false);
+        let opt_bounds = {
+            if self.eat(&token::COLON) {
+                let (_, bounds) = self.parse_ty_param_bounds(false);
+                Some(bounds)
+            } else {
+                None
+            }
+        };
         // For typarams we don't care about the difference b/w "<T>" and "<T:>".
         let bounds = opt_bounds.unwrap_or_default();
 
         let default = if self.token == token::EQ {
             self.bump();
-            Some(self.parse_ty(false))
+            Some(self.parse_ty(true))
         }
         else { None };
 
@@ -3548,7 +3583,7 @@ impl<'a> Parser<'a> {
             Some(token::COMMA),
             |p| {
                 p.forbid_lifetime();
-                p.parse_ty(false)
+                p.parse_ty(true)
             }
         );
         (lifetimes, result.into_vec())
@@ -3804,7 +3839,7 @@ impl<'a> Parser<'a> {
             }
         };
         let output = if self.eat(&token::RARROW) {
-            self.parse_ty(false)
+            self.parse_ty(true)
         } else {
             P(Ty {
                 id: ast::DUMMY_NODE_ID,
@@ -3830,7 +3865,7 @@ impl<'a> Parser<'a> {
                                      |p| p.parse_fn_block_arg());
 
         let output = if self.eat(&token::RARROW) {
-            self.parse_ty(false)
+            self.parse_ty(true)
         } else {
             P(Ty {
                 id: ast::DUMMY_NODE_ID,
@@ -3942,7 +3977,7 @@ impl<'a> Parser<'a> {
         let could_be_trait = self.token != token::LPAREN;
 
         // Parse the trait.
-        let mut ty = self.parse_ty(false);
+        let mut ty = self.parse_ty(true);
 
         // Parse traits, if necessary.
         let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
@@ -3965,7 +4000,7 @@ impl<'a> Parser<'a> {
                 }
             };
 
-            ty = self.parse_ty(false);
+            ty = self.parse_ty(true);
             opt_trait_ref
         } else {
             None
@@ -4008,7 +4043,7 @@ impl<'a> Parser<'a> {
         let generics = self.parse_generics();
 
         let super_struct = if self.eat(&token::COLON) {
-            let ty = self.parse_ty(false);
+            let ty = self.parse_ty(true);
             match ty.node {
                 TyPath(_, None, _) => {
                     Some(ty)
@@ -4051,7 +4086,7 @@ impl<'a> Parser<'a> {
                 let struct_field_ = ast::StructField_ {
                     kind: UnnamedField(p.parse_visibility()),
                     id: ast::DUMMY_NODE_ID,
-                    ty: p.parse_ty(false),
+                    ty: p.parse_ty(true),
                     attrs: attrs,
                 };
                 spanned(lo, p.span.hi, struct_field_)
@@ -4205,7 +4240,7 @@ impl<'a> Parser<'a> {
         let m = if self.eat_keyword(keywords::Mut) {MutMutable} else {MutImmutable};
         let id = self.parse_ident();
         self.expect(&token::COLON);
-        let ty = self.parse_ty(false);
+        let ty = self.parse_ty(true);
         self.expect(&token::EQ);
         let e = self.parse_expr();
         self.commit_expr_expecting(e, token::SEMI);
@@ -4386,7 +4421,7 @@ impl<'a> Parser<'a> {
 
         let ident = self.parse_ident();
         self.expect(&token::COLON);
-        let ty = self.parse_ty(false);
+        let ty = self.parse_ty(true);
         let hi = self.span.hi;
         self.expect(&token::SEMI);
         box(GC) ast::ForeignItem {
@@ -4514,7 +4549,7 @@ impl<'a> Parser<'a> {
         let ident = self.parse_ident();
         let tps = self.parse_generics();
         self.expect(&token::EQ);
-        let ty = self.parse_ty(false);
+        let ty = self.parse_ty(true);
         self.expect(&token::SEMI);
         (ident, ItemTy(ty, tps), None)
     }
@@ -4562,7 +4597,7 @@ impl<'a> Parser<'a> {
                     &token::LPAREN,
                     &token::RPAREN,
                     seq_sep_trailing_disallowed(token::COMMA),
-                    |p| p.parse_ty(false)
+                    |p| p.parse_ty(true)
                 );
                 for ty in arg_tys.move_iter() {
                     args.push(ast::VariantArg {
@@ -4930,6 +4965,11 @@ impl<'a> Parser<'a> {
         return IoviNone(attrs);
     }
 
+    pub fn parse_item_with_outer_attributes(&mut self) -> Option<Gc<Item>> {
+        let attrs = self.parse_outer_attributes();
+        self.parse_item(attrs)
+    }
+
     pub fn parse_item(&mut self, attrs: Vec<Attribute> ) -> Option<Gc<Item>> {
         match self.parse_item_or_view_item(attrs, true) {
             IoviNone(_) => None,
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index fa70261a7d7..a4a022708d9 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -232,7 +232,7 @@ pub fn to_str(t: &Token) -> String {
       /* Name components */
       IDENT(s, _) => get_ident(s).get().to_string(),
       LIFETIME(s) => {
-          (format!("'{}", get_ident(s))).to_string()
+          (format!("{}", get_ident(s))).to_string()
       }
       UNDERSCORE => "_".to_string(),
 
@@ -433,71 +433,72 @@ declare_special_idents_and_keywords! {
         (0,                          invalid,                "");
         (super::SELF_KEYWORD_NAME,   self_,                  "self");
         (super::STATIC_KEYWORD_NAME, statik,                 "static");
+        (3,                          static_lifetime,        "'static");
 
         // for matcher NTs
-        (3,                          tt,                     "tt");
-        (4,                          matchers,               "matchers");
+        (4,                          tt,                     "tt");
+        (5,                          matchers,               "matchers");
 
         // outside of libsyntax
-        (5,                          clownshoe_abi,          "__rust_abi");
-        (6,                          opaque,                 "<opaque>");
-        (7,                          unnamed_field,          "<unnamed_field>");
-        (8,                          type_self,              "Self");
+        (6,                          clownshoe_abi,          "__rust_abi");
+        (7,                          opaque,                 "<opaque>");
+        (8,                          unnamed_field,          "<unnamed_field>");
+        (9,                          type_self,              "Self");
     }
 
     pub mod keywords {
         // These ones are variants of the Keyword enum
 
         'strict:
-        (9,                          As,         "as");
-        (10,                         Break,      "break");
-        (11,                         Crate,      "crate");
-        (12,                         Else,       "else");
-        (13,                         Enum,       "enum");
-        (14,                         Extern,     "extern");
-        (15,                         False,      "false");
-        (16,                         Fn,         "fn");
-        (17,                         For,        "for");
-        (18,                         If,         "if");
-        (19,                         Impl,       "impl");
-        (20,                         In,         "in");
-        (21,                         Let,        "let");
-        (22,                         Loop,       "loop");
-        (23,                         Match,      "match");
-        (24,                         Mod,        "mod");
-        (25,                         Mut,        "mut");
-        (26,                         Once,       "once");
-        (27,                         Pub,        "pub");
-        (28,                         Ref,        "ref");
-        (29,                         Return,     "return");
+        (10,                         As,         "as");
+        (11,                         Break,      "break");
+        (12,                         Crate,      "crate");
+        (13,                         Else,       "else");
+        (14,                         Enum,       "enum");
+        (15,                         Extern,     "extern");
+        (16,                         False,      "false");
+        (17,                         Fn,         "fn");
+        (18,                         For,        "for");
+        (19,                         If,         "if");
+        (20,                         Impl,       "impl");
+        (21,                         In,         "in");
+        (22,                         Let,        "let");
+        (23,                         Loop,       "loop");
+        (24,                         Match,      "match");
+        (25,                         Mod,        "mod");
+        (26,                         Mut,        "mut");
+        (27,                         Once,       "once");
+        (28,                         Pub,        "pub");
+        (29,                         Ref,        "ref");
+        (30,                         Return,     "return");
         // Static and Self are also special idents (prefill de-dupes)
         (super::STATIC_KEYWORD_NAME, Static,     "static");
         (super::SELF_KEYWORD_NAME,   Self,       "self");
-        (30,                         Struct,     "struct");
-        (31,                         Super,      "super");
-        (32,                         True,       "true");
-        (33,                         Trait,      "trait");
-        (34,                         Type,       "type");
-        (35,                         Unsafe,     "unsafe");
-        (36,                         Use,        "use");
-        (37,                         Virtual,    "virtual");
-        (38,                         While,      "while");
-        (39,                         Continue,   "continue");
-        (40,                         Proc,       "proc");
-        (41,                         Box,        "box");
+        (31,                         Struct,     "struct");
+        (32,                         Super,      "super");
+        (33,                         True,       "true");
+        (34,                         Trait,      "trait");
+        (35,                         Type,       "type");
+        (36,                         Unsafe,     "unsafe");
+        (37,                         Use,        "use");
+        (38,                         Virtual,    "virtual");
+        (39,                         While,      "while");
+        (40,                         Continue,   "continue");
+        (41,                         Proc,       "proc");
+        (42,                         Box,        "box");
 
         'reserved:
-        (42,                         Alignof,    "alignof");
-        (43,                         Be,         "be");
-        (44,                         Const,      "const");
-        (45,                         Offsetof,   "offsetof");
-        (46,                         Priv,       "priv");
-        (47,                         Pure,       "pure");
-        (48,                         Sizeof,     "sizeof");
-        (49,                         Typeof,     "typeof");
-        (50,                         Unsized,    "unsized");
-        (51,                         Yield,      "yield");
-        (52,                         Do,         "do");
+        (43,                         Alignof,    "alignof");
+        (44,                         Be,         "be");
+        (45,                         Const,      "const");
+        (46,                         Offsetof,   "offsetof");
+        (47,                         Priv,       "priv");
+        (48,                         Pure,       "pure");
+        (49,                         Sizeof,     "sizeof");
+        (50,                         Typeof,     "typeof");
+        (51,                         Unsized,    "unsized");
+        (52,                         Yield,      "yield");
+        (53,                         Do,         "do");
     }
 }
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 33b7086d7ae..63acdb1a6ca 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 use abi;
-use ast::{P, StaticRegionTyParamBound, OtherRegionTyParamBound,
-          TraitTyParamBound, UnboxedFnTyParamBound, Required, Provided};
+use ast::{P, StaticRegionTyParamBound, OtherRegionTyParamBound};
+use ast::{TraitTyParamBound, UnboxedFnTyParamBound, Required, Provided};
 use ast;
 use ast_util;
 use owned_slice::OwnedSlice;
@@ -495,6 +495,11 @@ impl<'a> State<'a> {
                 }
                 try!(self.pclose());
             }
+            ast::TyParen(ref typ) => {
+                try!(self.popen());
+                try!(self.print_type(&**typ));
+                try!(self.pclose());
+            }
             ast::TyBareFn(f) => {
                 let generics = ast::Generics {
                     lifetimes: f.lifetimes.clone(),
@@ -1325,7 +1330,6 @@ impl<'a> State<'a> {
             }
             ast::ExprForLoop(ref pat, ref iter, ref blk, opt_ident) => {
                 for ident in opt_ident.iter() {
-                    try!(word(&mut self.s, "'"));
                     try!(self.print_ident(*ident));
                     try!(self.word_space(":"));
                 }
@@ -1339,7 +1343,6 @@ impl<'a> State<'a> {
             }
             ast::ExprLoop(ref blk, opt_ident) => {
                 for ident in opt_ident.iter() {
-                    try!(word(&mut self.s, "'"));
                     try!(self.print_ident(*ident));
                     try!(self.word_space(":"));
                 }
@@ -1504,7 +1507,6 @@ impl<'a> State<'a> {
                 try!(word(&mut self.s, "break"));
                 try!(space(&mut self.s));
                 for ident in opt_ident.iter() {
-                    try!(word(&mut self.s, "'"));
                     try!(self.print_ident(*ident));
                     try!(space(&mut self.s));
                 }
@@ -1513,7 +1515,6 @@ impl<'a> State<'a> {
                 try!(word(&mut self.s, "continue"));
                 try!(space(&mut self.s));
                 for ident in opt_ident.iter() {
-                    try!(word(&mut self.s, "'"));
                     try!(self.print_ident(*ident));
                     try!(space(&mut self.s))
                 }
@@ -1677,7 +1678,7 @@ impl<'a> State<'a> {
 
         match *opt_bounds {
             None => Ok(()),
-            Some(ref bounds) => self.print_bounds(&None, bounds, true),
+            Some(ref bounds) => self.print_bounds(&None, bounds, true, true),
         }
     }
 
@@ -1936,14 +1937,21 @@ impl<'a> State<'a> {
     pub fn print_bounds(&mut self,
                         region: &Option<ast::Lifetime>,
                         bounds: &OwnedSlice<ast::TyParamBound>,
-                        print_colon_anyway: bool) -> IoResult<()> {
+                        print_colon_anyway: bool,
+                        print_plus_before_bounds: bool)
+                        -> IoResult<()> {
+        let separator = if print_plus_before_bounds {
+            "+"
+        } else {
+            ":"
+        };
         if !bounds.is_empty() || region.is_some() {
-            try!(word(&mut self.s, ":"));
+            try!(word(&mut self.s, separator));
             let mut first = true;
             match *region {
                 Some(ref lt) => {
                     let token = token::get_name(lt.name);
-                    if token.get() != "static" {
+                    if token.get() != "'static" {
                         try!(self.nbsp());
                         first = false;
                         try!(self.print_lifetime(lt));
@@ -1980,7 +1988,7 @@ impl<'a> State<'a> {
             }
             Ok(())
         } else if print_colon_anyway {
-            word(&mut self.s, ":")
+            word(&mut self.s, separator)
         } else {
             Ok(())
         }
@@ -1988,7 +1996,6 @@ impl<'a> State<'a> {
 
     pub fn print_lifetime(&mut self,
                           lifetime: &ast::Lifetime) -> IoResult<()> {
-        try!(word(&mut self.s, "'"));
         self.print_name(lifetime.name)
     }
 
@@ -2016,7 +2023,10 @@ impl<'a> State<'a> {
                             try!(s.word_space("type"));
                         }
                         try!(s.print_ident(param.ident));
-                        try!(s.print_bounds(&None, &param.bounds, false));
+                        try!(s.print_bounds(&None,
+                                            &param.bounds,
+                                            false,
+                                            false));
                         match param.default {
                             Some(ref default) => {
                                 try!(space(&mut s.s));
@@ -2219,7 +2229,7 @@ impl<'a> State<'a> {
         }
 
         opt_bounds.as_ref().map(|bounds| {
-            self.print_bounds(opt_region, bounds, true)
+            self.print_bounds(opt_region, bounds, true, false)
         });
 
         try!(self.maybe_print_comment(decl.output.span.lo));
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 59771a57dfa..6f0fc217533 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -336,7 +336,7 @@ pub fn skip_ty<E, V: Visitor<E>>(_: &mut V, _: &Ty, _: E) {
 
 pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
     match typ.node {
-        TyUniq(ty) | TyVec(ty) | TyBox(ty) => {
+        TyUniq(ty) | TyVec(ty) | TyBox(ty) | TyParen(ty) => {
             visitor.visit_ty(&*ty, env)
         }
         TyPtr(ref mutable_type) => {
diff --git a/src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs b/src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs
index 213fdd6b74a..1592ffb6c67 100644
--- a/src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs
+++ b/src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs
@@ -27,7 +27,7 @@ impl Drop for Foo {
 
 #[plugin_registrar]
 pub fn registrar(_: &mut Registry) {
-    local_data_key!(foo: Box<Any:Send>);
-    foo.replace(Some(box Foo { foo: 10 } as Box<Any:Send>));
+    local_data_key!(foo: Box<Any+Send>);
+    foo.replace(Some(box Foo { foo: 10 } as Box<Any+Send>));
 }
 
diff --git a/src/test/compile-fail/hygienic-label-1.rs b/src/test/compile-fail/hygienic-label-1.rs
index 010cde769d7..0e87dc97c26 100644
--- a/src/test/compile-fail/hygienic-label-1.rs
+++ b/src/test/compile-fail/hygienic-label-1.rs
@@ -15,5 +15,5 @@ macro_rules! foo {
 }
 
 pub fn main() {
-    'x: loop { foo!() } //~ ERROR use of undeclared label `x`
+    'x: loop { foo!() } //~ ERROR use of undeclared label `'x`
 }
diff --git a/src/test/compile-fail/hygienic-label-2.rs b/src/test/compile-fail/hygienic-label-2.rs
index 78d8fce38d5..fe87e32459b 100644
--- a/src/test/compile-fail/hygienic-label-2.rs
+++ b/src/test/compile-fail/hygienic-label-2.rs
@@ -15,5 +15,5 @@ macro_rules! foo {
 }
 
 pub fn main() {
-    foo!(break 'x); //~ ERROR use of undeclared label `x`
+    foo!(break 'x); //~ ERROR use of undeclared label `'x`
 }
diff --git a/src/test/compile-fail/hygienic-label-3.rs b/src/test/compile-fail/hygienic-label-3.rs
index 439132fa152..b5954ac9930 100644
--- a/src/test/compile-fail/hygienic-label-3.rs
+++ b/src/test/compile-fail/hygienic-label-3.rs
@@ -16,6 +16,6 @@ macro_rules! foo {
 
 pub fn main() {
     'x: for _ in range(0,1) {
-        foo!() //~ ERROR use of undeclared label `x`
+        foo!() //~ ERROR use of undeclared label `'x`
     };
 }
diff --git a/src/test/compile-fail/hygienic-label-4.rs b/src/test/compile-fail/hygienic-label-4.rs
index dfda4586527..67fa56b1306 100644
--- a/src/test/compile-fail/hygienic-label-4.rs
+++ b/src/test/compile-fail/hygienic-label-4.rs
@@ -15,5 +15,5 @@ macro_rules! foo {
 }
 
 pub fn main() {
-    foo!(break 'x); //~ ERROR use of undeclared label `x`
+    foo!(break 'x); //~ ERROR use of undeclared label `'x`
 }
diff --git a/src/test/compile-fail/issue-14845.rs b/src/test/compile-fail/issue-14845.rs
new file mode 100644
index 00000000000..90366d09e2d
--- /dev/null
+++ b/src/test/compile-fail/issue-14845.rs
@@ -0,0 +1,24 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+struct X {
+    a: [u8, ..1]
+}
+
+fn main() {
+    let x = X { a: [0] };
+    let _f = &x.a as *mut u8;
+    //~^ ERROR mismatched types: expected `*mut u8` but found `&[u8, .. 1]`
+
+    let local = [0u8];
+    let _v = &local as *mut u8;
+    //~^ ERROR mismatched types: expected `*mut u8` but found `&[u8, .. 1]`
+}
diff --git a/src/test/compile-fail/issue-7013.rs b/src/test/compile-fail/issue-7013.rs
index 1bc4e076553..3028db00f58 100644
--- a/src/test/compile-fail/issue-7013.rs
+++ b/src/test/compile-fail/issue-7013.rs
@@ -31,7 +31,7 @@ struct A {
 }
 
 fn main() {
-    let a = A {v: box B{v: None} as Box<Foo:Send>};
+    let a = A {v: box B{v: None} as Box<Foo+Send>};
     //~^ ERROR cannot pack type `~B`, which does not fulfill `Send`
     let v = Rc::new(RefCell::new(a));
     let w = v.clone();
diff --git a/src/test/compile-fail/kindck-copy.rs b/src/test/compile-fail/kindck-copy.rs
index 5404b32eb24..651ea6abf08 100644
--- a/src/test/compile-fail/kindck-copy.rs
+++ b/src/test/compile-fail/kindck-copy.rs
@@ -45,15 +45,15 @@ fn test<'a,T,U:Copy>(_: &'a int) {
 
     // borrowed object types are generally ok
     assert_copy::<&'a Dummy>();
-    assert_copy::<&'a Dummy:Copy>();
-    assert_copy::<&'static Dummy:Copy>();
+    assert_copy::<&'a Dummy+Copy>();
+    assert_copy::<&'static Dummy+Copy>();
 
     // owned object types are not ok
     assert_copy::<Box<Dummy>>(); //~ ERROR does not fulfill
-    assert_copy::<Box<Dummy:Copy>>(); //~ ERROR does not fulfill
+    assert_copy::<Box<Dummy+Copy>>(); //~ ERROR does not fulfill
 
     // mutable object types are not ok
-    assert_copy::<&'a mut Dummy:Copy>();  //~ ERROR does not fulfill
+    assert_copy::<&'a mut Dummy+Copy>();  //~ ERROR does not fulfill
 
     // closures are like an `&mut` object
     assert_copy::<||>(); //~ ERROR does not fulfill
diff --git a/src/test/compile-fail/kindck-send.rs b/src/test/compile-fail/kindck-send.rs
index aa9d2dda22a..0414e64f1b7 100644
--- a/src/test/compile-fail/kindck-send.rs
+++ b/src/test/compile-fail/kindck-send.rs
@@ -39,17 +39,17 @@ fn test<'a,T,U:Send>(_: &'a int) {
     // careful with object types, who knows what they close over...
     assert_send::<&'static Dummy>(); //~ ERROR does not fulfill `Send`
     assert_send::<&'a Dummy>(); //~ ERROR does not fulfill `Send`
-    assert_send::<&'a Dummy:Send>(); //~ ERROR does not fulfill `Send`
-    assert_send::<Box<Dummy:>>(); //~ ERROR does not fulfill `Send`
+    assert_send::<&'a Dummy+Send>(); //~ ERROR does not fulfill `Send`
+    assert_send::<Box<Dummy+>>(); //~ ERROR does not fulfill `Send`
 
     // ...unless they are properly bounded
-    assert_send::<&'static Dummy:Send>();
-    assert_send::<Box<Dummy:Send>>();
+    assert_send::<&'static Dummy+Send>();
+    assert_send::<Box<Dummy+Send>>();
 
     // but closure and object types can have lifetime bounds which make
     // them not ok (FIXME #5121)
     // assert_send::<proc:'a()>(); // ERROR does not fulfill `Send`
-    // assert_send::<Box<Dummy:'a>>(); // ERROR does not fulfill `Send`
+    // assert_send::<Box<Dummy+'a>>(); // ERROR does not fulfill `Send`
 
     // unsafe ptrs are ok unless they point at unsendable things
     assert_send::<*int>();
diff --git a/src/test/compile-fail/regions-name-static.rs b/src/test/compile-fail/regions-name-static.rs
index c1170654dd2..9f50ad36660 100644
--- a/src/test/compile-fail/regions-name-static.rs
+++ b/src/test/compile-fail/regions-name-static.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-struct Foo<'static> { //~ ERROR illegal lifetime parameter name: `static`
+struct Foo<'static> { //~ ERROR illegal lifetime parameter name: `'static`
     x: &'static int
 }
 
diff --git a/src/test/compile-fail/trait-bounds-cant-coerce.rs b/src/test/compile-fail/trait-bounds-cant-coerce.rs
index 12205ef062d..3737025da6c 100644
--- a/src/test/compile-fail/trait-bounds-cant-coerce.rs
+++ b/src/test/compile-fail/trait-bounds-cant-coerce.rs
@@ -12,14 +12,14 @@
 trait Foo {
 }
 
-fn a(_x: Box<Foo:Send>) {
+fn a(_x: Box<Foo+Send>) {
 }
 
-fn c(x: Box<Foo:Share+Send>) {
+fn c(x: Box<Foo+Share+Send>) {
     a(x);
 }
 
-fn d(x: Box<Foo:>) {
+fn d(x: Box<Foo+>) {
     a(x); //~ ERROR found no bounds
 }
 
diff --git a/src/test/compile-fail/trait-bounds-sugar.rs b/src/test/compile-fail/trait-bounds-sugar.rs
index 9447030a7f4..d548098ebe1 100644
--- a/src/test/compile-fail/trait-bounds-sugar.rs
+++ b/src/test/compile-fail/trait-bounds-sugar.rs
@@ -13,17 +13,17 @@
 
 trait Foo {}
 
-fn a(_x: Box<Foo:Send>) {
+fn a(_x: Box<Foo+Send>) {
 }
 
-fn b(_x: &'static Foo) { // should be same as &'static Foo:'static
+fn b(_x: &'static Foo) { // should be same as &'static Foo+'static
 }
 
-fn c(x: Box<Foo:Share>) {
+fn c(x: Box<Foo+Share>) {
     a(x); //~ ERROR expected bounds `Send`
 }
 
-fn d(x: &'static Foo:Share) {
+fn d(x: &'static Foo+Share) {
     b(x); //~ ERROR expected bounds `'static`
 }
 
diff --git a/src/test/compile-fail/transmute-different-sizes.rs b/src/test/compile-fail/transmute-different-sizes.rs
new file mode 100644
index 00000000000..abdfe983e3a
--- /dev/null
+++ b/src/test/compile-fail/transmute-different-sizes.rs
@@ -0,0 +1,29 @@
+// Copyright 2012 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.
+
+// Tests that `transmute` cannot be called on types of different size.
+
+#![allow(warnings)]
+
+use std::mem::transmute;
+
+unsafe fn f() {
+    let _: i8 = transmute(16i16);
+    //~^ ERROR transmute called on types with different sizes
+}
+
+unsafe fn g<T>(x: &T) {
+    let _: i8 = transmute(x);
+    //~^ ERROR transmute called on types with different sizes
+}
+
+fn main() {}
+
+
diff --git a/src/test/compile-fail/transmute-type-parameters.rs b/src/test/compile-fail/transmute-type-parameters.rs
new file mode 100644
index 00000000000..53391a0e894
--- /dev/null
+++ b/src/test/compile-fail/transmute-type-parameters.rs
@@ -0,0 +1,48 @@
+// Copyright 2012 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.
+
+// Tests that `transmute` cannot be called on type parameters.
+
+use std::mem::transmute;
+
+unsafe fn f<T>(x: T) {
+    let _: int = transmute(x);  //~ ERROR cannot transmute
+}
+
+unsafe fn g<T>(x: (T, int)) {
+    let _: int = transmute(x);  //~ ERROR cannot transmute
+}
+
+unsafe fn h<T>(x: [T, ..10]) {
+    let _: int = transmute(x);  //~ ERROR cannot transmute
+}
+
+struct Bad<T> {
+    f: T,
+}
+
+unsafe fn i<T>(x: Bad<T>) {
+    let _: int = transmute(x);  //~ ERROR cannot transmute
+}
+
+enum Worse<T> {
+    A(T),
+    B,
+}
+
+unsafe fn j<T>(x: Worse<T>) {
+    let _: int = transmute(x);  //~ ERROR cannot transmute
+}
+
+unsafe fn k<T>(x: Option<T>) {
+    let _: int = transmute(x);  //~ ERROR cannot transmute
+}
+
+fn main() {}
diff --git a/src/test/pretty/path-type-bounds.rs b/src/test/pretty/path-type-bounds.rs
index 0fdbad67f16..f90937c34a6 100644
--- a/src/test/pretty/path-type-bounds.rs
+++ b/src/test/pretty/path-type-bounds.rs
@@ -14,11 +14,11 @@
 trait Tr { }
 impl Tr for int { }
 
-fn foo(x: Box<Tr: Share>) -> Box<Tr: Share> { x }
+fn foo(x: Box<Tr+ Share>) -> Box<Tr+ Share> { x }
 
 fn main() {
-    let x: Box<Tr: Share>;
+    let x: Box<Tr+ Share>;
 
-    box() 1 as Box<Tr: Share>;
+    box() 1 as Box<Tr+ Share>;
 }
 
diff --git a/src/test/run-fail/fail-macro-any.rs b/src/test/run-fail/fail-macro-any.rs
index 09b50743308..c56eabbb3b4 100644
--- a/src/test/run-fail/fail-macro-any.rs
+++ b/src/test/run-fail/fail-macro-any.rs
@@ -12,5 +12,5 @@
 
 
 fn main() {
-    fail!(box 413 as Box<::std::any::Any:Send>);
+    fail!(box 413 as Box<::std::any::Any+Send>);
 }
diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs
index 7c25246807d..4b2e29135ad 100644
--- a/src/test/run-pass-fulldeps/quote-tokens.rs
+++ b/src/test/run-pass-fulldeps/quote-tokens.rs
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test
+// ignore-android
+// ignore-pretty: does not work well with `--test`
 
 #![feature(quote)]
 #![feature(managed_boxes)]
@@ -18,11 +19,11 @@ extern crate syntax;
 use syntax::ext::base::ExtCtxt;
 
 fn syntax_extension(cx: &ExtCtxt) {
-    let e_toks : Vec<syntax::ast::token_tree> = quote_tokens!(cx, 1 + 2);
-    let p_toks : Vec<syntax::ast::token_tree> = quote_tokens!(cx, (x, 1 .. 4, *));
+    let e_toks : Vec<syntax::ast::TokenTree> = quote_tokens!(cx, 1 + 2);
+    let p_toks : Vec<syntax::ast::TokenTree> = quote_tokens!(cx, (x, 1 .. 4, *));
 
     let a: @syntax::ast::Expr = quote_expr!(cx, 1 + 2);
-    let _b: Option<@syntax::ast::item> = quote_item!(cx, static foo : int = $e_toks; );
+    let _b: Option<@syntax::ast::Item> = quote_item!(cx, static foo : int = $e_toks; );
     let _c: @syntax::ast::Pat = quote_pat!(cx, (x, 1 .. 4, *) );
     let _d: @syntax::ast::Stmt = quote_stmt!(cx, let x = $a; );
     let _e: @syntax::ast::Expr = quote_expr!(cx, match foo { $p_toks => 10 } );
@@ -30,6 +31,9 @@ fn syntax_extension(cx: &ExtCtxt) {
     let _f: @syntax::ast::Expr = quote_expr!(cx, ());
     let _g: @syntax::ast::Expr = quote_expr!(cx, true);
     let _h: @syntax::ast::Expr = quote_expr!(cx, 'a');
+
+    let i: Option<@syntax::ast::Item> = quote_item!(cx, #[deriving(Eq)] struct Foo; );
+    assert!(i.is_some());
 }
 
 fn main() {
diff --git a/src/test/run-pass/alignment-gep-tup-like-1.rs b/src/test/run-pass/alignment-gep-tup-like-1.rs
index 38a3d3c5fff..4fa695de522 100644
--- a/src/test/run-pass/alignment-gep-tup-like-1.rs
+++ b/src/test/run-pass/alignment-gep-tup-like-1.rs
@@ -33,7 +33,7 @@ fn f<A:Clone + 'static>(a: A, b: u16) -> Box<Invokable<A>:> {
     box Invoker {
         a: a,
         b: b,
-    } as Box<Invokable<A>>:
+    } as (Box<Invokable<A>>+)
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/as-precedence.rs b/src/test/run-pass/as-precedence.rs
new file mode 100644
index 00000000000..0760f13200c
--- /dev/null
+++ b/src/test/run-pass/as-precedence.rs
@@ -0,0 +1,18 @@
+// Copyright 2012 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() {
+    assert_eq!(3 as uint * 3, 9);
+    assert_eq!(3 as (uint) * 3, 9);
+    assert_eq!(3 as (uint) / 3, 1);
+    assert_eq!(3 as uint + 3, 6);
+    assert_eq!(3 as (uint) + 3, 6);
+}
+
diff --git a/src/test/run-pass/capturing-logging.rs b/src/test/run-pass/capturing-logging.rs
index 3402db7c355..23607e16795 100644
--- a/src/test/run-pass/capturing-logging.rs
+++ b/src/test/run-pass/capturing-logging.rs
@@ -41,7 +41,7 @@ fn main() {
     let (tx, rx) = channel();
     let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
     spawn(proc() {
-        set_logger(box MyWriter(w) as Box<Logger:Send>);
+        set_logger(box MyWriter(w) as Box<Logger+Send>);
         debug!("debug");
         info!("info");
     });
diff --git a/src/test/run-pass/close-over-big-then-small-data.rs b/src/test/run-pass/close-over-big-then-small-data.rs
index acae6135937..3d642be082c 100644
--- a/src/test/run-pass/close-over-big-then-small-data.rs
+++ b/src/test/run-pass/close-over-big-then-small-data.rs
@@ -33,11 +33,11 @@ impl<A:Clone> Invokable<A> for Invoker<A> {
     }
 }
 
-fn f<A:Clone + 'static>(a: A, b: u16) -> Box<Invokable<A>:> {
+fn f<A:Clone + 'static>(a: A, b: u16) -> Box<Invokable<A>+> {
     box Invoker {
         a: a,
         b: b,
-    } as Box<Invokable<A>>:
+    } as (Box<Invokable<A>>+)
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/issue-14837.rs b/src/test/run-pass/issue-14837.rs
new file mode 100644
index 00000000000..7876fe86d47
--- /dev/null
+++ b/src/test/run-pass/issue-14837.rs
@@ -0,0 +1,20 @@
+// 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.
+
+#![feature(struct_variant)]
+
+#[deny(dead_code)]
+pub enum Foo {
+    Bar {
+        pub baz: int
+    }
+}
+
+fn main() { }
diff --git a/src/test/run-pass/loop-label-shadowing.rs b/src/test/run-pass/loop-label-shadowing.rs
new file mode 100644
index 00000000000..cfe51fe7758
--- /dev/null
+++ b/src/test/run-pass/loop-label-shadowing.rs
@@ -0,0 +1,19 @@
+// Copyright 2012 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.
+
+// Issue #12512.
+
+fn main() {
+    let mut foo = Vec::new();
+    'foo: for i in [1, 2, 3].iter() {
+        foo.push(i);
+    }
+}
+
diff --git a/src/test/run-pass/trait-bounds-basic.rs b/src/test/run-pass/trait-bounds-basic.rs
index 68ebf2c6382..d1bb0db511b 100644
--- a/src/test/run-pass/trait-bounds-basic.rs
+++ b/src/test/run-pass/trait-bounds-basic.rs
@@ -12,21 +12,21 @@
 trait Foo {
 }
 
-fn a(_x: Box<Foo:>) {
+fn a(_x: Box<Foo+>) {
 }
 
-fn b(_x: Box<Foo:Send>) {
+fn b(_x: Box<Foo+Send>) {
 }
 
-fn c(x: Box<Foo:Share+Send>) {
+fn c(x: Box<Foo+Share+Send>) {
     a(x);
 }
 
-fn d(x: Box<Foo:Send>) {
+fn d(x: Box<Foo+Send>) {
     b(x);
 }
 
-fn e(x: Box<Foo>) { // sugar for Box<Foo:Owned>
+fn e(x: Box<Foo>) { // sugar for Box<Foo+Owned>
     a(x);
 }
 
diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs
index 4ca67811982..18a0e5d471c 100644
--- a/src/test/run-pass/trait-bounds-in-arc.rs
+++ b/src/test/run-pass/trait-bounds-in-arc.rs
@@ -71,10 +71,10 @@ pub fn main() {
         swim_speed: 998,
         name: "alec_guinness".to_string(),
     };
-    let arc = Arc::new(vec!(box catte  as Box<Pet:Share+Send>,
-                            box dogge1 as Box<Pet:Share+Send>,
-                            box fishe  as Box<Pet:Share+Send>,
-                            box dogge2 as Box<Pet:Share+Send>));
+    let arc = Arc::new(vec!(box catte  as Box<Pet+Share+Send>,
+                            box dogge1 as Box<Pet+Share+Send>,
+                            box fishe  as Box<Pet+Share+Send>,
+                            box dogge2 as Box<Pet+Share+Send>));
     let (tx1, rx1) = channel();
     let arc1 = arc.clone();
     task::spawn(proc() { check_legs(arc1); tx1.send(()); });
@@ -89,21 +89,21 @@ pub fn main() {
     rx3.recv();
 }
 
-fn check_legs(arc: Arc<Vec<Box<Pet:Share+Send>>>) {
+fn check_legs(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
     let mut legs = 0;
     for pet in arc.iter() {
         legs += pet.num_legs();
     }
     assert!(legs == 12);
 }
-fn check_names(arc: Arc<Vec<Box<Pet:Share+Send>>>) {
+fn check_names(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
     for pet in arc.iter() {
         pet.name(|name| {
             assert!(name[0] == 'a' as u8 && name[1] == 'l' as u8);
         })
     }
 }
-fn check_pedigree(arc: Arc<Vec<Box<Pet:Share+Send>>>) {
+fn check_pedigree(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
     for pet in arc.iter() {
         assert!(pet.of_good_pedigree());
     }
diff --git a/src/test/run-pass/trait-cast.rs b/src/test/run-pass/trait-cast.rs
index a9067ef87ba..0f99998b7a6 100644
--- a/src/test/run-pass/trait-cast.rs
+++ b/src/test/run-pass/trait-cast.rs
@@ -20,7 +20,7 @@ struct Tree(@RefCell<TreeR>);
 struct TreeR {
     left: Option<Tree>,
     right: Option<Tree>,
-    val: Box<to_str:Send>
+    val: Box<to_str+Send>
 }
 
 trait to_str {
@@ -57,10 +57,10 @@ fn foo<T:to_str>(x: T) -> String { x.to_str_() }
 pub fn main() {
     let t1 = Tree(@RefCell::new(TreeR{left: None,
                                       right: None,
-                                      val: box 1 as Box<to_str:Send>}));
+                                      val: box 1 as Box<to_str+Send>}));
     let t2 = Tree(@RefCell::new(TreeR{left: Some(t1),
                                       right: Some(t1),
-                                      val: box 2 as Box<to_str:Send>}));
+                                      val: box 2 as Box<to_str+Send>}));
     let expected =
         "[2, some([1, none, none]), some([1, none, none])]".to_string();
     assert!(t2.to_str_() == expected);
diff --git a/src/test/run-pass/trait-contravariant-self.rs b/src/test/run-pass/trait-contravariant-self.rs
index 1576c646286..d8df5d5600c 100644
--- a/src/test/run-pass/trait-contravariant-self.rs
+++ b/src/test/run-pass/trait-contravariant-self.rs
@@ -10,8 +10,8 @@
 
 // This is an interesting test case. We have a trait (Bar) that is
 // implemented for a `Box<Foo>` object (note: no bounds). And then we
-// have a `Box<Foo:Send>` object. The impl for `Box<Foo>` is applicable
-// to `Box<Foo:Send>` because:
+// have a `Box<Foo+Send>` object. The impl for `Box<Foo>` is applicable
+// to `Box<Foo+Send>` because:
 //
 // 1. The trait Bar is contravariant w/r/t Self because `Self` appears
 //    only in argument position.
@@ -30,7 +30,7 @@ impl Bar for Box<Foo> { fn dummy(&self) { } }
 fn wants_bar<B:Bar>(b: &B) { }
 
 fn main() {
-    let x: Box<Foo:Send> = (box SFoo);
+    let x: Box<Foo+Send> = (box SFoo);
     wants_bar(&x);
 }