diff --git a/src/Cargo.lock b/src/Cargo.lock
index 2a7dbce2ddc91..de2e5319b1d0c 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -2048,6 +2048,7 @@ version = "0.0.0"
 dependencies = [
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
+ "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_target 0.0.0",
  "syntax 0.0.0",
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 6b66fd8a2b2ff..9ae5ab7f8be2e 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -51,6 +51,8 @@ use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
                     ELIDED_LIFETIMES_IN_PATHS};
 use middle::cstore::CrateStore;
 use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::small_vec::OneVector;
+use rustc_data_structures::thin_vec::ThinVec;
 use session::Session;
 use util::common::FN_OUTPUT_NAME;
 use util::nodemap::{DefIdMap, NodeMap};
@@ -71,7 +73,6 @@ use syntax::std_inject;
 use syntax::symbol::{keywords, Symbol};
 use syntax::tokenstream::{Delimited, TokenStream, TokenTree};
 use syntax::parse::token::Token;
-use syntax::util::small_vector::SmallVector;
 use syntax::visit::{self, Visitor};
 use syntax_pos::{Span, MultiSpan};
 
@@ -3136,12 +3137,12 @@ impl<'a> LoweringContext<'a> {
         &mut self,
         decl: &FnDecl,
         header: &FnHeader,
-        ids: &mut SmallVector<hir::ItemId>,
+        ids: &mut OneVector<hir::ItemId>,
     ) {
         if let Some(id) = header.asyncness.opt_return_id() {
             ids.push(hir::ItemId { id });
         }
-        struct IdVisitor<'a> { ids: &'a mut SmallVector<hir::ItemId> }
+        struct IdVisitor<'a> { ids: &'a mut OneVector<hir::ItemId> }
         impl<'a, 'b> Visitor<'a> for IdVisitor<'b> {
             fn visit_ty(&mut self, ty: &'a Ty) {
                 match ty.node {
@@ -3174,21 +3175,21 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
-    fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
+    fn lower_item_id(&mut self, i: &Item) -> OneVector<hir::ItemId> {
         match i.node {
             ItemKind::Use(ref use_tree) => {
-                let mut vec = SmallVector::one(hir::ItemId { id: i.id });
+                let mut vec = OneVector::one(hir::ItemId { id: i.id });
                 self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
                 vec
             }
-            ItemKind::MacroDef(..) => SmallVector::new(),
+            ItemKind::MacroDef(..) => OneVector::new(),
             ItemKind::Fn(ref decl, ref header, ..) => {
-                let mut ids = SmallVector::one(hir::ItemId { id: i.id });
+                let mut ids = OneVector::one(hir::ItemId { id: i.id });
                 self.lower_impl_trait_ids(decl, header, &mut ids);
                 ids
             },
             ItemKind::Impl(.., None, _, ref items) => {
-                let mut ids = SmallVector::one(hir::ItemId { id: i.id });
+                let mut ids = OneVector::one(hir::ItemId { id: i.id });
                 for item in items {
                     if let ImplItemKind::Method(ref sig, _) = item.node {
                         self.lower_impl_trait_ids(&sig.decl, &sig.header, &mut ids);
@@ -3196,14 +3197,14 @@ impl<'a> LoweringContext<'a> {
                 }
                 ids
             },
-            _ => SmallVector::one(hir::ItemId { id: i.id }),
+            _ => OneVector::one(hir::ItemId { id: i.id }),
         }
     }
 
     fn lower_item_id_use_tree(&mut self,
                               tree: &UseTree,
                               base_id: NodeId,
-                              vec: &mut SmallVector<hir::ItemId>)
+                              vec: &mut OneVector<hir::ItemId>)
     {
         match tree.kind {
             UseTreeKind::Nested(ref nested_vec) => for &(ref nested, id) in nested_vec {
@@ -4295,8 +4296,8 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
-    fn lower_stmt(&mut self, s: &Stmt) -> SmallVector<hir::Stmt> {
-        SmallVector::one(match s.node {
+    fn lower_stmt(&mut self, s: &Stmt) -> OneVector<hir::Stmt> {
+        OneVector::one(match s.node {
             StmtKind::Local(ref l) => Spanned {
                 node: hir::StmtKind::Decl(
                     P(Spanned {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 0003790e6d552..899d91990e2b2 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -33,13 +33,13 @@ use syntax::ext::hygiene::SyntaxContext;
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, keywords};
 use syntax::tokenstream::TokenStream;
-use syntax::util::ThinVec;
 use syntax::util::parser::ExprPrecedence;
 use ty::AdtKind;
 use ty::query::Providers;
 
 use rustc_data_structures::indexed_vec;
 use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope};
+use rustc_data_structures::thin_vec::ThinVec;
 
 use serialize::{self, Encoder, Encodable, Decoder, Decodable};
 use std::collections::BTreeMap;
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index b55843ac527df..5991845d265b2 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -127,14 +127,14 @@ impl<'tcx> Place<'tcx> {
     /// of a closure type.
     pub fn is_upvar_field_projection<'cx, 'gcx>(&self, mir: &'cx Mir<'tcx>,
                                                 tcx: &TyCtxt<'cx, 'gcx, 'tcx>) -> Option<Field> {
-        let place = if let Place::Projection(ref proj) = self {
+        let (place, by_ref) = if let Place::Projection(ref proj) = self {
             if let ProjectionElem::Deref = proj.elem {
-                &proj.base
+                (&proj.base, true)
             } else {
-                self
+                (self, false)
             }
         } else {
-            self
+            (self, false)
         };
 
         match place {
@@ -142,14 +142,16 @@ impl<'tcx> Place<'tcx> {
                 ProjectionElem::Field(field, _ty) => {
                     let base_ty = proj.base.ty(mir, *tcx).to_ty(*tcx);
 
-                    if  base_ty.is_closure() || base_ty.is_generator() {
+                    if (base_ty.is_closure() || base_ty.is_generator()) &&
+                        (!by_ref || mir.upvar_decls[field.index()].by_ref)
+                    {
                         Some(field)
                     } else {
                         None
                     }
                 },
                 _ => None,
-            },
+            }
             _ => None,
         }
     }
diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs
index cfe3583a9806f..1ffe8157a0fb4 100644
--- a/src/librustc/traits/auto_trait.rs
+++ b/src/librustc/traits/auto_trait.rs
@@ -681,10 +681,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                     }
                 }
                 &ty::Predicate::RegionOutlives(ref binder) => {
-                    if let Err(_) = select
-                        .infcx()
-                        .region_outlives_predicate(&dummy_cause, binder)
-                    {
+                    if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
                         return false;
                     }
                 }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index c04785aac2095..a02b63755dc12 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -143,7 +143,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 // Eventually I'll need to implement param-env-aware
                 // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
                 let param_env = ty::ParamEnv::empty();
-                if let Ok(_) = self.can_sub(param_env, error, implication) {
+                if self.can_sub(param_env, error, implication).is_ok() {
                     debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
                     return true
                 }
diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs
index f79ce73ad928a..0127ae423da54 100644
--- a/src/librustc/traits/query/outlives_bounds.rs
+++ b/src/librustc/traits/query/outlives_bounds.rs
@@ -137,7 +137,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
         // variables. Process these constraints.
         let mut fulfill_cx = FulfillmentContext::new();
         fulfill_cx.register_predicate_obligations(self, result.obligations);
-        if let Err(_) = fulfill_cx.select_all_or_error(self) {
+        if fulfill_cx.select_all_or_error(self).is_err() {
             self.tcx.sess.delay_span_bug(
                 span,
                 "implied_outlives_bounds failed to solve obligations from instantiation"
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 35184ca6a2559..1e3fe70535bcc 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1587,8 +1587,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                         -> bool
     {
         assert!(!skol_trait_ref.has_escaping_regions());
-        if let Err(_) = self.infcx.at(&obligation.cause, obligation.param_env)
-                                  .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) {
+        if self.infcx.at(&obligation.cause, obligation.param_env)
+                     .sup(ty::Binder::dummy(skol_trait_ref), trait_bound).is_err() {
             return false;
         }
 
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 66edbeff749f7..7329f4832f2e2 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -294,7 +294,7 @@ fn resolve_associated_item<'a, 'tcx>(
             })
         }
         traits::VtableBuiltin(..) => {
-            if let Some(_) = tcx.lang_items().clone_trait() {
+            if tcx.lang_items().clone_trait().is_some() {
                 Some(Instance {
                     def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
                     substs: rcvr_substs
diff --git a/src/librustc_allocator/Cargo.toml b/src/librustc_allocator/Cargo.toml
index 1cbde181cafae..83a918f2af837 100644
--- a/src/librustc_allocator/Cargo.toml
+++ b/src/librustc_allocator/Cargo.toml
@@ -10,6 +10,7 @@ test = false
 
 [dependencies]
 rustc = { path = "../librustc" }
+rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs
index 05843852ee0de..676dbeeeeb00b 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/librustc_allocator/expand.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use rustc::middle::allocator::AllocatorKind;
+use rustc_data_structures::small_vec::OneVector;
 use rustc_errors;
 use syntax::{
     ast::{
@@ -28,8 +29,7 @@ use syntax::{
     fold::{self, Folder},
     parse::ParseSess,
     ptr::P,
-    symbol::Symbol,
-    util::small_vector::SmallVector,
+    symbol::Symbol
 };
 use syntax_pos::Span;
 
@@ -65,7 +65,7 @@ struct ExpandAllocatorDirectives<'a> {
 }
 
 impl<'a> Folder for ExpandAllocatorDirectives<'a> {
-    fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
+    fn fold_item(&mut self, item: P<Item>) -> OneVector<P<Item>> {
         debug!("in submodule {}", self.in_submod);
 
         let name = if attr::contains_name(&item.attrs, "global_allocator") {
@@ -78,20 +78,20 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
             _ => {
                 self.handler
                     .span_err(item.span, "allocators must be statics");
-                return SmallVector::one(item);
+                return OneVector::one(item);
             }
         }
 
         if self.in_submod > 0 {
             self.handler
                 .span_err(item.span, "`global_allocator` cannot be used in submodules");
-            return SmallVector::one(item);
+            return OneVector::one(item);
         }
 
         if self.found {
             self.handler
                 .span_err(item.span, "cannot define more than one #[global_allocator]");
-            return SmallVector::one(item);
+            return OneVector::one(item);
         }
         self.found = true;
 
@@ -152,7 +152,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
         let module = f.cx.monotonic_expander().fold_item(module).pop().unwrap();
 
         // Return the item and new submodule
-        let mut ret = SmallVector::with_capacity(2);
+        let mut ret = OneVector::with_capacity(2);
         ret.push(item);
         ret.push(module);
 
diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs
index b217d3665a245..c7dc336b1ca51 100644
--- a/src/librustc_allocator/lib.rs
+++ b/src/librustc_allocator/lib.rs
@@ -12,6 +12,7 @@
 
 #[macro_use] extern crate log;
 extern crate rustc;
+extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate rustc_target;
 extern crate syntax;
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index 21bf490beb0fb..6b3faa3a41df6 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -351,7 +351,7 @@ pub fn codegen_static<'a, 'tcx>(
         if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
             llvm::set_thread_local_mode(g, cx.tls_model);
 
-            // Do not allow LLVM to change the alignment of a TLS on macOS.
+            // Do not allow LLVM to change the alignment of a TLS on macOS and Fuchsia.
             //
             // By default a global's alignment can be freely increased.
             // This allows LLVM to generate more performant instructions
@@ -361,6 +361,10 @@ pub fn codegen_static<'a, 'tcx>(
             // respect any alignment given on the TLS (radar 24221680).
             // This will violate the alignment assumption, and causing segfault at runtime.
             //
+            // Fuchsia's libc currently does not support greater than 16-byte alignment
+            // of TLS segments, so this hack is also enabled temporarily for Fuchsia targets
+            // until libc is fixed.
+            //
             // This bug is very easy to trigger. In `println!` and `panic!`,
             // the `LOCAL_STDOUT`/`LOCAL_STDERR` handles are stored in a TLS,
             // which the values would be `mem::replace`d on initialization.
@@ -380,7 +384,9 @@ pub fn codegen_static<'a, 'tcx>(
             // will use load-unaligned instructions instead, and thus avoiding the crash.
             //
             // We could remove this hack whenever we decide to drop macOS 10.10 support.
-            if cx.tcx.sess.target.target.options.is_like_osx {
+            if cx.tcx.sess.target.target.options.is_like_osx ||
+                (cx.tcx.sess.target.target.target_os == "fuchsia")
+            {
                 let sect_name = if alloc.bytes.iter().all(|b| *b == 0) {
                     CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0")
                 } else {
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 441fff5f08c8f..ff26e0f35f00f 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -169,6 +169,10 @@ const MIPS_WHITELIST: &[(&str, Option<&str>)] = &[
     ("msa", Some("mips_target_feature")),
 ];
 
+const WASM_WHITELIST: &[(&str, Option<&str>)] = &[
+    ("simd128", Some("wasm_target_feature")),
+];
+
 /// When rustdoc is running, provide a list of all known features so that all their respective
 /// primtives may be documented.
 ///
@@ -181,6 +185,7 @@ pub fn all_known_features() -> impl Iterator<Item=(&'static str, Option<&'static
         .chain(HEXAGON_WHITELIST.iter().cloned())
         .chain(POWERPC_WHITELIST.iter().cloned())
         .chain(MIPS_WHITELIST.iter().cloned())
+        .chain(WASM_WHITELIST.iter().cloned())
 }
 
 pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
@@ -228,6 +233,7 @@ pub fn target_feature_whitelist(sess: &Session)
         "hexagon" => HEXAGON_WHITELIST,
         "mips" | "mips64" => MIPS_WHITELIST,
         "powerpc" | "powerpc64" => POWERPC_WHITELIST,
+        "wasm32" => WASM_WHITELIST,
         _ => &[],
     }
 }
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index dd90cf7ae19e4..8c8cc8ce7a19a 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -74,6 +74,7 @@ pub mod sorted_map;
 pub mod stable_hasher;
 pub mod sync;
 pub mod tiny_list;
+pub mod thin_vec;
 pub mod transitive_relation;
 pub mod tuple_slice;
 pub use ena::unify;
diff --git a/src/librustc_data_structures/small_vec.rs b/src/librustc_data_structures/small_vec.rs
index 76b01beb4bad3..c12039cfdd009 100644
--- a/src/librustc_data_structures/small_vec.rs
+++ b/src/librustc_data_structures/small_vec.rs
@@ -29,6 +29,8 @@ use array_vec::Array;
 
 pub struct SmallVec<A: Array>(AccumulateVec<A>);
 
+pub type OneVector<T> = SmallVec<[T; 1]>;
+
 impl<A> Clone for SmallVec<A>
     where A: Array,
           A::Element: Clone {
@@ -222,6 +224,69 @@ mod tests {
 
     use super::*;
 
+    #[test]
+    fn test_len() {
+        let v: OneVector<isize> = OneVector::new();
+        assert_eq!(0, v.len());
+
+        assert_eq!(1, OneVector::one(1).len());
+        assert_eq!(5, OneVector::many(vec![1, 2, 3, 4, 5]).len());
+    }
+
+    #[test]
+    fn test_push_get() {
+        let mut v = OneVector::new();
+        v.push(1);
+        assert_eq!(1, v.len());
+        assert_eq!(1, v[0]);
+        v.push(2);
+        assert_eq!(2, v.len());
+        assert_eq!(2, v[1]);
+        v.push(3);
+        assert_eq!(3, v.len());
+        assert_eq!(3, v[2]);
+    }
+
+    #[test]
+    fn test_from_iter() {
+        let v: OneVector<isize> = (vec![1, 2, 3]).into_iter().collect();
+        assert_eq!(3, v.len());
+        assert_eq!(1, v[0]);
+        assert_eq!(2, v[1]);
+        assert_eq!(3, v[2]);
+    }
+
+    #[test]
+    fn test_move_iter() {
+        let v = OneVector::new();
+        let v: Vec<isize> = v.into_iter().collect();
+        assert_eq!(v, Vec::new());
+
+        let v = OneVector::one(1);
+        assert_eq!(v.into_iter().collect::<Vec<_>>(), [1]);
+
+        let v = OneVector::many(vec![1, 2, 3]);
+        assert_eq!(v.into_iter().collect::<Vec<_>>(), [1, 2, 3]);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_expect_one_zero() {
+        let _: isize = OneVector::new().expect_one("");
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_expect_one_many() {
+        OneVector::many(vec![1, 2]).expect_one("");
+    }
+
+    #[test]
+    fn test_expect_one_one() {
+        assert_eq!(1, OneVector::one(1).expect_one(""));
+        assert_eq!(1, OneVector::many(vec![1]).expect_one(""));
+    }
+
     #[bench]
     fn fill_small_vec_1_10_with_cap(b: &mut Bencher) {
         b.iter(|| {
diff --git a/src/libsyntax/util/thin_vec.rs b/src/librustc_data_structures/thin_vec.rs
similarity index 100%
rename from src/libsyntax/util/thin_vec.rs
rename to src/librustc_data_structures/thin_vec.rs
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 3e74aef9e7345..a66392833f695 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -24,6 +24,8 @@ use rustc::session::Session;
 use rustc::session::config::{Input, OutputFilenames};
 use rustc_borrowck as borrowck;
 use rustc_borrowck::graphviz as borrowck_dot;
+use rustc_data_structures::small_vec::OneVector;
+use rustc_data_structures::thin_vec::ThinVec;
 use rustc_metadata::cstore::CStore;
 
 use rustc_mir::util::{write_mir_pretty, write_mir_graphviz};
@@ -33,8 +35,6 @@ use syntax::fold::{self, Folder};
 use syntax::print::{pprust};
 use syntax::print::pprust::PrintState;
 use syntax::ptr::P;
-use syntax::util::ThinVec;
-use syntax::util::small_vector::SmallVector;
 use syntax_pos::{self, FileName};
 
 use graphviz as dot;
@@ -727,7 +727,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
         self.run(is_const, |s| fold::noop_fold_item_kind(i, s))
     }
 
-    fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector<ast::TraitItem> {
+    fn fold_trait_item(&mut self, i: ast::TraitItem) -> OneVector<ast::TraitItem> {
         let is_const = match i.node {
             ast::TraitItemKind::Const(..) => true,
             ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
@@ -737,7 +737,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
         self.run(is_const, |s| fold::noop_fold_trait_item(i, s))
     }
 
-    fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector<ast::ImplItem> {
+    fn fold_impl_item(&mut self, i: ast::ImplItem) -> OneVector<ast::ImplItem> {
         let is_const = match i.node {
             ast::ImplItemKind::Const(..) => true,
             ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
@@ -785,7 +785,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
             node: ast::ExprKind::Loop(P(empty_block), None),
             id: self.sess.next_node_id(),
             span: syntax_pos::DUMMY_SP,
-            attrs: ast::ThinVec::new(),
+                attrs: ThinVec::new(),
         });
 
         let loop_stmt = ast::Stmt {
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 09295e2c7ff00..6b1298750fba0 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -1295,7 +1295,7 @@ impl EmitterWriter {
                 }
 
                 // if we elided some lines, add an ellipsis
-                if let Some(_) = lines.next() {
+                if lines.next().is_some() {
                     buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber);
                 } else if !show_underline {
                     draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1);
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 4dc66fb812144..f1636c4dcb08a 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -790,21 +790,18 @@ impl LintPass for ImproperCTypes {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
-    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+    fn check_foreign_item(&mut self, cx: &LateContext, it: &hir::ForeignItem) {
         let mut vis = ImproperCTypesVisitor { cx: cx };
-        if let hir::ItemKind::ForeignMod(ref nmod) = it.node {
-            if nmod.abi != Abi::RustIntrinsic && nmod.abi != Abi::PlatformIntrinsic {
-                for ni in &nmod.items {
-                    match ni.node {
-                        hir::ForeignItemKind::Fn(ref decl, _, _) => {
-                            vis.check_foreign_fn(ni.id, decl);
-                        }
-                        hir::ForeignItemKind::Static(ref ty, _) => {
-                            vis.check_foreign_static(ni.id, ty.span);
-                        }
-                        hir::ForeignItemKind::Type => ()
-                    }
+        let abi = cx.tcx.hir.get_foreign_abi(it.id);
+        if abi != Abi::RustIntrinsic && abi != Abi::PlatformIntrinsic {
+            match it.node {
+                hir::ForeignItemKind::Fn(ref decl, _, _) => {
+                    vis.check_foreign_fn(it.id, decl);
+                }
+                hir::ForeignItemKind::Static(ref ty, _) => {
+                    vis.check_foreign_static(it.id, ty.span);
                 }
+                hir::ForeignItemKind::Type => ()
             }
         }
     }
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index aabed6686858f..2ae06375af13c 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -138,7 +138,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         let tables = self.tcx.typeck_tables_of(id);
                         let node_id = self.tcx.hir.as_local_node_id(id).unwrap();
                         let hir_id = self.tcx.hir.node_to_hir_id(node_id);
-                        if let Some(_) = tables.closure_kind_origins().get(hir_id) {
+                        if tables.closure_kind_origins().get(hir_id).is_some() {
                             false
                         } else {
                             true
@@ -412,6 +412,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             .insert((root_place.clone(), borrow_span));
 
         let mut err = match &self.describe_place(&borrow.borrowed_place) {
+            Some(_) if self.is_place_thread_local(root_place) => {
+                self.report_thread_local_value_does_not_live_long_enough(
+                    drop_span,
+                    borrow_span,
+                )
+            }
             Some(name) => self.report_local_value_does_not_live_long_enough(
                 context,
                 name,
@@ -455,9 +461,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             context, name, scope_tree, borrow, drop_span, borrow_span
         );
 
-        let tcx = self.tcx;
-        let mut err =
-            tcx.path_does_not_live_long_enough(borrow_span, &format!("`{}`", name), Origin::Mir);
+        let mut err = self.tcx.path_does_not_live_long_enough(
+            borrow_span, &format!("`{}`", name), Origin::Mir);
+
         err.span_label(borrow_span, "borrowed value does not live long enough");
         err.span_label(
             drop_span,
@@ -468,6 +474,27 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         err
     }
 
+    fn report_thread_local_value_does_not_live_long_enough(
+        &mut self,
+        drop_span: Span,
+        borrow_span: Span,
+    ) -> DiagnosticBuilder<'cx> {
+        debug!(
+            "report_thread_local_value_does_not_live_long_enough(\
+             {:?}, {:?}\
+             )",
+            drop_span, borrow_span
+        );
+
+        let mut err = self.tcx.thread_local_value_does_not_live_long_enough(
+            borrow_span, Origin::Mir);
+
+        err.span_label(borrow_span,
+                       "thread-local variables cannot be borrowed beyond the end of the function");
+        err.span_label(drop_span, "end of enclosing function is here");
+        err
+    }
+
     fn report_temporary_value_does_not_live_long_enough(
         &mut self,
         context: Context,
@@ -735,7 +762,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                             &including_downcast,
                         )?;
                         buf.push_str("[");
-                        if let Err(_) = self.append_local_to_string(index, buf) {
+                        if self.append_local_to_string(index, buf).is_err() {
                             buf.push_str("..");
                         }
                         buf.push_str("]");
@@ -856,6 +883,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             },
         }
     }
+
+    /// Check if a place is a thread-local static.
+    pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
+        if let Place::Static(statik) = place {
+            let attrs = self.tcx.get_attrs(statik.def_id);
+            let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
+
+            debug!("is_place_thread_local: attrs={:?} is_thread_local={:?}",
+                   attrs, is_thread_local);
+            is_thread_local
+        } else {
+            debug!("is_place_thread_local: no");
+            false
+        }
+    }
 }
 
 // The span(s) associated to a use of a place.
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 320d3a4720321..f96b9b8082fa7 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -151,7 +151,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let location_table = &LocationTable::new(mir);
 
     let mut errors_buffer = Vec::new();
-    let (move_data, move_errors): (MoveData<'tcx>, Option<Vec<MoveError<'tcx>>>) =
+    let (move_data, move_errors): (MoveData<'tcx>, Option<Vec<(Place<'tcx>, MoveError<'tcx>)>>) =
         match MoveData::gather_moves(mir, tcx) {
             Ok(move_data) => (move_data, None),
             Err((move_data, move_errors)) => (move_data, Some(move_errors)),
@@ -1487,15 +1487,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         // FIXME: allow thread-locals to borrow other thread locals?
         let (might_be_alive, will_be_dropped) = match root_place {
             Place::Promoted(_) => (true, false),
-            Place::Static(statik) => {
+            Place::Static(_) => {
                 // Thread-locals might be dropped after the function exits, but
                 // "true" statics will never be.
-                let is_thread_local = self
-                    .tcx
-                    .get_attrs(statik.def_id)
-                    .iter()
-                    .any(|attr| attr.check_name("thread_local"));
-
+                let is_thread_local = self.is_place_thread_local(&root_place);
                 (true, is_thread_local)
             }
             Place::Local(_) => {
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index 4d988fef450b8..d3524e841b223 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -11,11 +11,12 @@
 use rustc::hir;
 use rustc::mir::*;
 use rustc::ty;
-use rustc_data_structures::indexed_vec::Idx;
 use rustc_errors::DiagnosticBuilder;
+use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
 
 use borrow_check::MirBorrowckCtxt;
+use borrow_check::prefixes::PrefixSet;
 use dataflow::move_paths::{IllegalMoveOrigin, IllegalMoveOriginKind};
 use dataflow::move_paths::{LookupResult, MoveError, MovePathIndex};
 use util::borrowck_errors::{BorrowckErrors, Origin};
@@ -38,6 +39,7 @@ enum GroupedMoveError<'tcx> {
     // Match place can't be moved from
     // e.g. match x[0] { s => (), } where x: &[String]
     MovesFromMatchPlace {
+        original_path: Place<'tcx>,
         span: Span,
         move_from: Place<'tcx>,
         kind: IllegalMoveOriginKind<'tcx>,
@@ -46,6 +48,7 @@ enum GroupedMoveError<'tcx> {
     // Part of a pattern can't be moved from,
     // e.g. match &String::new() { &x => (), }
     MovesFromPattern {
+        original_path: Place<'tcx>,
         span: Span,
         move_from: MovePathIndex,
         kind: IllegalMoveOriginKind<'tcx>,
@@ -53,23 +56,27 @@ enum GroupedMoveError<'tcx> {
     },
     // Everything that isn't from pattern matching.
     OtherIllegalMove {
+        original_path: Place<'tcx>,
         span: Span,
         kind: IllegalMoveOriginKind<'tcx>,
     },
 }
 
 impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
-    pub(crate) fn report_move_errors(&mut self, move_errors: Vec<MoveError<'tcx>>) {
+    pub(crate) fn report_move_errors(&mut self, move_errors: Vec<(Place<'tcx>, MoveError<'tcx>)>) {
         let grouped_errors = self.group_move_errors(move_errors);
         for error in grouped_errors {
             self.report(error);
         }
     }
 
-    fn group_move_errors(&self, errors: Vec<MoveError<'tcx>>) -> Vec<GroupedMoveError<'tcx>> {
+    fn group_move_errors(
+        &self,
+        errors: Vec<(Place<'tcx>, MoveError<'tcx>)>
+    ) -> Vec<GroupedMoveError<'tcx>> {
         let mut grouped_errors = Vec::new();
-        for error in errors {
-            self.append_to_grouped_errors(&mut grouped_errors, error);
+        for (original_path, error) in errors {
+            self.append_to_grouped_errors(&mut grouped_errors, original_path, error);
         }
         grouped_errors
     }
@@ -77,6 +84,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
     fn append_to_grouped_errors(
         &self,
         grouped_errors: &mut Vec<GroupedMoveError<'tcx>>,
+        original_path: Place<'tcx>,
         error: MoveError<'tcx>,
     ) {
         match error {
@@ -116,6 +124,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                         self.append_binding_error(
                             grouped_errors,
                             kind,
+                            original_path,
                             move_from,
                             *local,
                             opt_match_place,
@@ -127,6 +136,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 }
                 grouped_errors.push(GroupedMoveError::OtherIllegalMove {
                     span: stmt_source_info.span,
+                    original_path,
                     kind,
                 });
             }
@@ -137,6 +147,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
         &self,
         grouped_errors: &mut Vec<GroupedMoveError<'tcx>>,
         kind: IllegalMoveOriginKind<'tcx>,
+        original_path: Place<'tcx>,
         move_from: &Place<'tcx>,
         bind_to: Local,
         match_place: &Option<Place<'tcx>>,
@@ -176,6 +187,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 grouped_errors.push(GroupedMoveError::MovesFromMatchPlace {
                     span,
                     move_from: match_place.clone(),
+                    original_path,
                     kind,
                     binds_to,
                 });
@@ -206,6 +218,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 grouped_errors.push(GroupedMoveError::MovesFromPattern {
                     span: match_span,
                     move_from: mpi,
+                    original_path,
                     kind,
                     binds_to: vec![bind_to],
                 });
@@ -215,12 +228,23 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
 
     fn report(&mut self, error: GroupedMoveError<'tcx>) {
         let (mut err, err_span) = {
-            let (span, kind): (Span, &IllegalMoveOriginKind) = match error {
-                GroupedMoveError::MovesFromMatchPlace { span, ref kind, .. }
-                | GroupedMoveError::MovesFromPattern { span, ref kind, .. }
-                | GroupedMoveError::OtherIllegalMove { span, ref kind } => (span, kind),
-            };
+            let (span, original_path, kind): (Span, &Place<'tcx>, &IllegalMoveOriginKind) =
+                match error {
+                    GroupedMoveError::MovesFromMatchPlace {
+                        span,
+                        ref original_path,
+                        ref kind,
+                        ..
+                    } |
+                    GroupedMoveError::MovesFromPattern { span, ref original_path, ref kind, .. } |
+                    GroupedMoveError::OtherIllegalMove { span, ref original_path, ref kind } => {
+                        (span, original_path, kind)
+                    },
+                };
             let origin = Origin::Mir;
+            debug!("report: original_path={:?} span={:?}, kind={:?} \
+                   original_path.is_upvar_field_projection={:?}", original_path, span, kind,
+                   original_path.is_upvar_field_projection(self.mir, &self.tcx));
             (
                 match kind {
                     IllegalMoveOriginKind::Static => {
@@ -231,22 +255,17 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                         // borrow to provide feedback about why this
                         // was a move rather than a copy.
                         let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
+                        let is_upvar_field_projection =
+                            self.prefixes(&original_path, PrefixSet::All)
+                            .any(|p| p.is_upvar_field_projection(self.mir, &self.tcx)
+                                 .is_some());
                         match ty.sty {
                             ty::TyArray(..) | ty::TySlice(..) => self
                                 .tcx
                                 .cannot_move_out_of_interior_noncopy(span, ty, None, origin),
                             ty::TyClosure(def_id, closure_substs)
-                                if !self.mir.upvar_decls.is_empty()
-                                    && {
-                                        match place {
-                                            Place::Projection(ref proj) => {
-                                                proj.base == Place::Local(Local::new(1))
-                                            }
-                                            Place::Promoted(_) |
-                                            Place::Local(_) | Place::Static(_) => unreachable!(),
-                                        }
-                                    } =>
-                            {
+                                if !self.mir.upvar_decls.is_empty() && is_upvar_field_projection
+                            => {
                                 let closure_kind_ty =
                                     closure_substs.closure_kind_ty(def_id, self.tcx);
                                 let closure_kind = closure_kind_ty.to_opt_closure_kind();
@@ -262,7 +281,28 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                                     }
                                     None => bug!("closure kind not inferred by borrowck"),
                                 };
-                                self.tcx.cannot_move_out_of(span, place_description, origin)
+                                debug!("report: closure_kind_ty={:?} closure_kind={:?} \
+                                       place_description={:?}", closure_kind_ty, closure_kind,
+                                       place_description);
+
+                                let mut diag = self.tcx.cannot_move_out_of(
+                                    span, place_description, origin);
+
+                                for prefix in self.prefixes(&original_path, PrefixSet::All) {
+                                    if let Some(field) = prefix.is_upvar_field_projection(
+                                            self.mir, &self.tcx) {
+                                        let upvar_decl = &self.mir.upvar_decls[field.index()];
+                                        let upvar_hir_id =
+                                            upvar_decl.var_hir_id.assert_crate_local();
+                                        let upvar_node_id =
+                                            self.tcx.hir.hir_to_node_id(upvar_hir_id);
+                                        let upvar_span = self.tcx.hir.span(upvar_node_id);
+                                        diag.span_label(upvar_span, "captured outer variable");
+                                        break;
+                                    }
+                                }
+
+                                diag
                             }
                             _ => self
                                 .tcx
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index e8862320ddf3f..283cccd51174a 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -36,10 +36,18 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
         error_access: AccessKind,
         location: Location,
     ) {
+        debug!(
+            "report_mutability_error(\
+                access_place={:?}, span={:?}, the_place_err={:?}, error_access={:?}, location={:?},\
+            )",
+            access_place, span, the_place_err, error_access, location,
+        );
+
         let mut err;
         let item_msg;
         let reason;
         let access_place_desc = self.describe_place(access_place);
+        debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
 
         match the_place_err {
             Place::Local(local) => {
@@ -63,7 +71,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 ));
 
                 item_msg = format!("`{}`", access_place_desc.unwrap());
-                if self.is_upvar(access_place) {
+                if access_place.is_upvar_field_projection(self.mir, &self.tcx).is_some() {
                     reason = ", as it is not declared as mutable".to_string();
                 } else {
                     let name = self.mir.upvar_decls[upvar_index.index()].debug_name;
@@ -82,7 +90,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                         the_place_err.ty(self.mir, self.tcx).to_ty(self.tcx)
                     ));
 
-                    reason = if self.is_upvar(access_place) {
+                    reason = if access_place.is_upvar_field_projection(self.mir,
+                                                                       &self.tcx).is_some() {
                         ", as it is a captured variable in a `Fn` closure".to_string()
                     } else {
                         ", as `Fn` closures cannot mutate their captured variables".to_string()
@@ -155,6 +164,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             }) => bug!("Unexpected immutable place."),
         }
 
+        debug!("report_mutability_error: item_msg={:?}, reason={:?}", item_msg, reason);
+
         // `act` and `acted_on` are strings that let us abstract over
         // the verbs used in some diagnostic messages.
         let act;
@@ -199,6 +210,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             }
         };
 
+        debug!("report_mutability_error: act={:?}, acted_on={:?}", act, acted_on);
+
         match the_place_err {
             // We want to suggest users use `let mut` for local (user
             // variable) mutations...
@@ -382,31 +395,6 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
 
         err.buffer(&mut self.errors_buffer);
     }
-
-    // Does this place refer to what the user sees as an upvar
-    fn is_upvar(&self, place: &Place<'tcx>) -> bool {
-        match *place {
-            Place::Projection(box Projection {
-                ref base,
-                elem: ProjectionElem::Field(_, _),
-            }) => {
-                let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
-                is_closure_or_generator(base_ty)
-            }
-            Place::Projection(box Projection {
-                base:
-                    Place::Projection(box Projection {
-                        ref base,
-                        elem: ProjectionElem::Field(upvar_index, _),
-                    }),
-                elem: ProjectionElem::Deref,
-            }) => {
-                let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
-                is_closure_or_generator(base_ty) && self.mir.upvar_decls[upvar_index.index()].by_ref
-            }
-            _ => false,
-        }
-    }
 }
 
 fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 44e46e90549a7..60030f2702055 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -27,7 +27,7 @@ struct MoveDataBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     data: MoveData<'tcx>,
-    errors: Vec<MoveError<'tcx>>,
+    errors: Vec<(Place<'tcx>, MoveError<'tcx>)>,
 }
 
 impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
@@ -186,7 +186,9 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
-    fn finalize(self) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<MoveError<'tcx>>)> {
+    fn finalize(
+        self
+    ) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
         debug!("{}", {
             debug!("moves for {:?}:", self.mir.span);
             for (j, mo) in self.data.moves.iter_enumerated() {
@@ -207,9 +209,10 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
     }
 }
 
-pub(super) fn gather_moves<'a, 'gcx, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                                           -> Result<MoveData<'tcx>,
-                                                     (MoveData<'tcx>, Vec<MoveError<'tcx>>)> {
+pub(super) fn gather_moves<'a, 'gcx, 'tcx>(
+    mir: &Mir<'tcx>,
+    tcx: TyCtxt<'a, 'gcx, 'tcx>
+) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
     let mut builder = MoveDataBuilder::new(mir, tcx);
 
     builder.gather_args();
@@ -407,7 +410,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
         let path = match self.move_path_for(place) {
             Ok(path) | Err(MoveError::UnionMove { path }) => path,
             Err(error @ MoveError::IllegalMove { .. }) => {
-                self.builder.errors.push(error);
+                self.builder.errors.push((place.clone(), error));
                 return;
             }
         };
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index 64bfd36b7eeb6..7b4cbdf7131b0 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -313,7 +313,7 @@ impl<'tcx> MoveError<'tcx> {
 
 impl<'a, 'gcx, 'tcx> MoveData<'tcx> {
     pub fn gather_moves(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                        -> Result<Self, (Self, Vec<MoveError<'tcx>>)> {
+                        -> Result<Self, (Self, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
         builder::gather_moves(mir, tcx)
     }
 }
diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs
index 79b7d042dd6db..ae4713a65de63 100644
--- a/src/librustc_mir/diagnostics.rs
+++ b/src/librustc_mir/diagnostics.rs
@@ -2164,6 +2164,29 @@ unsafe { b.resume() };
 ```
 "##,
 
+E0712: r##"
+This error occurs because a borrow of a thread-local variable was made inside a
+function which outlived the lifetime of the function.
+
+Example of erroneous code:
+
+```compile_fail,E0712
+#![feature(nll)]
+#![feature(thread_local)]
+
+#[thread_local]
+static FOO: u8 = 3;
+
+fn main() {
+    let a = &FOO; // error: thread-local variable borrowed past end of function
+
+    std::thread::spawn(move || {
+        println!("{}", a);
+    });
+}
+```
+"##,
+
 }
 
 register_diagnostics! {
diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs
index 0a53361df6e95..7be6241b3f91e 100644
--- a/src/librustc_mir/util/borrowck_errors.rs
+++ b/src/librustc_mir/util/borrowck_errors.rs
@@ -675,6 +675,22 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
 
         self.cancel_if_wrong_origin(err, o)
     }
+
+    fn thread_local_value_does_not_live_long_enough(
+        self,
+        span: Span,
+        o: Origin,
+    ) -> DiagnosticBuilder<'cx> {
+        let err = struct_span_err!(
+            self,
+            span,
+            E0712,
+            "thread-local variable borrowed past end of function{OGN}",
+            OGN = o
+        );
+
+        self.cancel_if_wrong_origin(err, o)
+    }
 }
 
 impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index d96967725f45e..7e54f176e102b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2698,7 +2698,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             self.label_ribs.pop();
         }
         self.ribs[ValueNS].pop();
-        if let Some(_) = anonymous_module {
+        if anonymous_module.is_some() {
             self.ribs[TypeNS].pop();
         }
         debug!("(resolving block) leaving block");
@@ -4256,7 +4256,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
 
         while let Some((in_module, path_segments)) = worklist.pop() {
             // abort if the module is already found
-            if let Some(_) = result { break; }
+            if result.is_some() { break; }
 
             self.populate_module_if_necessary(in_module);
 
diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs
index 2fe7d73de8aa0..d2e52f98238dd 100644
--- a/src/librustc_save_analysis/json_dumper.rs
+++ b/src/librustc_save_analysis/json_dumper.rs
@@ -39,7 +39,7 @@ pub struct WriteOutput<'b, W: Write + 'b> {
 
 impl<'b, W: Write> DumpOutput for WriteOutput<'b, W> {
     fn dump(&mut self, result: &Analysis) {
-        if let Err(_) = write!(self.output, "{}", as_json(&result)) {
+        if write!(self.output, "{}", as_json(&result)).is_err() {
             error!("Error writing output");
         }
     }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 703489f56c1fd..e256f1761f146 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -125,7 +125,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             result.push(ExternalCrateData {
                 // FIXME: change file_name field to PathBuf in rls-data
                 // https://github.com/nrc/rls-data/issues/7
-                file_name: SpanUtils::make_path_string(&lo_loc.file.name),
+                file_name: self.span_utils.make_path_string(&lo_loc.file.name),
                 num: n.as_u32(),
                 id: GlobalCrateId {
                     name: self.tcx.crate_name(n).to_string(),
diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs
index 4d93e81a78fa1..85dd2a3a20683 100644
--- a/src/librustc_save_analysis/span_utils.rs
+++ b/src/librustc_save_analysis/span_utils.rs
@@ -13,7 +13,6 @@ use rustc::session::Session;
 use generated_code;
 
 use std::cell::Cell;
-use std::env;
 
 use syntax::parse::lexer::{self, StringReader};
 use syntax::parse::token::{self, Token};
@@ -36,11 +35,10 @@ impl<'a> SpanUtils<'a> {
         }
     }
 
-    pub fn make_path_string(path: &FileName) -> String {
+    pub fn make_path_string(&self, path: &FileName) -> String {
         match *path {
             FileName::Real(ref path) if !path.is_absolute() =>
-                env::current_dir()
-                    .unwrap()
+                self.sess.working_dir.0
                     .join(&path)
                     .display()
                     .to_string(),
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 8d8482208b97d..68e851446dc96 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -758,8 +758,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                         self.span, infer::FnCall, &fty);
 
                     if let Some(self_ty) = self_ty {
-                        if let Err(_) = self.at(&ObligationCause::dummy(), self.param_env)
-                            .sup(fty.inputs()[0], self_ty)
+                        if self.at(&ObligationCause::dummy(), self.param_env)
+                               .sup(fty.inputs()[0], self_ty)
+                               .is_err()
                         {
                             return false
                         }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 8c47df8b04221..9b6772e2dbb21 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3915,7 +3915,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
             }
             hir::ExprKind::Continue(destination) => {
-                if let Ok(_) = destination.target_id {
+                if destination.target_id.is_ok() {
                     tcx.types.never
                 } else {
                     // There was an error, make typecheck fail
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 86e5bbeab706a..68e4618328077 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -486,7 +486,7 @@ pub fn run_core(search_paths: SearchPaths,
                                                         &name,
                                                         &output_filenames,
                                                         |tcx, analysis, _, result| {
-            if let Err(_) = result {
+            if result.is_err() {
                 sess.fatal("Compilation failed, aborting rustdoc");
             }
 
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 73d7a9ab8599d..ff2cc35fce807 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -44,7 +44,7 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>,
     write_header(class, &mut out).unwrap();
 
     let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm, None), sess.codemap());
-    if let Err(_) = classifier.write_source(&mut out) {
+    if classifier.write_source(&mut out).is_err() {
         return format!("<pre>{}</pre>", src);
     }
 
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index b22e239e20a0e..c104b88334061 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -625,7 +625,7 @@ impl LangString {
                     data.no_run = true;
                 }
                 x if allow_error_code_check && x.starts_with("E") && x.len() == 5 => {
-                    if let Ok(_) = x[1..].parse::<u32>() {
+                    if x[1..].parse::<u32>().is_ok() {
                         data.error_codes.push(x.to_owned());
                         seen_rust_tags = !seen_other_tags || seen_rust_tags;
                     } else {
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 62ef5626ee5bb..07507047dc2c9 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -2208,6 +2208,25 @@
     };
 
     autoCollapse(getPageId(), getCurrentValue("rustdoc-collapse") === "true");
+
+    if (window.location.hash && window.location.hash.length > 0) {
+        var hash = getPageId();
+        if (hash !== null) {
+            var elem = document.getElementById(hash);
+            if (elem && elem.offsetParent === null) {
+                console.log(elem, elem.parentNode);
+                if (elem.parentNode && elem.parentNode.previousSibling) {
+                    var collapses = elem.parentNode
+                                        .previousSibling
+                                        .getElementsByClassName("collapse-toggle");
+                    if (collapses.length > 0) {
+                        // The element is not visible, we need to make it appear!
+                        collapseDocs(collapses[0], "show");
+                    }
+                }
+            }
+        }
+    }
 }());
 
 // Sets the focus on the search bar at the top of the page
diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs
index d5eeb5252f0f1..4b8dda493b097 100644
--- a/src/libstd/os/raw/mod.rs
+++ b/src/libstd/os/raw/mod.rs
@@ -29,6 +29,8 @@ use fmt;
           all(target_os = "android", any(target_arch = "aarch64",
                                          target_arch = "arm")),
           all(target_os = "l4re", target_arch = "x86_64"),
+          all(target_os = "netbsd", any(target_arch = "arm",
+                                        target_arch = "powerpc")),
           all(target_os = "openbsd", target_arch = "aarch64"),
           all(target_os = "fuchsia", target_arch = "aarch64")))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
@@ -41,6 +43,8 @@ use fmt;
               all(target_os = "android", any(target_arch = "aarch64",
                                              target_arch = "arm")),
               all(target_os = "l4re", target_arch = "x86_64"),
+              all(target_os = "netbsd", any(target_arch = "arm",
+                                            target_arch = "powerpc")),
               all(target_os = "openbsd", target_arch = "aarch64"),
               all(target_os = "fuchsia", target_arch = "aarch64"))))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 28c1e4324de7a..17e3d88a9099d 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -13,7 +13,6 @@
 pub use self::UnsafeSource::*;
 pub use self::GenericArgs::*;
 pub use symbol::{Ident, Symbol as Name};
-pub use util::ThinVec;
 pub use util::parser::ExprPrecedence;
 
 use syntax_pos::{Span, DUMMY_SP};
@@ -25,6 +24,7 @@ use ptr::P;
 use rustc_data_structures::indexed_vec;
 use rustc_data_structures::indexed_vec::Idx;
 use symbol::{Symbol, keywords};
+use ThinVec;
 use tokenstream::{ThinTokenStream, TokenStream};
 
 use serialize::{self, Encoder, Decoder};
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index b3b173db70b89..879f555ba03ee 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -33,8 +33,8 @@ use parse::{self, ParseSess, PResult};
 use parse::token::{self, Token};
 use ptr::P;
 use symbol::Symbol;
+use ThinVec;
 use tokenstream::{TokenStream, TokenTree, Delimited};
-use util::ThinVec;
 use GLOBALS;
 
 use std::iter;
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 3364378913952..4fe78bf829a1c 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -15,9 +15,9 @@ use ast;
 use codemap::Spanned;
 use edition::Edition;
 use parse::{token, ParseSess};
+use OneVector;
 
 use ptr::P;
-use util::small_vector::SmallVector;
 
 /// A folder that strips out items that do not belong in the current configuration.
 pub struct StripUnconfigured<'a> {
@@ -319,22 +319,22 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
         Some(P(fold::noop_fold_expr(expr, self)))
     }
 
-    fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
+    fn fold_stmt(&mut self, stmt: ast::Stmt) -> OneVector<ast::Stmt> {
         match self.configure_stmt(stmt) {
             Some(stmt) => fold::noop_fold_stmt(stmt, self),
-            None => return SmallVector::new(),
+            None => return OneVector::new(),
         }
     }
 
-    fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
+    fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
         fold::noop_fold_item(configure!(self, item), self)
     }
 
-    fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVector<ast::ImplItem> {
+    fn fold_impl_item(&mut self, item: ast::ImplItem) -> OneVector<ast::ImplItem> {
         fold::noop_fold_impl_item(configure!(self, item), self)
     }
 
-    fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector<ast::TraitItem> {
+    fn fold_trait_item(&mut self, item: ast::TraitItem) -> OneVector<ast::TraitItem> {
         fold::noop_fold_trait_item(configure!(self, item), self)
     }
 
diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs
index 72ce2740190d4..6a5a2a5e500ff 100644
--- a/src/libsyntax/diagnostics/plugin.rs
+++ b/src/libsyntax/diagnostics/plugin.rs
@@ -19,9 +19,9 @@ use ext::base::{ExtCtxt, MacEager, MacResult};
 use ext::build::AstBuilder;
 use parse::token;
 use ptr::P;
+use OneVector;
 use symbol::{keywords, Symbol};
 use tokenstream::{TokenTree};
-use util::small_vector::SmallVector;
 
 use diagnostics::metadata::output_metadata;
 
@@ -131,7 +131,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
     let sym = Ident::with_empty_ctxt(Symbol::gensym(&format!(
         "__register_diagnostic_{}", code
     )));
-    MacEager::items(SmallVector::many(vec![
+    MacEager::items(OneVector::many(vec![
         ecx.item_mod(
             span,
             span,
@@ -214,7 +214,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
         ),
     );
 
-    MacEager::items(SmallVector::many(vec![
+    MacEager::items(OneVector::many(vec![
         P(ast::Item {
             ident: *name,
             attrs: Vec::new(),
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index de391ee4219a4..482d8c2cf9866 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -22,8 +22,9 @@ use fold::{self, Folder};
 use parse::{self, parser, DirectoryOwnership};
 use parse::token;
 use ptr::P;
+use OneVector;
 use symbol::{keywords, Ident, Symbol};
-use util::small_vector::SmallVector;
+use ThinVec;
 
 use std::collections::HashMap;
 use std::iter;
@@ -315,7 +316,7 @@ impl<F> IdentMacroExpander for F
 // Use a macro because forwarding to a simple function has type system issues
 macro_rules! make_stmts_default {
     ($me:expr) => {
-        $me.make_expr().map(|e| SmallVector::one(ast::Stmt {
+        $me.make_expr().map(|e| OneVector::one(ast::Stmt {
             id: ast::DUMMY_NODE_ID,
             span: e.span,
             node: ast::StmtKind::Expr(e),
@@ -331,22 +332,22 @@ pub trait MacResult {
         None
     }
     /// Create zero or more items.
-    fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> {
+    fn make_items(self: Box<Self>) -> Option<OneVector<P<ast::Item>>> {
         None
     }
 
     /// Create zero or more impl items.
-    fn make_impl_items(self: Box<Self>) -> Option<SmallVector<ast::ImplItem>> {
+    fn make_impl_items(self: Box<Self>) -> Option<OneVector<ast::ImplItem>> {
         None
     }
 
     /// Create zero or more trait items.
-    fn make_trait_items(self: Box<Self>) -> Option<SmallVector<ast::TraitItem>> {
+    fn make_trait_items(self: Box<Self>) -> Option<OneVector<ast::TraitItem>> {
         None
     }
 
     /// Create zero or more items in an `extern {}` block
-    fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> { None }
+    fn make_foreign_items(self: Box<Self>) -> Option<OneVector<ast::ForeignItem>> { None }
 
     /// Create a pattern.
     fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
@@ -357,7 +358,7 @@ pub trait MacResult {
     ///
     /// By default this attempts to create an expression statement,
     /// returning None if that fails.
-    fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
+    fn make_stmts(self: Box<Self>) -> Option<OneVector<ast::Stmt>> {
         make_stmts_default!(self)
     }
 
@@ -393,11 +394,11 @@ macro_rules! make_MacEager {
 make_MacEager! {
     expr: P<ast::Expr>,
     pat: P<ast::Pat>,
-    items: SmallVector<P<ast::Item>>,
-    impl_items: SmallVector<ast::ImplItem>,
-    trait_items: SmallVector<ast::TraitItem>,
-    foreign_items: SmallVector<ast::ForeignItem>,
-    stmts: SmallVector<ast::Stmt>,
+    items: OneVector<P<ast::Item>>,
+    impl_items: OneVector<ast::ImplItem>,
+    trait_items: OneVector<ast::TraitItem>,
+    foreign_items: OneVector<ast::ForeignItem>,
+    stmts: OneVector<ast::Stmt>,
     ty: P<ast::Ty>,
 }
 
@@ -406,23 +407,23 @@ impl MacResult for MacEager {
         self.expr
     }
 
-    fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> {
+    fn make_items(self: Box<Self>) -> Option<OneVector<P<ast::Item>>> {
         self.items
     }
 
-    fn make_impl_items(self: Box<Self>) -> Option<SmallVector<ast::ImplItem>> {
+    fn make_impl_items(self: Box<Self>) -> Option<OneVector<ast::ImplItem>> {
         self.impl_items
     }
 
-    fn make_trait_items(self: Box<Self>) -> Option<SmallVector<ast::TraitItem>> {
+    fn make_trait_items(self: Box<Self>) -> Option<OneVector<ast::TraitItem>> {
         self.trait_items
     }
 
-    fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> {
+    fn make_foreign_items(self: Box<Self>) -> Option<OneVector<ast::ForeignItem>> {
         self.foreign_items
     }
 
-    fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
+    fn make_stmts(self: Box<Self>) -> Option<OneVector<ast::Stmt>> {
         match self.stmts.as_ref().map_or(0, |s| s.len()) {
             0 => make_stmts_default!(self),
             _ => self.stmts,
@@ -482,7 +483,7 @@ impl DummyResult {
             id: ast::DUMMY_NODE_ID,
             node: ast::ExprKind::Lit(P(codemap::respan(sp, ast::LitKind::Bool(false)))),
             span: sp,
-            attrs: ast::ThinVec::new(),
+            attrs: ThinVec::new(),
         })
     }
 
@@ -513,41 +514,41 @@ impl MacResult for DummyResult {
         Some(P(DummyResult::raw_pat(self.span)))
     }
 
-    fn make_items(self: Box<DummyResult>) -> Option<SmallVector<P<ast::Item>>> {
+    fn make_items(self: Box<DummyResult>) -> Option<OneVector<P<ast::Item>>> {
         // this code needs a comment... why not always just return the Some() ?
         if self.expr_only {
             None
         } else {
-            Some(SmallVector::new())
+            Some(OneVector::new())
         }
     }
 
-    fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVector<ast::ImplItem>> {
+    fn make_impl_items(self: Box<DummyResult>) -> Option<OneVector<ast::ImplItem>> {
         if self.expr_only {
             None
         } else {
-            Some(SmallVector::new())
+            Some(OneVector::new())
         }
     }
 
-    fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVector<ast::TraitItem>> {
+    fn make_trait_items(self: Box<DummyResult>) -> Option<OneVector<ast::TraitItem>> {
         if self.expr_only {
             None
         } else {
-            Some(SmallVector::new())
+            Some(OneVector::new())
         }
     }
 
-    fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> {
+    fn make_foreign_items(self: Box<Self>) -> Option<OneVector<ast::ForeignItem>> {
         if self.expr_only {
             None
         } else {
-            Some(SmallVector::new())
+            Some(OneVector::new())
         }
     }
 
-    fn make_stmts(self: Box<DummyResult>) -> Option<SmallVector<ast::Stmt>> {
-        Some(SmallVector::one(ast::Stmt {
+    fn make_stmts(self: Box<DummyResult>) -> Option<OneVector<ast::Stmt>> {
+        Some(OneVector::one(ast::Stmt {
             id: ast::DUMMY_NODE_ID,
             node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span)),
             span: self.span,
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 6135650766569..1a17aa3e8fb64 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -16,6 +16,7 @@ use codemap::{dummy_spanned, respan, Spanned};
 use ext::base::ExtCtxt;
 use ptr::P;
 use symbol::{Symbol, keywords};
+use ThinVec;
 
 // Transitional re-exports so qquote can find the paths it is looking for
 mod syntax {
@@ -519,7 +520,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             init: Some(ex),
             id: ast::DUMMY_NODE_ID,
             span: sp,
-            attrs: ast::ThinVec::new(),
+            attrs: ThinVec::new(),
         });
         ast::Stmt {
             id: ast::DUMMY_NODE_ID,
@@ -547,7 +548,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             init: Some(ex),
             id: ast::DUMMY_NODE_ID,
             span: sp,
-            attrs: ast::ThinVec::new(),
+            attrs: ThinVec::new(),
         });
         ast::Stmt {
             id: ast::DUMMY_NODE_ID,
@@ -564,7 +565,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             init: None,
             id: ast::DUMMY_NODE_ID,
             span,
-            attrs: ast::ThinVec::new(),
+            attrs: ThinVec::new(),
         });
         ast::Stmt {
             id: ast::DUMMY_NODE_ID,
@@ -603,7 +604,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             id: ast::DUMMY_NODE_ID,
             node,
             span,
-            attrs: ast::ThinVec::new(),
+            attrs: ThinVec::new(),
         })
     }
 
@@ -678,7 +679,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             expr: e,
             span,
             is_shorthand: false,
-            attrs: ast::ThinVec::new(),
+            attrs: ThinVec::new(),
         }
     }
     fn expr_struct(&self, span: Span, path: ast::Path, fields: Vec<ast::Field>) -> P<ast::Expr> {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 12941a8566987..f7ea781e02115 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -26,12 +26,12 @@ use parse::{DirectoryOwnership, PResult, ParseSess};
 use parse::token::{self, Token};
 use parse::parser::Parser;
 use ptr::P;
+use OneVector;
 use symbol::Symbol;
 use symbol::keywords;
 use syntax_pos::{Span, DUMMY_SP, FileName};
 use syntax_pos::hygiene::ExpnFormat;
 use tokenstream::{TokenStream, TokenTree};
-use util::small_vector::SmallVector;
 use visit::{self, Visitor};
 
 use std::collections::HashMap;
@@ -131,7 +131,7 @@ macro_rules! ast_fragments {
                 self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()
             })*)*
             $($(fn $fold_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy {
-                self.expand_fragment(AstFragment::$Kind(SmallVector::one(ast_elt))).$make_ast()
+                self.expand_fragment(AstFragment::$Kind(OneVector::one(ast_elt))).$make_ast()
             })*)*
         }
 
@@ -148,15 +148,15 @@ ast_fragments! {
     Expr(P<ast::Expr>) { "expression"; one fn fold_expr; fn visit_expr; fn make_expr; }
     Pat(P<ast::Pat>) { "pattern"; one fn fold_pat; fn visit_pat; fn make_pat; }
     Ty(P<ast::Ty>) { "type"; one fn fold_ty; fn visit_ty; fn make_ty; }
-    Stmts(SmallVector<ast::Stmt>) { "statement"; many fn fold_stmt; fn visit_stmt; fn make_stmts; }
-    Items(SmallVector<P<ast::Item>>) { "item"; many fn fold_item; fn visit_item; fn make_items; }
-    TraitItems(SmallVector<ast::TraitItem>) {
+    Stmts(OneVector<ast::Stmt>) { "statement"; many fn fold_stmt; fn visit_stmt; fn make_stmts; }
+    Items(OneVector<P<ast::Item>>) { "item"; many fn fold_item; fn visit_item; fn make_items; }
+    TraitItems(OneVector<ast::TraitItem>) {
         "trait item"; many fn fold_trait_item; fn visit_trait_item; fn make_trait_items;
     }
-    ImplItems(SmallVector<ast::ImplItem>) {
+    ImplItems(OneVector<ast::ImplItem>) {
         "impl item"; many fn fold_impl_item; fn visit_impl_item; fn make_impl_items;
     }
-    ForeignItems(SmallVector<ast::ForeignItem>) {
+    ForeignItems(OneVector<ast::ForeignItem>) {
         "foreign item"; many fn fold_foreign_item; fn visit_foreign_item; fn make_foreign_items;
     }
 }
@@ -279,7 +279,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
 
         let orig_mod_span = krate.module.inner;
 
-        let krate_item = AstFragment::Items(SmallVector::one(P(ast::Item {
+        let krate_item = AstFragment::Items(OneVector::one(P(ast::Item {
             attrs: krate.attrs,
             span: krate.span,
             node: ast::ItemKind::Mod(krate.module),
@@ -989,28 +989,28 @@ impl<'a> Parser<'a> {
                               -> PResult<'a, AstFragment> {
         Ok(match kind {
             AstFragmentKind::Items => {
-                let mut items = SmallVector::new();
+                let mut items = OneVector::new();
                 while let Some(item) = self.parse_item()? {
                     items.push(item);
                 }
                 AstFragment::Items(items)
             }
             AstFragmentKind::TraitItems => {
-                let mut items = SmallVector::new();
+                let mut items = OneVector::new();
                 while self.token != token::Eof {
                     items.push(self.parse_trait_item(&mut false)?);
                 }
                 AstFragment::TraitItems(items)
             }
             AstFragmentKind::ImplItems => {
-                let mut items = SmallVector::new();
+                let mut items = OneVector::new();
                 while self.token != token::Eof {
                     items.push(self.parse_impl_item(&mut false)?);
                 }
                 AstFragment::ImplItems(items)
             }
             AstFragmentKind::ForeignItems => {
-                let mut items = SmallVector::new();
+                let mut items = OneVector::new();
                 while self.token != token::Eof {
                     if let Some(item) = self.parse_foreign_item()? {
                         items.push(item);
@@ -1019,7 +1019,7 @@ impl<'a> Parser<'a> {
                 AstFragment::ForeignItems(items)
             }
             AstFragmentKind::Stmts => {
-                let mut stmts = SmallVector::new();
+                let mut stmts = OneVector::new();
                 while self.token != token::Eof &&
                       // won't make progress on a `}`
                       self.token != token::CloseDelim(token::Brace) {
@@ -1086,12 +1086,12 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
 
     /// Folds the item allowing tests to be expanded because they are still nameable.
     /// This should probably only be called with module items
-    fn fold_nameable(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
+    fn fold_nameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
         fold::noop_fold_item(item, self)
     }
 
     /// Folds the item but doesn't allow tests to occur within it
-    fn fold_unnameable(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
+    fn fold_unnameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
         let was_nameable = mem::replace(&mut self.tests_nameable, false);
         let items = fold::noop_fold_item(item, self);
         self.tests_nameable = was_nameable;
@@ -1254,10 +1254,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
         })
     }
 
-    fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
+    fn fold_stmt(&mut self, stmt: ast::Stmt) -> OneVector<ast::Stmt> {
         let mut stmt = match self.cfg.configure_stmt(stmt) {
             Some(stmt) => stmt,
-            None => return SmallVector::new(),
+            None => return OneVector::new(),
         };
 
         // we'll expand attributes on expressions separately
@@ -1313,7 +1313,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
         result
     }
 
-    fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
+    fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
         let item = configure!(self, item);
 
         let (attr, traits, mut item) = self.classify_item(item);
@@ -1422,7 +1422,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
                         ui
                     });
 
-                    SmallVector::many(
+                    OneVector::many(
                         self.fold_unnameable(item).into_iter()
                             .chain(self.fold_unnameable(use_item)))
                 } else {
@@ -1433,7 +1433,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
         }
     }
 
-    fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector<ast::TraitItem> {
+    fn fold_trait_item(&mut self, item: ast::TraitItem) -> OneVector<ast::TraitItem> {
         let item = configure!(self, item);
 
         let (attr, traits, item) = self.classify_item(item);
@@ -1453,7 +1453,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
         }
     }
 
-    fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVector<ast::ImplItem> {
+    fn fold_impl_item(&mut self, item: ast::ImplItem) -> OneVector<ast::ImplItem> {
         let item = configure!(self, item);
 
         let (attr, traits, item) = self.classify_item(item);
@@ -1490,7 +1490,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
     }
 
     fn fold_foreign_item(&mut self,
-                         foreign_item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> {
+                         foreign_item: ast::ForeignItem) -> OneVector<ast::ForeignItem> {
         let (attr, traits, foreign_item) = self.classify_item(foreign_item);
 
         if attr.is_some() || !traits.is_empty() {
diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs
index 968cf508edaaa..1dc9bae8848f3 100644
--- a/src/libsyntax/ext/placeholders.rs
+++ b/src/libsyntax/ext/placeholders.rs
@@ -16,9 +16,10 @@ use ext::hygiene::Mark;
 use tokenstream::TokenStream;
 use fold::*;
 use ptr::P;
+use OneVector;
 use symbol::keywords;
+use ThinVec;
 use util::move_map::MoveMap;
-use util::small_vector::SmallVector;
 
 use std::collections::HashMap;
 
@@ -38,31 +39,31 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
     let span = DUMMY_SP;
     let expr_placeholder = || P(ast::Expr {
         id, span,
-        attrs: ast::ThinVec::new(),
+        attrs: ThinVec::new(),
         node: ast::ExprKind::Mac(mac_placeholder()),
     });
 
     match kind {
         AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
         AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
-        AstFragmentKind::Items => AstFragment::Items(SmallVector::one(P(ast::Item {
+        AstFragmentKind::Items => AstFragment::Items(OneVector::one(P(ast::Item {
             id, span, ident, vis, attrs,
             node: ast::ItemKind::Mac(mac_placeholder()),
             tokens: None,
         }))),
-        AstFragmentKind::TraitItems => AstFragment::TraitItems(SmallVector::one(ast::TraitItem {
+        AstFragmentKind::TraitItems => AstFragment::TraitItems(OneVector::one(ast::TraitItem {
             id, span, ident, attrs, generics,
             node: ast::TraitItemKind::Macro(mac_placeholder()),
             tokens: None,
         })),
-        AstFragmentKind::ImplItems => AstFragment::ImplItems(SmallVector::one(ast::ImplItem {
+        AstFragmentKind::ImplItems => AstFragment::ImplItems(OneVector::one(ast::ImplItem {
             id, span, ident, vis, attrs, generics,
             node: ast::ImplItemKind::Macro(mac_placeholder()),
             defaultness: ast::Defaultness::Final,
             tokens: None,
         })),
         AstFragmentKind::ForeignItems =>
-            AstFragment::ForeignItems(SmallVector::one(ast::ForeignItem {
+            AstFragment::ForeignItems(OneVector::one(ast::ForeignItem {
                 id, span, ident, vis, attrs,
                 node: ast::ForeignItemKind::Macro(mac_placeholder()),
             })),
@@ -72,8 +73,8 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
         AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
             id, span, node: ast::TyKind::Mac(mac_placeholder()),
         })),
-        AstFragmentKind::Stmts => AstFragment::Stmts(SmallVector::one({
-            let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::ThinVec::new()));
+        AstFragmentKind::Stmts => AstFragment::Stmts(OneVector::one({
+            let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ThinVec::new()));
             ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) }
         })),
     }
@@ -114,31 +115,31 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> {
 }
 
 impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
-    fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
+    fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
         match item.node {
             ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
-            ast::ItemKind::MacroDef(_) => return SmallVector::one(item),
+            ast::ItemKind::MacroDef(_) => return OneVector::one(item),
             _ => {}
         }
 
         noop_fold_item(item, self)
     }
 
-    fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector<ast::TraitItem> {
+    fn fold_trait_item(&mut self, item: ast::TraitItem) -> OneVector<ast::TraitItem> {
         match item.node {
             ast::TraitItemKind::Macro(_) => self.remove(item.id).make_trait_items(),
             _ => noop_fold_trait_item(item, self),
         }
     }
 
-    fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVector<ast::ImplItem> {
+    fn fold_impl_item(&mut self, item: ast::ImplItem) -> OneVector<ast::ImplItem> {
         match item.node {
             ast::ImplItemKind::Macro(_) => self.remove(item.id).make_impl_items(),
             _ => noop_fold_impl_item(item, self),
         }
     }
 
-    fn fold_foreign_item(&mut self, item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> {
+    fn fold_foreign_item(&mut self, item: ast::ForeignItem) -> OneVector<ast::ForeignItem> {
         match item.node {
             ast::ForeignItemKind::Macro(_) => self.remove(item.id).make_foreign_items(),
             _ => noop_fold_foreign_item(item, self),
@@ -159,7 +160,7 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
         }
     }
 
-    fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
+    fn fold_stmt(&mut self, stmt: ast::Stmt) -> OneVector<ast::Stmt> {
         let (style, mut stmts) = match stmt.node {
             ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
             _ => return noop_fold_stmt(stmt, self),
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 1ace4d4a880e2..bc891700fc1b6 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -34,6 +34,7 @@ pub mod rt {
     use parse::token::{self, Token};
     use ptr::P;
     use symbol::Symbol;
+    use ThinVec;
 
     use tokenstream::{self, TokenTree, TokenStream};
 
@@ -274,7 +275,7 @@ pub mod rt {
                 id: ast::DUMMY_NODE_ID,
                 node: ast::ExprKind::Lit(P(self.clone())),
                 span: DUMMY_SP,
-                attrs: ast::ThinVec::new(),
+                attrs: ThinVec::new(),
             }).to_tokens(cx)
         }
     }
@@ -305,7 +306,7 @@ pub mod rt {
                         id: ast::DUMMY_NODE_ID,
                         node: ast::ExprKind::Lit(P(dummy_spanned(lit))),
                         span: DUMMY_SP,
-                        attrs: ast::ThinVec::new(),
+                        attrs: ThinVec::new(),
                     });
                     if *self >= 0 {
                         return lit.to_tokens(cx);
@@ -314,7 +315,7 @@ pub mod rt {
                         id: ast::DUMMY_NODE_ID,
                         node: ast::ExprKind::Unary(ast::UnOp::Neg, lit),
                         span: DUMMY_SP,
-                        attrs: ast::ThinVec::new(),
+                        attrs: ThinVec::new(),
                     }).to_tokens(cx)
                 }
             }
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 0c36c072a0302..9b7e0fe1ae55c 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -17,9 +17,9 @@ use parse::{token, DirectoryOwnership};
 use parse;
 use print::pprust;
 use ptr::P;
+use OneVector;
 use symbol::Symbol;
 use tokenstream;
-use util::small_vector::SmallVector;
 
 use std::fs::File;
 use std::io::prelude::*;
@@ -111,8 +111,8 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T
             Some(panictry!(self.p.parse_expr()))
         }
         fn make_items(mut self: Box<ExpandResult<'a>>)
-                      -> Option<SmallVector<P<ast::Item>>> {
-            let mut ret = SmallVector::new();
+                      -> Option<OneVector<P<ast::Item>>> {
+            let mut ret = OneVector::new();
             while self.p.token != token::Eof {
                 match panictry!(self.p.parse_item()) {
                     Some(item) => ret.push(item),
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 3046525b7144c..82f88d1d8643e 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -92,9 +92,9 @@ use parse::{Directory, ParseSess};
 use parse::parser::{Parser, PathStyle};
 use parse::token::{self, DocComment, Nonterminal, Token};
 use print::pprust;
+use OneVector;
 use symbol::keywords;
 use tokenstream::TokenStream;
-use util::small_vector::SmallVector;
 
 use std::mem;
 use std::ops::{Deref, DerefMut};
@@ -440,10 +440,10 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
 /// A `ParseResult`. Note that matches are kept track of through the items generated.
 fn inner_parse_loop<'a>(
     sess: &ParseSess,
-    cur_items: &mut SmallVector<MatcherPosHandle<'a>>,
+    cur_items: &mut OneVector<MatcherPosHandle<'a>>,
     next_items: &mut Vec<MatcherPosHandle<'a>>,
-    eof_items: &mut SmallVector<MatcherPosHandle<'a>>,
-    bb_items: &mut SmallVector<MatcherPosHandle<'a>>,
+    eof_items: &mut OneVector<MatcherPosHandle<'a>>,
+    bb_items: &mut OneVector<MatcherPosHandle<'a>>,
     token: &Token,
     span: syntax_pos::Span,
 ) -> ParseResult<()> {
@@ -644,15 +644,15 @@ pub fn parse(
     // This MatcherPos instance is allocated on the stack. All others -- and
     // there are frequently *no* others! -- are allocated on the heap.
     let mut initial = initial_matcher_pos(ms, parser.span.lo());
-    let mut cur_items = SmallVector::one(MatcherPosHandle::Ref(&mut initial));
+    let mut cur_items = OneVector::one(MatcherPosHandle::Ref(&mut initial));
     let mut next_items = Vec::new();
 
     loop {
         // Matcher positions black-box parsed by parser.rs (`parser`)
-        let mut bb_items = SmallVector::new();
+        let mut bb_items = OneVector::new();
 
         // Matcher positions that would be valid if the macro invocation was over now
-        let mut eof_items = SmallVector::new();
+        let mut eof_items = OneVector::new();
         assert!(next_items.is_empty());
 
         // Process `cur_items` until either we have finished the input or we need to get some
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index e7e94614ac865..f51d079a6c058 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -181,7 +181,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
         for lhs in lhses { // try each arm's matchers
             let lhs_tt = match *lhs {
                 quoted::TokenTree::Delimited(_, ref delim) => &delim.tts[..],
-                _ => cx.span_bug(sp, "malformed macro lhs")
+                _ => continue,
             };
             match TokenTree::parse(cx, lhs_tt, arg.clone()) {
                 Success(_) => {
@@ -191,7 +191,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
                         err.span_suggestion_short(
                             comma_span,
                             "missing comma here",
-                            ",".to_string(),
+                            ", ".to_string(),
                         );
                     }
                 }
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 1cdb6b0e5c902..d451227e77cf3 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -15,9 +15,9 @@ use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
 use ext::tt::quoted;
 use fold::noop_fold_tt;
 use parse::token::{self, Token, NtTT};
+use OneVector;
 use syntax_pos::{Span, DUMMY_SP};
 use tokenstream::{TokenStream, TokenTree, Delimited};
-use util::small_vector::SmallVector;
 
 use std::rc::Rc;
 use rustc_data_structures::sync::Lrc;
@@ -70,7 +70,7 @@ pub fn transcribe(cx: &ExtCtxt,
                   interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
                   src: Vec<quoted::TokenTree>)
                   -> TokenStream {
-    let mut stack = SmallVector::one(Frame::new(src));
+    let mut stack = OneVector::one(Frame::new(src));
     let interpolations = interp.unwrap_or_else(HashMap::new); /* just a convenience */
     let mut repeats = Vec::new();
     let mut result: Vec<TokenStream> = Vec::new();
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 65eeaff3f1078..976708ae78816 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -452,6 +452,7 @@ declare_features! (
     (active, mmx_target_feature, "1.27.0", Some(44839), None),
     (active, sse4a_target_feature, "1.27.0", Some(44839), None),
     (active, tbm_target_feature, "1.27.0", Some(44839), None),
+    (active, wasm_target_feature, "1.30.0", Some(44839), None),
 
     // Allows macro invocations of the form `#[foo::bar]`
     (active, proc_macro_path_invoc, "1.27.0", Some(38356), None),
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 9d5982c1e2861..3209939d9b14d 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -24,9 +24,10 @@ use syntax_pos::Span;
 use codemap::{Spanned, respan};
 use parse::token::{self, Token};
 use ptr::P;
+use OneVector;
 use symbol::keywords;
+use ThinVec;
 use tokenstream::*;
-use util::small_vector::SmallVector;
 use util::move_map::MoveMap;
 
 use rustc_data_structures::sync::Lrc;
@@ -60,7 +61,7 @@ pub trait Folder : Sized {
         noop_fold_use_tree(use_tree, self)
     }
 
-    fn fold_foreign_item(&mut self, ni: ForeignItem) -> SmallVector<ForeignItem> {
+    fn fold_foreign_item(&mut self, ni: ForeignItem) -> OneVector<ForeignItem> {
         noop_fold_foreign_item(ni, self)
     }
 
@@ -68,7 +69,7 @@ pub trait Folder : Sized {
         noop_fold_foreign_item_simple(ni, self)
     }
 
-    fn fold_item(&mut self, i: P<Item>) -> SmallVector<P<Item>> {
+    fn fold_item(&mut self, i: P<Item>) -> OneVector<P<Item>> {
         noop_fold_item(i, self)
     }
 
@@ -88,11 +89,11 @@ pub trait Folder : Sized {
         noop_fold_item_kind(i, self)
     }
 
-    fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
+    fn fold_trait_item(&mut self, i: TraitItem) -> OneVector<TraitItem> {
         noop_fold_trait_item(i, self)
     }
 
-    fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
+    fn fold_impl_item(&mut self, i: ImplItem) -> OneVector<ImplItem> {
         noop_fold_impl_item(i, self)
     }
 
@@ -108,7 +109,7 @@ pub trait Folder : Sized {
         noop_fold_block(b, self)
     }
 
-    fn fold_stmt(&mut self, s: Stmt) -> SmallVector<Stmt> {
+    fn fold_stmt(&mut self, s: Stmt) -> OneVector<Stmt> {
         noop_fold_stmt(s, self)
     }
 
@@ -960,8 +961,8 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
 }
 
 pub fn noop_fold_trait_item<T: Folder>(i: TraitItem, folder: &mut T)
-                                       -> SmallVector<TraitItem> {
-    SmallVector::one(TraitItem {
+                                       -> OneVector<TraitItem> {
+    OneVector::one(TraitItem {
         id: folder.new_id(i.id),
         ident: folder.fold_ident(i.ident),
         attrs: fold_attrs(i.attrs, folder),
@@ -989,8 +990,8 @@ pub fn noop_fold_trait_item<T: Folder>(i: TraitItem, folder: &mut T)
 }
 
 pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T)
-                                      -> SmallVector<ImplItem> {
-    SmallVector::one(ImplItem {
+                                      -> OneVector<ImplItem> {
+    OneVector::one(ImplItem {
         id: folder.new_id(i.id),
         vis: folder.fold_vis(i.vis),
         ident: folder.fold_ident(i.ident),
@@ -1065,8 +1066,8 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
 }
 
 // fold one item into possibly many items
-pub fn noop_fold_item<T: Folder>(i: P<Item>, folder: &mut T) -> SmallVector<P<Item>> {
-    SmallVector::one(i.map(|i| folder.fold_item_simple(i)))
+pub fn noop_fold_item<T: Folder>(i: P<Item>, folder: &mut T) -> OneVector<P<Item>> {
+    OneVector::one(i.map(|i| folder.fold_item_simple(i)))
 }
 
 // fold one item into exactly one item
@@ -1087,8 +1088,8 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span,
 }
 
 pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T)
--> SmallVector<ForeignItem> {
-    SmallVector::one(folder.fold_foreign_item_simple(ni))
+-> OneVector<ForeignItem> {
+    OneVector::one(folder.fold_foreign_item_simple(ni))
 }
 
 pub fn noop_fold_foreign_item_simple<T: Folder>(ni: ForeignItem, folder: &mut T) -> ForeignItem {
@@ -1366,7 +1367,7 @@ pub fn noop_fold_exprs<T: Folder>(es: Vec<P<Expr>>, folder: &mut T) -> Vec<P<Exp
     es.move_flat_map(|e| folder.fold_opt_expr(e))
 }
 
-pub fn noop_fold_stmt<T: Folder>(Stmt {node, span, id}: Stmt, folder: &mut T) -> SmallVector<Stmt> {
+pub fn noop_fold_stmt<T: Folder>(Stmt {node, span, id}: Stmt, folder: &mut T) -> OneVector<Stmt> {
     let id = folder.new_id(id);
     let span = folder.new_span(span);
     noop_fold_stmt_kind(node, folder).into_iter().map(|node| {
@@ -1374,9 +1375,9 @@ pub fn noop_fold_stmt<T: Folder>(Stmt {node, span, id}: Stmt, folder: &mut T) ->
     }).collect()
 }
 
-pub fn noop_fold_stmt_kind<T: Folder>(node: StmtKind, folder: &mut T) -> SmallVector<StmtKind> {
+pub fn noop_fold_stmt_kind<T: Folder>(node: StmtKind, folder: &mut T) -> OneVector<StmtKind> {
     match node {
-        StmtKind::Local(local) => SmallVector::one(StmtKind::Local(folder.fold_local(local))),
+        StmtKind::Local(local) => OneVector::one(StmtKind::Local(folder.fold_local(local))),
         StmtKind::Item(item) => folder.fold_item(item).into_iter().map(StmtKind::Item).collect(),
         StmtKind::Expr(expr) => {
             folder.fold_opt_expr(expr).into_iter().map(StmtKind::Expr).collect()
@@ -1384,7 +1385,7 @@ pub fn noop_fold_stmt_kind<T: Folder>(node: StmtKind, folder: &mut T) -> SmallVe
         StmtKind::Semi(expr) => {
             folder.fold_opt_expr(expr).into_iter().map(StmtKind::Semi).collect()
         }
-        StmtKind::Mac(mac) => SmallVector::one(StmtKind::Mac(mac.map(|(mac, semi, attrs)| {
+        StmtKind::Mac(mac) => OneVector::one(StmtKind::Mac(mac.map(|(mac, semi, attrs)| {
             (folder.fold_mac(mac), semi, fold_attrs(attrs.into(), folder).into())
         }))),
     }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index c8e60620248b3..7937799272c66 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -43,6 +43,8 @@ extern crate serialize as rustc_serialize; // used by deriving
 
 use rustc_data_structures::sync::Lock;
 use rustc_data_structures::bitvec::BitVector;
+pub use rustc_data_structures::small_vec::OneVector;
+pub use rustc_data_structures::thin_vec::ThinVec;
 use ast::AttrId;
 
 // A variant of 'try!' that panics on an Err. This is used as a crutch on the
@@ -122,12 +124,8 @@ pub mod util {
     pub mod parser;
     #[cfg(test)]
     pub mod parser_testing;
-    pub mod small_vector;
     pub mod move_map;
 
-    mod thin_vec;
-    pub use self::thin_vec::ThinVec;
-
     mod rc_slice;
     pub use self::rc_slice::RcSlice;
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 9011b6e48b974..27b0f23315180 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -53,9 +53,9 @@ use util::parser::{AssocOp, Fixity};
 use print::pprust;
 use ptr::P;
 use parse::PResult;
+use ThinVec;
 use tokenstream::{self, Delimited, ThinTokenStream, TokenTree, TokenStream};
 use symbol::{Symbol, keywords};
-use util::ThinVec;
 
 use std::borrow::Cow;
 use std::cmp;
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index d8b8d13a38c2e..1cbaf3cc312b7 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -38,8 +38,9 @@ use parse::{token, ParseSess};
 use print::pprust;
 use ast::{self, Ident};
 use ptr::P;
+use OneVector;
 use symbol::{self, Symbol, keywords};
-use util::small_vector::SmallVector;
+use ThinVec;
 
 enum ShouldPanic {
     No,
@@ -115,7 +116,7 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
         folded
     }
 
-    fn fold_item(&mut self, i: P<ast::Item>) -> SmallVector<P<ast::Item>> {
+    fn fold_item(&mut self, i: P<ast::Item>) -> OneVector<P<ast::Item>> {
         let ident = i.ident;
         if ident.name != keywords::Invalid.name() {
             self.cx.path.push(ident);
@@ -182,7 +183,7 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
         if ident.name != keywords::Invalid.name() {
             self.cx.path.pop();
         }
-        SmallVector::one(P(item))
+        OneVector::one(P(item))
     }
 
     fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac }
@@ -194,7 +195,7 @@ struct EntryPointCleaner {
 }
 
 impl fold::Folder for EntryPointCleaner {
-    fn fold_item(&mut self, i: P<ast::Item>) -> SmallVector<P<ast::Item>> {
+    fn fold_item(&mut self, i: P<ast::Item>) -> OneVector<P<ast::Item>> {
         self.depth += 1;
         let folded = fold::noop_fold_item(i, self).expect_one("noop did something");
         self.depth -= 1;
@@ -234,7 +235,7 @@ impl fold::Folder for EntryPointCleaner {
             EntryPointType::OtherMain => folded,
         };
 
-        SmallVector::one(folded)
+        OneVector::one(folded)
     }
 
     fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac }
@@ -631,7 +632,7 @@ fn path_name_i(idents: &[Ident]) -> String {
     let mut idents_iter = idents.iter().peekable();
     while let Some(ident) = idents_iter.next() {
         path_name.push_str(&ident.as_str());
-        if let Some(_) = idents_iter.peek() {
+        if idents_iter.peek().is_some() {
             path_name.push_str("::")
         }
     }
@@ -675,10 +676,10 @@ fn mk_test_descs(cx: &TestCtxt) -> P<ast::Expr> {
                     mk_test_desc_and_fn_rec(cx, test)
                 }).collect()),
                 span: DUMMY_SP,
-                attrs: ast::ThinVec::new(),
+                attrs: ThinVec::new(),
             })),
         span: DUMMY_SP,
-        attrs: ast::ThinVec::new(),
+        attrs: ThinVec::new(),
     })
 }
 
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index f84b5307a1137..fda975e6c456b 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -186,21 +186,43 @@ impl TokenStream {
     /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
     /// separating the two arguments with a comma for diagnostic suggestions.
     pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> {
-        // Used to suggest if a user writes `println!("{}" a);`
+        // Used to suggest if a user writes `foo!(a b);`
         if let TokenStreamKind::Stream(ref slice) = self.kind {
-            if slice.len() == 2 {
-                let comma_span = match slice[0] {
-                    TokenStream { kind: TokenStreamKind::Tree(TokenTree::Token(sp, _)) } |
-                    TokenStream { kind: TokenStreamKind::Tree(TokenTree::Delimited(sp, _)) } => {
-                        sp.shrink_to_hi()
+            let mut suggestion = None;
+            let mut iter = slice.iter().enumerate().peekable();
+            while let Some((pos, ts)) = iter.next() {
+                if let Some((_, next)) = iter.peek() {
+                    match (ts, next) {
+                        (TokenStream {
+                            kind: TokenStreamKind::Tree(TokenTree::Token(_, token::Token::Comma))
+                        }, _) |
+                        (_, TokenStream {
+                            kind: TokenStreamKind::Tree(TokenTree::Token(_, token::Token::Comma))
+                        }) => {}
+                        (TokenStream {
+                            kind: TokenStreamKind::Tree(TokenTree::Token(sp, _))
+                        }, _) |
+                        (TokenStream {
+                            kind: TokenStreamKind::Tree(TokenTree::Delimited(sp, _))
+                        }, _) => {
+                            let sp = sp.shrink_to_hi();
+                            let comma = TokenStream {
+                                kind: TokenStreamKind::Tree(TokenTree::Token(sp, token::Comma)),
+                            };
+                            suggestion = Some((pos, comma, sp));
+                        }
+                        _ => {}
                     }
-                    _ => DUMMY_SP,
-                };
-                let comma = TokenStream {
-                    kind: TokenStreamKind::Tree(TokenTree::Token(comma_span, token::Comma)),
-                };
-                let slice = RcSlice::new(vec![slice[0].clone(), comma, slice[1].clone()]);
-                return Some((TokenStream { kind: TokenStreamKind::Stream(slice) }, comma_span));
+                }
+            }
+            if let Some((pos, comma, sp)) = suggestion {
+                let mut new_slice = vec![];
+                let parts = slice.split_at(pos + 1);
+                new_slice.extend_from_slice(parts.0);
+                new_slice.push(comma);
+                new_slice.extend_from_slice(parts.1);
+                let slice = RcSlice::new(new_slice);
+                return Some((TokenStream { kind: TokenStreamKind::Stream(slice) }, sp));
             }
         }
         None
diff --git a/src/libsyntax/util/move_map.rs b/src/libsyntax/util/move_map.rs
index 8cc37afa354ff..eb2c5a2458c15 100644
--- a/src/libsyntax/util/move_map.rs
+++ b/src/libsyntax/util/move_map.rs
@@ -9,8 +9,7 @@
 // except according to those terms.
 
 use std::ptr;
-
-use util::small_vector::SmallVector;
+use OneVector;
 
 pub trait MoveMap<T>: Sized {
     fn move_map<F>(self, mut f: F) -> Self where F: FnMut(T) -> T {
@@ -78,7 +77,7 @@ impl<T> MoveMap<T> for ::ptr::P<[T]> {
     }
 }
 
-impl<T> MoveMap<T> for SmallVector<T> {
+impl<T> MoveMap<T> for OneVector<T> {
     fn move_flat_map<F, I>(mut self, mut f: F) -> Self
         where F: FnMut(T) -> I,
               I: IntoIterator<Item=T>
diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs
deleted file mode 100644
index 31e675836fc72..0000000000000
--- a/src/libsyntax/util/small_vector.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use rustc_data_structures::small_vec::SmallVec;
-
-pub type SmallVector<T> = SmallVec<[T; 1]>;
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn test_len() {
-        let v: SmallVector<isize> = SmallVector::new();
-        assert_eq!(0, v.len());
-
-        assert_eq!(1, SmallVector::one(1).len());
-        assert_eq!(5, SmallVector::many(vec![1, 2, 3, 4, 5]).len());
-    }
-
-    #[test]
-    fn test_push_get() {
-        let mut v = SmallVector::new();
-        v.push(1);
-        assert_eq!(1, v.len());
-        assert_eq!(1, v[0]);
-        v.push(2);
-        assert_eq!(2, v.len());
-        assert_eq!(2, v[1]);
-        v.push(3);
-        assert_eq!(3, v.len());
-        assert_eq!(3, v[2]);
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let v: SmallVector<isize> = (vec![1, 2, 3]).into_iter().collect();
-        assert_eq!(3, v.len());
-        assert_eq!(1, v[0]);
-        assert_eq!(2, v[1]);
-        assert_eq!(3, v[2]);
-    }
-
-    #[test]
-    fn test_move_iter() {
-        let v = SmallVector::new();
-        let v: Vec<isize> = v.into_iter().collect();
-        assert_eq!(v, Vec::new());
-
-        let v = SmallVector::one(1);
-        assert_eq!(v.into_iter().collect::<Vec<_>>(), [1]);
-
-        let v = SmallVector::many(vec![1, 2, 3]);
-        assert_eq!(v.into_iter().collect::<Vec<_>>(), [1, 2, 3]);
-    }
-
-    #[test]
-    #[should_panic]
-    fn test_expect_one_zero() {
-        let _: isize = SmallVector::new().expect_one("");
-    }
-
-    #[test]
-    #[should_panic]
-    fn test_expect_one_many() {
-        SmallVector::many(vec![1, 2]).expect_one("");
-    }
-
-    #[test]
-    fn test_expect_one_one() {
-        assert_eq!(1, SmallVector::one(1).expect_one(""));
-        assert_eq!(1, SmallVector::many(vec![1]).expect_one(""));
-    }
-}
diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index 4ebb1fcb65393..026ddccd7be97 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -12,6 +12,8 @@
 //
 use self::State::*;
 
+use rustc_data_structures::thin_vec::ThinVec;
+
 use syntax::ast;
 use syntax::ext::base;
 use syntax::ext::base::*;
@@ -263,6 +265,6 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
             ctxt: cx.backtrace(),
         })),
         span: sp,
-        attrs: ast::ThinVec::new(),
+        attrs: ThinVec::new(),
     }))
 }
diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs
index a3c5c3df66e4c..c8cc11e43545a 100644
--- a/src/libsyntax_ext/concat_idents.rs
+++ b/src/libsyntax_ext/concat_idents.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc_data_structures::thin_vec::ThinVec;
+
 use syntax::ast;
 use syntax::ext::base::*;
 use syntax::ext::base;
@@ -68,7 +70,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
                 id: ast::DUMMY_NODE_ID,
                 node: ast::ExprKind::Path(None, ast::Path::from_ident(self.ident)),
                 span: self.ident.span,
-                attrs: ast::ThinVec::new(),
+                attrs: ThinVec::new(),
             }))
         }
 
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index c2a7dea331673..df9c351ef1c95 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -12,6 +12,8 @@ use deriving::path_std;
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
+use rustc_data_structures::thin_vec::ThinVec;
+
 use syntax::ast::{self, Ident};
 use syntax::ast::{Expr, MetaItem};
 use syntax::ext::base::{Annotatable, ExtCtxt};
@@ -139,7 +141,7 @@ fn stmt_let_undescore(cx: &mut ExtCtxt, sp: Span, expr: P<ast::Expr>) -> ast::St
         init: Some(expr),
         id: ast::DUMMY_NODE_ID,
         span: sp,
-        attrs: ast::ThinVec::new(),
+        attrs: ThinVec::new(),
     });
     ast::Stmt {
         id: ast::DUMMY_NODE_ID,
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index e0f985c26c7a1..41759c375b8ee 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -191,6 +191,7 @@ use std::cell::RefCell;
 use std::iter;
 use std::vec;
 
+use rustc_data_structures::thin_vec::ThinVec;
 use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
 use syntax::ast::{VariantData, GenericParamKind, GenericArg};
@@ -1624,7 +1625,7 @@ impl<'a> TraitDef<'a> {
                                 ident: ident.unwrap(),
                                 pat,
                                 is_shorthand: false,
-                                attrs: ast::ThinVec::new(),
+                                attrs: ThinVec::new(),
                             },
                         }
                     })
diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs
index 3c34bf496da59..8f26b2402aadf 100644
--- a/src/libsyntax_ext/env.rs
+++ b/src/libsyntax_ext/env.rs
@@ -81,7 +81,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt,
         }
     };
 
-    if let Some(_) = exprs.next() {
+    if exprs.next().is_some() {
         cx.span_err(sp, "env! takes 1 or 2 arguments");
         return DummyResult::expr(sp);
     }
diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs
index 40ecd6e1519c3..7290b701e4dec 100644
--- a/src/libsyntax_ext/global_asm.rs
+++ b/src/libsyntax_ext/global_asm.rs
@@ -18,6 +18,8 @@
 /// LLVM's `module asm "some assembly here"`. All of LLVM's caveats
 /// therefore apply.
 
+use rustc_data_structures::small_vec::OneVector;
+
 use syntax::ast;
 use syntax::codemap::respan;
 use syntax::ext::base;
@@ -28,8 +30,6 @@ use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use syntax::tokenstream;
 
-use syntax::util::small_vector::SmallVector;
-
 pub const MACRO: &'static str = "global_asm";
 
 pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
@@ -52,7 +52,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
         None => return DummyResult::any(sp),
     };
 
-    MacEager::items(SmallVector::one(P(ast::Item {
+    MacEager::items(OneVector::one(P(ast::Item {
         ident: ast::Ident::with_empty_ctxt(Symbol::intern("")),
         attrs: Vec::new(),
         id: ast::DUMMY_NODE_ID,
diff --git a/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs b/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs
index f2e6d51d064d1..7aa02558446e3 100644
--- a/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs
+++ b/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs
@@ -19,5 +19,5 @@ static FOO: u8 = 3;
 fn assert_static(_t: &'static u8) {}
 fn main() {
      assert_static(&FOO); //[ast]~ ERROR [E0597]
-                          //[mir]~^ ERROR [E0597]
+                          //[mir]~^ ERROR [E0712]
 }
diff --git a/src/test/debuginfo/by-value-non-immediate-argument.rs b/src/test/debuginfo/by-value-non-immediate-argument.rs
index 9007b44296bcc..0fe08c3a22731 100644
--- a/src/test/debuginfo/by-value-non-immediate-argument.rs
+++ b/src/test/debuginfo/by-value-non-immediate-argument.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 
 // compile-flags:-g
diff --git a/src/test/debuginfo/drop-locations.rs b/src/test/debuginfo/drop-locations.rs
index 76c2826ee8c61..845af6a60bc30 100644
--- a/src/test/debuginfo/drop-locations.rs
+++ b/src/test/debuginfo/drop-locations.rs
@@ -10,13 +10,11 @@
 
 // ignore-windows
 // ignore-android
-// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 
 #![allow(unused)]
 
-// compile-flags:-g -O -C no-prepopulate-passes
-// -O -C no-prepopulate-passes added to work around https://bugs.llvm.org/show_bug.cgi?id=32123
+// compile-flags:-g
 
 // This test checks that drop glue code gets attributed to scope's closing brace,
 // and function epilogues - to function's closing brace.
@@ -90,4 +88,5 @@ fn foo() {
 
 } // #loc4
 
+#[inline(never)]
 fn zzz() {()}
diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs
index 90088a0297aa8..06acfec88aaec 100644
--- a/src/test/debuginfo/function-arg-initialization.rs
+++ b/src/test/debuginfo/function-arg-initialization.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 
 // This test case checks if function arguments already have the correct value
diff --git a/src/test/debuginfo/function-prologue-stepping-regular.rs b/src/test/debuginfo/function-prologue-stepping-regular.rs
index d50d105e009ff..529a8cd635a92 100644
--- a/src/test/debuginfo/function-prologue-stepping-regular.rs
+++ b/src/test/debuginfo/function-prologue-stepping-regular.rs
@@ -13,7 +13,6 @@
 
 // min-lldb-version: 310
 // ignore-gdb
-// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // compile-flags:-g
 
 // lldb-command:breakpoint set --name immediate_args
diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs
index 7bc566480e763..d26e7b8a4c81b 100644
--- a/src/test/debuginfo/pretty-std.rs
+++ b/src/test/debuginfo/pretty-std.rs
@@ -10,7 +10,6 @@
 
 // ignore-windows failing on win32 bot
 // ignore-freebsd: gdb package too new
-// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
 // min-gdb-version 7.7
@@ -40,14 +39,15 @@
 // gdbr-check:$6 = core::option::Option::None
 
 // gdb-command: print os_string
-// gdb-check:$7 = "IAMA OS string 😃"
+// gdb-check:$7 = "IAMA OS string"
 
-// gdb-command: print some_string
-// gdb-check:$8 = Some = {"IAMA optional string!"}
+// Disabled due to https://github.com/rust-lang/rust/issues/53153
+// g d b-command: print some_string
+// g d b-check:$8 = Some = {"IAMA optional string!"}
 
-// gdb-command: set print length 5
-// gdb-command: print some_string
-// gdb-check:$8 = Some = {"IAMA "...}
+// g d b-command: set print length 5
+// g d b-command: print some_string
+// g d b-check:$8 = Some = {"IAMA "...}
 
 
 // === LLDB TESTS ==================================================================================
@@ -92,7 +92,7 @@ fn main() {
     let string = "IAMA string!".to_string();
 
     // OsString
-    let os_string = OsString::from("IAMA OS string \u{1F603}");
+    let os_string = OsString::from("IAMA OS string");
 
     // Option
     let some = Some(8i16);
diff --git a/src/test/run-pass-fulldeps/auxiliary/issue-16723.rs b/src/test/run-pass-fulldeps/auxiliary/issue-16723.rs
index 7f8a741465b30..ff5d9a59bfa00 100644
--- a/src/test/run-pass-fulldeps/auxiliary/issue-16723.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/issue-16723.rs
@@ -15,12 +15,12 @@
 
 extern crate syntax;
 extern crate rustc;
+extern crate rustc_data_structures;
 extern crate rustc_plugin;
 extern crate syntax_pos;
 
-use syntax::ast;
+use rustc_data_structures::small_vec::OneVector;
 use syntax::ext::base::{ExtCtxt, MacResult, MacEager};
-use syntax::util::small_vector::SmallVector;
 use syntax::tokenstream;
 use rustc_plugin::Registry;
 
@@ -31,7 +31,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
 
 fn expand(cx: &mut ExtCtxt, _: syntax_pos::Span, _: &[tokenstream::TokenTree])
           -> Box<MacResult+'static> {
-    MacEager::items(SmallVector::many(vec![
+    MacEager::items(OneVector::many(vec![
         quote_item!(cx, struct Struct1;).unwrap(),
         quote_item!(cx, struct Struct2;).unwrap()
     ]))
diff --git a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
index bbd81e790b838..3da50f1696545 100644
--- a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
@@ -30,8 +30,10 @@
 
 #![feature(rustc_private)]
 
+extern crate rustc_data_structures;
 extern crate syntax;
 
+use rustc_data_structures::thin_vec::ThinVec;
 use syntax::ast::*;
 use syntax::codemap::{Spanned, DUMMY_SP, FileName};
 use syntax::codemap::FilePathMapping;
@@ -39,7 +41,6 @@ use syntax::fold::{self, Folder};
 use syntax::parse::{self, ParseSess};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::util::ThinVec;
 
 
 fn parse_expr(ps: &ParseSess, src: &str) -> P<Expr> {
diff --git a/src/test/ui/borrowck/borrowck-in-static.nll.stderr b/src/test/ui/borrowck/borrowck-in-static.nll.stderr
index 05a022a726cd9..45fa1764f7027 100644
--- a/src/test/ui/borrowck/borrowck-in-static.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-in-static.nll.stderr
@@ -1,6 +1,8 @@
 error[E0507]: cannot move out of captured variable in an `Fn` closure
   --> $DIR/borrowck-in-static.rs:15:17
    |
+LL |     let x = Box::new(0);
+   |         - captured outer variable
 LL |     Box::new(|| x) //~ ERROR cannot move out of captured outer variable
    |                 ^ cannot move out of captured variable in an `Fn` closure
 
diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr
index 07a9f374b2c39..0eb5fc8c32435 100644
--- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr
+++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr
@@ -1,6 +1,9 @@
 error[E0507]: cannot move out of captured variable in an `Fn` closure
   --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:21:9
    |
+LL |     let y = vec![format!("World")];
+   |         - captured outer variable
+LL |     call(|| {
 LL |         y.into_iter();
    |         ^ cannot move out of captured variable in an `Fn` closure
 
diff --git a/src/test/ui/issue-17954.ast.nll.stderr b/src/test/ui/issue-17954.ast.nll.stderr
deleted file mode 100644
index 5cab7ca9e7a3f..0000000000000
--- a/src/test/ui/issue-17954.ast.nll.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0597]: `FOO` does not live long enough
-  --> $DIR/issue-17954.rs:20:13
-   |
-LL |     let a = &FOO;
-   |             ^^^^ borrowed value does not live long enough
-...
-LL | }
-   | - `FOO` dropped here while still borrowed
-   |
-   = note: borrowed value must be valid for the static lifetime...
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issue-17954.mir.stderr b/src/test/ui/issue-17954.mir.stderr
deleted file mode 100644
index 5cab7ca9e7a3f..0000000000000
--- a/src/test/ui/issue-17954.mir.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0597]: `FOO` does not live long enough
-  --> $DIR/issue-17954.rs:20:13
-   |
-LL |     let a = &FOO;
-   |             ^^^^ borrowed value does not live long enough
-...
-LL | }
-   | - `FOO` dropped here while still borrowed
-   |
-   = note: borrowed value must be valid for the static lifetime...
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issue-17954.nll.stderr b/src/test/ui/issue-17954.nll.stderr
new file mode 100644
index 0000000000000..67a5e3eaec787
--- /dev/null
+++ b/src/test/ui/issue-17954.nll.stderr
@@ -0,0 +1,12 @@
+error[E0712]: thread-local variable borrowed past end of function
+  --> $DIR/issue-17954.rs:17:13
+   |
+LL |     let a = &FOO;
+   |             ^^^^ thread-local variables cannot be borrowed beyond the end of the function
+...
+LL | }
+   | - end of enclosing function is here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0712`.
diff --git a/src/test/ui/issue-17954.rs b/src/test/ui/issue-17954.rs
index b5e550e5be1c9..ce554a7254812 100644
--- a/src/test/ui/issue-17954.rs
+++ b/src/test/ui/issue-17954.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: ast mir
-//[mir]compile-flags: -Z borrowck=mir
-
 #![feature(thread_local)]
 
 #[thread_local]
@@ -18,16 +15,12 @@ static FOO: u8 = 3;
 
 fn main() {
     let a = &FOO;
-    //[mir]~^ ERROR `FOO` does not live long enough [E0597]
-    //[mir]~| does not live long enough
-    //[mir]~| NOTE borrowed value must be valid for the static lifetime
-    //[ast]~^^^^ ERROR borrowed value does not live long enough
-    //[ast]~| does not live long enough
-    //[ast]~| NOTE borrowed value must be valid for the static lifetime
+    //~^ ERROR borrowed value does not live long enough
+    //~| does not live long enough
+    //~| NOTE borrowed value must be valid for the static lifetime
 
     std::thread::spawn(move || {
         println!("{}", a);
     });
 }
-//[mir]~^ `FOO` dropped here while still borrowed
-//[ast]~^^ temporary value only lives until here
+//~^ NOTE temporary value only lives until here
diff --git a/src/test/ui/issue-17954.ast.stderr b/src/test/ui/issue-17954.stderr
similarity index 92%
rename from src/test/ui/issue-17954.ast.stderr
rename to src/test/ui/issue-17954.stderr
index 677d2cbfffc47..76858a9b097b2 100644
--- a/src/test/ui/issue-17954.ast.stderr
+++ b/src/test/ui/issue-17954.stderr
@@ -1,5 +1,5 @@
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/issue-17954.rs:20:14
+  --> $DIR/issue-17954.rs:17:14
    |
 LL |     let a = &FOO;
    |              ^^^ temporary value does not live long enough
diff --git a/src/test/ui/issue-4335.nll.stderr b/src/test/ui/issue-4335.nll.stderr
index 4ccd24fa45921..a9345e86f7248 100644
--- a/src/test/ui/issue-4335.nll.stderr
+++ b/src/test/ui/issue-4335.nll.stderr
@@ -1,6 +1,8 @@
 error[E0507]: cannot move out of captured variable in an `FnMut` closure
   --> $DIR/issue-4335.rs:16:20
    |
+LL | fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
+   |             - captured outer variable
 LL |     id(Box::new(|| *v))
    |                    ^^ cannot move out of captured variable in an `FnMut` closure
 
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr
index c5f3510fa0ed2..ad8b4edbf2db4 100644
--- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr
+++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr
@@ -4,14 +4,15 @@ warning: not reporting region error due to nll
 LL |     x.push(y); //~ ERROR explicit lifetime required
    |            ^
 
-error[E0282]: type annotations needed
-  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:20:9
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:17:5
    |
-LL | let x = baz;
-   |     -   ^^^ cannot infer type for `T`
-   |     |
-   |     consider giving `x` a type
+LL | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
+   |                                       - consider changing the type of `y` to `&'a T`
+...
+LL |     x.push(y); //~ ERROR explicit lifetime required
+   |     ^^^^^^^^^ lifetime `'a` required
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs
index 18a720f345d7f..cad0a3c6ac13d 100644
--- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs
+++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs
@@ -17,5 +17,4 @@ fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
     x.push(y); //~ ERROR explicit lifetime required
 }
 fn main() {
-let x = baz;
 }
diff --git a/src/test/ui/lint-ctypes.rs b/src/test/ui/lint-ctypes.rs
index 7f22dc8739e76..b8b1a675c5f6d 100644
--- a/src/test/ui/lint-ctypes.rs
+++ b/src/test/ui/lint-ctypes.rs
@@ -88,6 +88,13 @@ extern {
     pub fn good15(p: TransparentLifetime);
     pub fn good16(p: TransparentUnit<ZeroSize>);
     pub fn good17(p: TransparentCustomZst);
+    #[allow(improper_ctypes)]
+    pub fn good18(_: &String);
+}
+
+#[allow(improper_ctypes)]
+extern {
+    pub fn good19(_: &String);
 }
 
 #[cfg(not(target_arch = "wasm32"))]
diff --git a/src/test/ui/macros/missing-comma.rs b/src/test/ui/macros/missing-comma.rs
index ac82171a4e8cc..07e69b9619d1f 100644
--- a/src/test/ui/macros/missing-comma.rs
+++ b/src/test/ui/macros/missing-comma.rs
@@ -9,7 +9,11 @@
 // except according to those terms.
 
 macro_rules! foo {
-    ($a:ident, $b:ident) => ()
+    ($a:ident) => ();
+    ($a:ident, $b:ident) => ();
+    ($a:ident, $b:ident, $c:ident) => ();
+    ($a:ident, $b:ident, $c:ident, $d:ident) => ();
+    ($a:ident, $b:ident, $c:ident, $d:ident, $e:ident) => ();
 }
 
 fn main() {
@@ -17,4 +21,10 @@ fn main() {
     //~^ ERROR expected token: `,`
     foo!(a b);
     //~^ ERROR no rules expected the token `b`
+    foo!(a, b, c, d e);
+    //~^ ERROR no rules expected the token `e`
+    foo!(a, b, c d, e);
+    //~^ ERROR no rules expected the token `d`
+    foo!(a, b, c d e);
+    //~^ ERROR no rules expected the token `d`
 }
diff --git a/src/test/ui/macros/missing-comma.stderr b/src/test/ui/macros/missing-comma.stderr
index 3467032d9b5f3..9d8de87e5bb7f 100644
--- a/src/test/ui/macros/missing-comma.stderr
+++ b/src/test/ui/macros/missing-comma.stderr
@@ -1,16 +1,38 @@
 error: expected token: `,`
-  --> $DIR/missing-comma.rs:16:19
+  --> $DIR/missing-comma.rs:20:19
    |
 LL |     println!("{}" a);
    |                   ^
 
 error: no rules expected the token `b`
-  --> $DIR/missing-comma.rs:18:12
+  --> $DIR/missing-comma.rs:22:12
    |
 LL |     foo!(a b);
    |           -^
    |           |
    |           help: missing comma here
 
-error: aborting due to 2 previous errors
+error: no rules expected the token `e`
+  --> $DIR/missing-comma.rs:24:21
+   |
+LL |     foo!(a, b, c, d e);
+   |                    -^
+   |                    |
+   |                    help: missing comma here
+
+error: no rules expected the token `d`
+  --> $DIR/missing-comma.rs:26:18
+   |
+LL |     foo!(a, b, c d, e);
+   |                 -^
+   |                 |
+   |                 help: missing comma here
+
+error: no rules expected the token `d`
+  --> $DIR/missing-comma.rs:28:18
+   |
+LL |     foo!(a, b, c d e);
+   |                  ^
+
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/nll/issue-52663-span-decl-captured-variable.rs b/src/test/ui/nll/issue-52663-span-decl-captured-variable.rs
new file mode 100644
index 0000000000000..dc40b0c44fd02
--- /dev/null
+++ b/src/test/ui/nll/issue-52663-span-decl-captured-variable.rs
@@ -0,0 +1,23 @@
+// Copyright 2017 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(nll)]
+
+fn expect_fn<F>(f: F) where F : Fn() {
+    f();
+}
+
+fn main() {
+   {
+       let x = (vec![22], vec![44]);
+       expect_fn(|| drop(x.0));
+       //~^ ERROR cannot move out of captured variable in an `Fn` closure [E0507]
+   }
+}
diff --git a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr
new file mode 100644
index 0000000000000..51f19565855a7
--- /dev/null
+++ b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr
@@ -0,0 +1,11 @@
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/issue-52663-span-decl-captured-variable.rs:20:26
+   |
+LL |        let x = (vec![22], vec![44]);
+   |            - captured outer variable
+LL |        expect_fn(|| drop(x.0));
+   |                          ^^^ cannot move out of captured variable in an `Fn` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
index c7dbc043cdaee..a05a3911aa771 100644
--- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
@@ -31,6 +31,9 @@ LL |     f.f.call_mut(())
 error[E0507]: cannot move out of captured variable in an `FnMut` closure
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13
    |
+LL |     let mut f = move |g: Box<FnMut(isize)>, b: isize| {
+   |         ----- captured outer variable
+...
 LL |         foo(f);
    |             ^ cannot move out of captured variable in an `FnMut` closure
 
diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs
index c2dc927c4b524..8a045884cae31 100644
--- a/src/test/ui/target-feature-gate.rs
+++ b/src/test/ui/target-feature-gate.rs
@@ -23,6 +23,7 @@
 // gate-test-hexagon_target_feature
 // gate-test-mips_target_feature
 // gate-test-mmx_target_feature
+// gate-test-wasm_target_feature
 // min-llvm-version 6.0
 
 #[target_feature(enable = "avx512bw")]