diff --git a/src/Cargo.lock b/src/Cargo.lock
index 8b7f3591a2505..94a07f6c91cfa 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -185,11 +185,11 @@ dependencies = [
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "crates-io 0.21.0",
- "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -539,6 +539,14 @@ name = "crossbeam-utils"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "crossbeam-utils"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "crypto-hash"
 version = "0.3.1"
@@ -662,6 +670,18 @@ dependencies = [
  "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "env_logger"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "environment"
 version = "0.1.1"
@@ -731,6 +751,7 @@ version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2170,7 +2191,6 @@ dependencies = [
  "graphviz 0.0.0",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3211,6 +3231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crossbeam-epoch 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c90f1474584f38e270b5b613e898c8c328aa4f3dea85e0a27ac2e642f009416"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
 "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
+"checksum crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c55913cc2799171a550e307918c0a360e8c16004820291bf3b638969b4a01816"
 "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
 "checksum curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c9d851c825e0c033979d4516c9173bc19a78a96eb4d6ae51d4045440eafa16"
 "checksum curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "721c204978be2143fab0a84b708c49d79d1f6100b8785610f456043a90708870"
@@ -3223,6 +3244,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4837d77a1e157489a3933b743fd774ae75074e0e390b2b7f071530048a0d87ee"
 "checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621"
 "checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257"
+"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
 "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index c8689f7814086..b6bb11d07ef04 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -22,7 +22,7 @@ use std::fs::{self, File};
 use std::io::BufReader;
 use std::io::prelude::*;
 use std::path::{Path, PathBuf};
-use std::process::{Command, Stdio};
+use std::process::{Command, Stdio, exit};
 use std::str;
 
 use build_helper::{output, mtime, up_to_date};
@@ -1098,7 +1098,7 @@ pub fn run_cargo(builder: &Builder,
     });
 
     if !ok {
-        panic!("cargo must succeed");
+        exit(1);
     }
 
     // Ok now we need to actually find all the files listed in `toplevel`. We've
diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py
index e6d5ef1a23ff7..a5c8e73f919ed 100755
--- a/src/etc/gdb_rust_pretty_printing.py
+++ b/src/etc/gdb_rust_pretty_printing.py
@@ -18,6 +18,8 @@
 if sys.version_info[0] >= 3:
     xrange = range
 
+rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string = True)
+
 #===============================================================================
 # GDB Pretty Printing Module for Rust
 #===============================================================================
@@ -99,27 +101,9 @@ def rust_pretty_printer_lookup_function(gdb_val):
     val = GdbValue(gdb_val)
     type_kind = val.type.get_type_kind()
 
-    if type_kind == rustpp.TYPE_KIND_EMPTY:
-        return RustEmptyPrinter(val)
-
-    if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT:
-        return RustStructPrinter(val,
-                                 omit_first_field = False,
-                                 omit_type_name = False,
-                                 is_tuple_like = False)
-
-    if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT:
-        return RustStructPrinter(val,
-                                 omit_first_field = True,
-                                 omit_type_name = False,
-                                 is_tuple_like = False)
-
     if type_kind == rustpp.TYPE_KIND_SLICE:
         return RustSlicePrinter(val)
 
-    if type_kind == rustpp.TYPE_KIND_STR_SLICE:
-        return RustStringSlicePrinter(val)
-
     if type_kind == rustpp.TYPE_KIND_STD_VEC:
         return RustStdVecPrinter(val)
 
@@ -138,6 +122,29 @@ def rust_pretty_printer_lookup_function(gdb_val):
     if type_kind == rustpp.TYPE_KIND_OS_STRING:
         return RustOsStringPrinter(val)
 
+    # Checks after this point should only be for "compiler" types --
+    # things that gdb's Rust language support knows about.
+    if rust_enabled:
+        return None
+
+    if type_kind == rustpp.TYPE_KIND_EMPTY:
+        return RustEmptyPrinter(val)
+
+    if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT:
+        return RustStructPrinter(val,
+                                 omit_first_field = False,
+                                 omit_type_name = False,
+                                 is_tuple_like = False)
+
+    if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT:
+        return RustStructPrinter(val,
+                                 omit_first_field = True,
+                                 omit_type_name = False,
+                                 is_tuple_like = False)
+
+    if type_kind == rustpp.TYPE_KIND_STR_SLICE:
+        return RustStringSlicePrinter(val)
+
     if type_kind == rustpp.TYPE_KIND_TUPLE:
         return RustStructPrinter(val,
                                  omit_first_field = False,
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 9cf42eff219ba..d8d51f53377f7 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -1509,7 +1509,9 @@ impl<T: ?Sized> UnsafeCell<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn get(&self) -> *mut T {
-        &self.value as *const T as *mut T
+        // We can just cast the pointer from `UnsafeCell<T>` to `T` because of
+        // #[repr(transparent)]
+        self as *const UnsafeCell<T> as *const T as *mut T
     }
 }
 
diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs
index ab96d3126bb22..0928f7560e175 100644
--- a/src/libcore/tests/num/mod.rs
+++ b/src/libcore/tests/num/mod.rs
@@ -82,36 +82,28 @@ fn from_str_issue7588() {
 
 #[test]
 fn test_int_from_str_overflow() {
-    let mut i8_val: i8 = 127;
-    assert_eq!("127".parse::<i8>().ok(), Some(i8_val));
+    assert_eq!("127".parse::<i8>().ok(), Some(127i8));
     assert_eq!("128".parse::<i8>().ok(), None);
 
-    i8_val = i8_val.wrapping_add(1);
-    assert_eq!("-128".parse::<i8>().ok(), Some(i8_val));
+    assert_eq!("-128".parse::<i8>().ok(), Some(-128i8));
     assert_eq!("-129".parse::<i8>().ok(), None);
 
-    let mut i16_val: i16 = 32_767;
-    assert_eq!("32767".parse::<i16>().ok(), Some(i16_val));
+    assert_eq!("32767".parse::<i16>().ok(), Some(32_767i16));
     assert_eq!("32768".parse::<i16>().ok(), None);
 
-    i16_val = i16_val.wrapping_add(1);
-    assert_eq!("-32768".parse::<i16>().ok(), Some(i16_val));
+    assert_eq!("-32768".parse::<i16>().ok(), Some(-32_768i16));
     assert_eq!("-32769".parse::<i16>().ok(), None);
 
-    let mut i32_val: i32 = 2_147_483_647;
-    assert_eq!("2147483647".parse::<i32>().ok(), Some(i32_val));
+    assert_eq!("2147483647".parse::<i32>().ok(), Some(2_147_483_647i32));
     assert_eq!("2147483648".parse::<i32>().ok(), None);
 
-    i32_val = i32_val.wrapping_add(1);
-    assert_eq!("-2147483648".parse::<i32>().ok(), Some(i32_val));
+    assert_eq!("-2147483648".parse::<i32>().ok(), Some(-2_147_483_648i32));
     assert_eq!("-2147483649".parse::<i32>().ok(), None);
 
-    let mut i64_val: i64 = 9_223_372_036_854_775_807;
-    assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(i64_val));
+    assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(9_223_372_036_854_775_807i64));
     assert_eq!("9223372036854775808".parse::<i64>().ok(), None);
 
-    i64_val = i64_val.wrapping_add(1);
-    assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(i64_val));
+    assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(-9_223_372_036_854_775_808i64));
     assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
 }
 
diff --git a/src/librustc/cfg/graphviz.rs b/src/librustc/cfg/graphviz.rs
index cc4f3f95d079a..650aa39114fad 100644
--- a/src/librustc/cfg/graphviz.rs
+++ b/src/librustc/cfg/graphviz.rs
@@ -106,8 +106,7 @@ impl<'a> dot::GraphWalk<'a> for &'a cfg::CFG {
     type Node = Node<'a>;
     type Edge = Edge<'a>;
     fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> {
-        let mut v = Vec::new();
-        self.graph.each_node(|i, nd| { v.push((i, nd)); true });
+        let v: Vec<_> = self.graph.enumerated_nodes().collect();
         v.into()
     }
     fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> {
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index e532b50a28b6b..ce1e678043188 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1062,8 +1062,7 @@ impl<'a> LoweringContext<'a> {
         attrs
             .iter()
             .map(|a| self.lower_attr(a))
-            .collect::<Vec<_>>()
-            .into()
+            .collect()
     }
 
     fn lower_attr(&mut self, attr: &Attribute) -> Attribute {
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index f3a62975dd9f4..928a6accf2d12 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -216,7 +216,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::adjustment::AutoBorrow
     }
 }
 
-impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
+impl_stable_hash_for!(struct ty::UpvarPath { hir_id });
+
+impl_stable_hash_for!(struct ty::UpvarId { var_path, closure_expr_id });
 
 impl_stable_hash_for!(enum ty::BorrowKind {
     ImmBorrow,
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index f833ebc7ca763..59a490f4a013d 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -1315,7 +1315,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 format!(" for lifetime parameter `{}` in coherence check", name)
             }
             infer::UpvarRegion(ref upvar_id, _) => {
-                let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id);
+                let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id);
                 let var_name = self.tcx.hir.name(var_node_id);
                 format!(" for capture of `{}` by closure", var_name)
             }
diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs
index 54d01a035a8be..a539c321af3f0 100644
--- a/src/librustc/infer/error_reporting/note.rs
+++ b/src/librustc/infer/error_reporting/note.rs
@@ -41,7 +41,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                               "...so that reference does not outlive borrowed content");
             }
             infer::ReborrowUpvar(span, ref upvar_id) => {
-                let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id);
+                let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id);
                 let var_name = self.tcx.hir.name(var_node_id);
                 err.span_note(span,
                               &format!("...so that closure can access `{}`", var_name));
@@ -174,7 +174,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 err
             }
             infer::ReborrowUpvar(span, ref upvar_id) => {
-                let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id);
+                let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id);
                 let var_name = self.tcx.hir.name(var_node_id);
                 let mut err = struct_span_err!(self.tcx.sess,
                                                span,
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 7e9b26bbf729c..5b92bfe6ad3c4 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -938,7 +938,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 let var_hir_id = self.tcx().hir.node_to_hir_id(freevar.var_id());
                 let closure_def_id = self.tcx().hir.local_def_id(closure_expr.id);
                 let upvar_id = ty::UpvarId {
-                    var_id: var_hir_id,
+                    var_path: ty::UpvarPath { hir_id: var_hir_id },
                     closure_expr_id: closure_def_id.to_local(),
                 };
                 let upvar_capture = self.mc.tables.upvar_capture(upvar_id);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 59ef8fa14484b..cadf0c42d228f 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -818,7 +818,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         let closure_expr_def_id = self.tcx.hir.local_def_id(fn_node_id);
         let var_hir_id = self.tcx.hir.node_to_hir_id(var_id);
         let upvar_id = ty::UpvarId {
-            var_id: var_hir_id,
+            var_path: ty::UpvarPath { hir_id: var_hir_id },
             closure_expr_id: closure_expr_def_id.to_local(),
         };
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index cdfe8f53b854b..923d362c2345f 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -789,7 +789,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
             pat_adjustments.hash_stable(hcx, hasher);
             hash_stable_hashmap(hcx, hasher, upvar_capture_map, |up_var_id, hcx| {
                 let ty::UpvarId {
-                    var_id,
+                    var_path,
                     closure_expr_id
                 } = *up_var_id;
 
@@ -798,14 +798,14 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
 
                 let var_owner_def_id = DefId {
                     krate: local_id_root.krate,
-                    index: var_id.owner,
+                    index: var_path.hir_id.owner,
                 };
                 let closure_def_id = DefId {
                     krate: local_id_root.krate,
                     index: closure_expr_id.to_def_id().index,
                 };
                 (hcx.def_path_hash(var_owner_def_id),
-                 var_id.local_id,
+                 var_path.hir_id.local_id,
                  hcx.def_path_hash(closure_def_id))
             });
 
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 79324bd97a3db..d7fb8da7acd05 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -697,7 +697,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                             Align::from_bytes(repr_align, repr_align).unwrap());
                     }
 
+                    let optimize = !def.repr.inhibit_union_abi_opt();
                     let mut size = Size::ZERO;
+                    let mut abi = Abi::Aggregate { sized: true };
                     let index = VariantIdx::new(0);
                     for field in &variants[index] {
                         assert!(!field.is_unsized());
@@ -708,13 +710,44 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                         } else {
                             align = align.max(field.align);
                         }
+
+                        // If all non-ZST fields have the same ABI, forward this ABI
+                        if optimize && !field.is_zst() {
+                            // Normalize scalar_unit to the maximal valid range
+                            let field_abi = match &field.abi {
+                                Abi::Scalar(x) => Abi::Scalar(scalar_unit(x.value)),
+                                Abi::ScalarPair(x, y) => {
+                                    Abi::ScalarPair(
+                                        scalar_unit(x.value),
+                                        scalar_unit(y.value),
+                                    )
+                                }
+                                Abi::Vector { element: x, count } => {
+                                    Abi::Vector {
+                                        element: scalar_unit(x.value),
+                                        count: *count,
+                                    }
+                                }
+                                Abi::Uninhabited |
+                                Abi::Aggregate { .. }  => Abi::Aggregate { sized: true },
+                            };
+
+                            if size == Size::ZERO {
+                                // first non ZST: initialize 'abi'
+                                abi = field_abi;
+                            } else if abi != field_abi  {
+                                // different fields have different ABI: reset to Aggregate
+                                abi = Abi::Aggregate { sized: true };
+                            }
+                        }
+
                         size = cmp::max(size, field.size);
                     }
 
                     return Ok(tcx.intern_layout(LayoutDetails {
                         variants: Variants::Single { index },
                         fields: FieldPlacement::Union(variants[index].len()),
-                        abi: Abi::Aggregate { sized: true },
+                        abi,
                         align,
                         size: size.abi_align(align)
                     }));
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 96f4b1ef8e32a..dfdffa2d54783 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -49,7 +49,6 @@ use std::hash::{Hash, Hasher};
 use std::ops::Deref;
 use rustc_data_structures::sync::{self, Lrc, ParallelIterator, par_iter};
 use std::slice;
-use std::vec::IntoIter;
 use std::{mem, ptr};
 use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
 use syntax::attr;
@@ -731,12 +730,17 @@ impl<T> List<T> {
     }
 }
 
+#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub struct UpvarPath {
+    pub hir_id: hir::HirId,
+}
+
 /// Upvars do not get their own node-id. Instead, we use the pair of
 /// the original var id (that is, the root variable that is referenced
 /// by the upvar) and the id of the closure expression.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct UpvarId {
-    pub var_id: hir::HirId,
+    pub var_path: UpvarPath,
     pub closure_expr_id: LocalDefId,
 }
 
@@ -1343,49 +1347,88 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
     }
 }
 
+// A custom iterator used by Predicate::walk_tys.
+enum WalkTysIter<'tcx, I, J, K>
+    where I: Iterator<Item = Ty<'tcx>>,
+          J: Iterator<Item = Ty<'tcx>>,
+          K: Iterator<Item = Ty<'tcx>>
+{
+    None,
+    One(Ty<'tcx>),
+    Two(Ty<'tcx>, Ty<'tcx>),
+    Types(I),
+    InputTypes(J),
+    ProjectionTypes(K)
+}
+
+impl<'tcx, I, J, K> Iterator for WalkTysIter<'tcx, I, J, K>
+    where I: Iterator<Item = Ty<'tcx>>,
+          J: Iterator<Item = Ty<'tcx>>,
+          K: Iterator<Item = Ty<'tcx>>
+{
+    type Item = Ty<'tcx>;
+
+    fn next(&mut self) -> Option<Ty<'tcx>> {
+        match *self {
+            WalkTysIter::None => None,
+            WalkTysIter::One(item) => {
+                *self = WalkTysIter::None;
+                Some(item)
+            },
+            WalkTysIter::Two(item1, item2) => {
+                *self = WalkTysIter::One(item2);
+                Some(item1)
+            },
+            WalkTysIter::Types(ref mut iter) => {
+                iter.next()
+            },
+            WalkTysIter::InputTypes(ref mut iter) => {
+                iter.next()
+            },
+            WalkTysIter::ProjectionTypes(ref mut iter) => {
+                iter.next()
+            }
+        }
+    }
+}
+
 impl<'tcx> Predicate<'tcx> {
     /// Iterates over the types in this predicate. Note that in all
     /// cases this is skipping over a binder, so late-bound regions
     /// with depth 0 are bound by the predicate.
-    pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> {
-        let vec: Vec<_> = match *self {
+    pub fn walk_tys(&'a self) -> impl Iterator<Item = Ty<'tcx>> + 'a {
+        match *self {
             ty::Predicate::Trait(ref data) => {
-                data.skip_binder().input_types().collect()
+                WalkTysIter::InputTypes(data.skip_binder().input_types())
             }
             ty::Predicate::Subtype(binder) => {
                 let SubtypePredicate { a, b, a_is_expected: _ } = binder.skip_binder();
-                vec![a, b]
+                WalkTysIter::Two(a, b)
             }
             ty::Predicate::TypeOutlives(binder) => {
-                vec![binder.skip_binder().0]
+                WalkTysIter::One(binder.skip_binder().0)
             }
             ty::Predicate::RegionOutlives(..) => {
-                vec![]
+                WalkTysIter::None
             }
             ty::Predicate::Projection(ref data) => {
                 let inner = data.skip_binder();
-                inner.projection_ty.substs.types().chain(Some(inner.ty)).collect()
+                WalkTysIter::ProjectionTypes(
+                    inner.projection_ty.substs.types().chain(Some(inner.ty)))
             }
             ty::Predicate::WellFormed(data) => {
-                vec![data]
+                WalkTysIter::One(data)
             }
             ty::Predicate::ObjectSafe(_trait_def_id) => {
-                vec![]
+                WalkTysIter::None
             }
             ty::Predicate::ClosureKind(_closure_def_id, closure_substs, _kind) => {
-                closure_substs.substs.types().collect()
+                WalkTysIter::Types(closure_substs.substs.types())
             }
             ty::Predicate::ConstEvaluatable(_, substs) => {
-                substs.types().collect()
+                WalkTysIter::Types(substs.types())
             }
-        };
-
-        // FIXME: The only reason to collect into a vector here is that I was
-        // too lazy to make the full (somewhat complicated) iterator
-        // type that would be needed here. But I wanted this fn to
-        // return an iterator conceptually, rather than a `Vec`, so as
-        // to be closer to `Ty::walk`.
-        vec.into_iter()
+        }
     }
 
     pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {
@@ -1998,6 +2041,12 @@ impl ReprOptions {
     pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
         !(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1)
     }
+
+    /// Returns true if this `#[repr()]` should inhibit union abi optimisations
+    pub fn inhibit_union_abi_opt(&self) -> bool {
+        self.c()
+    }
+
 }
 
 impl<'a, 'gcx, 'tcx> AdtDef {
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index 54550b8a2055f..7d3ae64f4fcd6 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -281,7 +281,7 @@ impl<'sess> OnDiskCache<'sess> {
                         // otherwise, abort
                         break;
                     }
-                    interpret_alloc_index.reserve(new_n);
+                    interpret_alloc_index.reserve(new_n - n);
                     for idx in n..new_n {
                         let id = encoder.interpret_allocs_inverse[idx];
                         let pos = encoder.position() as u32;
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index e44c0c05bb1a6..d53370d242bd9 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -678,8 +678,8 @@ impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
 impl fmt::Debug for ty::UpvarId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "UpvarId({:?};`{}`;{:?})",
-               self.var_id,
-               ty::tls::with(|tcx| tcx.hir.name(tcx.hir.hir_to_node_id(self.var_id))),
+               self.var_path.hir_id,
+               ty::tls::with(|tcx| tcx.hir.name(tcx.hir.hir_to_node_id(self.var_path.hir_id))),
                self.closure_expr_id)
     }
 }
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index 78a31ed668fca..21fb0cdf90ad1 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -453,8 +453,8 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
                     }
                     None
                 }
-                LpUpvar(ty::UpvarId{ var_id, closure_expr_id: _ }) => {
-                    self.bccx.used_mut_nodes.borrow_mut().insert(var_id);
+                LpUpvar(ty::UpvarId{ var_path: ty::UpvarPath { hir_id }, closure_expr_id: _ }) => {
+                    self.bccx.used_mut_nodes.borrow_mut().insert(hir_id);
                     None
                 }
                 LpExtend(ref base, mc::McInherited, LpDeref(pointer_kind)) |
diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
index e1a4473539c8c..cfd530b7e3d09 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
@@ -97,7 +97,7 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, errors: &[MoveErr
             }
         }
         if let NoteClosureEnv(upvar_id) = error.move_from.note {
-            let var_node_id = bccx.tcx.hir.hir_to_node_id(upvar_id.var_id);
+            let var_node_id = bccx.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id);
             err.span_label(bccx.tcx.hir.span(var_node_id),
                            "captured outer variable");
         }
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index d52d78181b77a..d189460d08848 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -846,7 +846,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                     MutabilityViolation => {
                         let mut db = self.cannot_assign(error_span, &descr, Origin::Ast);
                         if let mc::NoteClosureEnv(upvar_id) = err.cmt.note {
-                            let node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id);
+                            let node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id);
                             let sp = self.tcx.hir.span(node_id);
                             let fn_closure_msg = "`Fn` closures cannot capture their enclosing \
                                                   environment for modifications";
@@ -1415,7 +1415,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                                       loan_path: &LoanPath<'tcx>,
                                       out: &mut String) {
         match loan_path.kind {
-            LpUpvar(ty::UpvarId { var_id: id, closure_expr_id: _ }) => {
+            LpUpvar(ty::UpvarId { var_path: ty::UpvarPath { hir_id: id}, closure_expr_id: _ }) => {
                 out.push_str(&self.tcx.hir.name(self.tcx.hir.hir_to_node_id(id)).as_str());
             }
             LpVar(id) => {
@@ -1533,7 +1533,7 @@ impl<'tcx> fmt::Debug for LoanPath<'tcx> {
                 write!(f, "$({})", ty::tls::with(|tcx| tcx.hir.node_to_string(id)))
             }
 
-            LpUpvar(ty::UpvarId{ var_id, closure_expr_id }) => {
+            LpUpvar(ty::UpvarId{ var_path: ty::UpvarPath {hir_id: var_id}, closure_expr_id }) => {
                 let s = ty::tls::with(|tcx| {
                     let var_node_id = tcx.hir.hir_to_node_id(var_id);
                     tcx.hir.node_to_string(var_node_id)
@@ -1568,9 +1568,9 @@ impl<'tcx> fmt::Display for LoanPath<'tcx> {
                 write!(f, "$({})", ty::tls::with(|tcx| tcx.hir.node_to_user_string(id)))
             }
 
-            LpUpvar(ty::UpvarId{ var_id, closure_expr_id: _ }) => {
+            LpUpvar(ty::UpvarId{ var_path: ty::UpvarPath { hir_id }, closure_expr_id: _ }) => {
                 let s = ty::tls::with(|tcx| {
-                    let var_node_id = tcx.hir.hir_to_node_id(var_id);
+                    let var_node_id = tcx.hir.hir_to_node_id(hir_id);
                     tcx.hir.node_to_string(var_node_id)
                 });
                 write!(f, "$({} captured by closure)", s)
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 10820007629ff..79f073d643ddc 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -16,7 +16,6 @@ serialize = { path = "../libserialize" }
 graphviz = { path = "../libgraphviz" }
 cfg-if = "0.1.2"
 stable_deref_trait = "1.0.0"
-parking_lot_core = "0.2.8"
 rustc-rayon = "0.1.1"
 rustc-rayon-core = "0.1.1"
 rustc-hash = "1.0.1"
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index a01f8940a948a..0aa1924c0e59c 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -664,7 +664,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
             let var_hir_id = tcx.hir.node_to_hir_id(var_id);
             let closure_expr_id = tcx.hir.local_def_id(fn_id);
             let capture = hir.tables().upvar_capture(ty::UpvarId {
-                var_id: var_hir_id,
+                var_path: ty::UpvarPath {hir_id: var_hir_id},
                 closure_expr_id: LocalDefId::from_def_id(closure_expr_id),
             });
             let by_ref = match capture {
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 656a467fb4912..2e9edf20c5708 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -1061,7 +1061,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             // ...but the upvar might be an `&T` or `&mut T` capture, at which
             // point we need an implicit deref
             let upvar_id = ty::UpvarId {
-                var_id: var_hir_id,
+                var_path: ty::UpvarPath {hir_id: var_hir_id},
                 closure_expr_id: LocalDefId::from_def_id(closure_def_id),
             };
             match cx.tables().upvar_capture(upvar_id) {
@@ -1178,7 +1178,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                    -> ExprRef<'tcx> {
     let var_hir_id = cx.tcx.hir.node_to_hir_id(freevar.var_id());
     let upvar_id = ty::UpvarId {
-        var_id: var_hir_id,
+        var_path: ty::UpvarPath { hir_id: var_hir_id },
         closure_expr_id: cx.tcx.hir.local_def_id(closure_expr.id).to_local(),
     };
     let upvar_capture = cx.tables().upvar_capture(upvar_id);
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 118539fc58ebf..7d636b77ced4c 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -44,16 +44,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
             }
 
             Misc => {
+                let src_layout = src.layout;
                 let src = self.read_immediate(src)?;
 
-                if self.type_is_fat_ptr(src.layout.ty) {
-                    match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
+                // There are no casts to references
+                assert!(!dest.layout.ty.is_region_ptr());
+                // Hence we make all casts erase the tag
+                let src = src.erase_tag().with_default_tag();
+
+                if self.type_is_fat_ptr(src_layout.ty) {
+                    match (src, self.type_is_fat_ptr(dest.layout.ty)) {
                         // pointers to extern types
                         (Immediate::Scalar(_),_) |
                         // slices and trait objects to other slices/trait objects
                         (Immediate::ScalarPair(..), true) => {
                             // No change to immediate
-                            self.write_immediate(*src, dest)?;
+                            self.write_immediate(src, dest)?;
                         }
                         // slices and trait objects to thin pointers (dropping the metadata)
                         (Immediate::ScalarPair(data, _), false) => {
@@ -61,11 +67,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                         }
                     }
                 } else {
-                    match src.layout.variants {
+                    match src_layout.variants {
                         layout::Variants::Single { index } => {
-                            if let Some(def) = src.layout.ty.ty_adt_def() {
+                            if let Some(def) = src_layout.ty.ty_adt_def() {
                                 // Cast from a univariant enum
-                                assert!(src.layout.is_zst());
+                                assert!(src_layout.is_zst());
                                 let discr_val = def
                                     .discriminant_for_variant(*self.tcx, index)
                                     .val;
@@ -78,7 +84,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                         layout::Variants::NicheFilling { .. } => {},
                     }
 
-                    let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
+                    let dest_val = self.cast_scalar(src.to_scalar()?, src_layout, dest.layout)?;
                     self.write_scalar(dest_val, dest)?;
                 }
             }
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index e6267012dc275..ca09857bbd5ff 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -341,8 +341,21 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
                 // the last field).  Can't have foreign types here, how would we
                 // adjust alignment and size for them?
                 let field = layout.field(self, layout.fields.count() - 1)?;
-                let (unsized_size, unsized_align) = self.size_and_align_of(metadata, field)?
-                    .expect("Fields cannot be extern types");
+                let (unsized_size, unsized_align) = match self.size_and_align_of(metadata, field)? {
+                    Some(size_and_align) => size_and_align,
+                    None => {
+                        // A field with extern type.  If this field is at offset 0, we behave
+                        // like the underlying extern type.
+                        // FIXME: Once we have made decisions for how to handle size and alignment
+                        // of `extern type`, this should be adapted.  It is just a temporary hack
+                        // to get some code to work that probably ought to work.
+                        if sized_size == Size::ZERO {
+                            return Ok(None)
+                        } else {
+                            bug!("Fields cannot be extern types, unless they are at offset 0")
+                        }
+                    }
+                };
 
                 // FIXME (#26403, #27023): We should be adding padding
                 // to `sized_size` (to accommodate the `unsized_align`
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 82fe08fa038a4..96ea0d5094966 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -39,6 +39,6 @@ pub use self::machine::{Machine, AllocMap, MayLeak};
 
 pub use self::operand::{ScalarMaybeUndef, Immediate, ImmTy, Operand, OpTy};
 
-pub use self::visitor::ValueVisitor;
+pub use self::visitor::{ValueVisitor, MutValueVisitor};
 
 pub use self::validity::RefTracking;
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 201d320dcd858..fa76eeb2fedd5 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -351,8 +351,17 @@ where
         // Offset may need adjustment for unsized fields
         let (meta, offset) = if field_layout.is_unsized() {
             // re-use parent metadata to determine dynamic field layout
-            let (_, align) = self.size_and_align_of(base.meta, field_layout)?
-                .expect("Fields cannot be extern types");
+            let align = match self.size_and_align_of(base.meta, field_layout)? {
+                Some((_, align)) => align,
+                None if offset == Size::ZERO =>
+                    // An extern type at offset 0, we fall back to its static alignment.
+                    // FIXME: Once we have made decisions for how to handle size and alignment
+                    // of `extern type`, this should be adapted.  It is just a temporary hack
+                    // to get some code to work that probably ought to work.
+                    field_layout.align,
+                None =>
+                    bug!("Cannot compute offset for extern type field at non-0 offset"),
+            };
             (base.meta, offset.abi_align(align))
         } else {
             // base.meta could be present; we might be accessing a sized field of an unsized
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index 988ff7e75163d..e8fb06feb901c 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -21,7 +21,7 @@ use rustc::mir::interpret::{
 };
 
 use super::{
-    OpTy, MPlaceTy, ImmTy, Machine, EvalContext, ValueVisitor
+    OpTy, MPlaceTy, Machine, EvalContext, ValueVisitor
 };
 
 macro_rules! validation_failure {
@@ -281,8 +281,9 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
         }
     }
 
-    fn visit_primitive(&mut self, value: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
+    fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
     {
+        let value = self.ecx.read_immediate(value)?;
         // Go over all the primitive types
         let ty = value.layout.ty;
         match ty.sty {
diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs
index 4a47045643253..f0a71242599bf 100644
--- a/src/librustc_mir/interpret/visitor.rs
+++ b/src/librustc_mir/interpret/visitor.rs
@@ -8,7 +8,7 @@ use rustc::mir::interpret::{
 };
 
 use super::{
-    Machine, EvalContext, MPlaceTy, OpTy, ImmTy,
+    Machine, EvalContext, MPlaceTy, OpTy,
 };
 
 // A thing that we can project into, and that has a layout.
@@ -201,9 +201,11 @@ macro_rules! make_value_visitor {
             { Ok(()) }
 
             /// Called whenever we reach a value of primitive type.  There can be no recursion
-            /// below such a value.  This is the leave function.
+            /// below such a value.  This is the leaf function.
+            /// We do *not* provide an `ImmTy` here because some implementations might want
+            /// to write to the place this primitive lives in.
             #[inline(always)]
-            fn visit_primitive(&mut self, _val: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
+            fn visit_primitive(&mut self, _v: Self::V) -> EvalResult<'tcx>
             { Ok(()) }
 
             // Default recursors. Not meant to be overloaded.
@@ -279,9 +281,7 @@ macro_rules! make_value_visitor {
                     _ => v.layout().ty.builtin_deref(true).is_some(),
                 };
                 if primitive {
-                    let op = v.to_op(self.ecx())?;
-                    let val = self.ecx().read_immediate(op)?;
-                    return self.visit_primitive(val);
+                    return self.visit_primitive(v);
                 }
 
                 // Proceed into the fields.
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index df994ad9e55c4..312ce402775d2 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -45,14 +45,14 @@ use super::FnCtxt;
 use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
 use middle::mem_categorization::Categorization;
+use rustc::hir;
 use rustc::hir::def_id::DefId;
-use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
+use rustc::hir::def_id::LocalDefId;
+use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::infer::UpvarRegion;
+use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
 use syntax::ast;
 use syntax_pos::Span;
-use rustc::hir;
-use rustc::hir::def_id::LocalDefId;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     pub fn closure_analyze(&self, body: &'gcx hir::Body) {
@@ -121,7 +121,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             }
         };
 
-        let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs{
+        let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs {
             if self.closure_kind(closure_def_id, closure_substs).is_none() {
                 Some(closure_substs)
             } else {
@@ -134,7 +134,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         self.tcx.with_freevars(closure_node_id, |freevars| {
             for freevar in freevars {
                 let upvar_id = ty::UpvarId {
-                    var_id: self.tcx.hir.node_to_hir_id(freevar.var_id()),
+                    var_path: ty::UpvarPath {
+                        hir_id : self.tcx.hir.node_to_hir_id(freevar.var_id()),
+                    },
                     closure_expr_id: LocalDefId::from_def_id(closure_def_id),
                 };
                 debug!("seed upvar_id {:?}", upvar_id);
@@ -213,12 +215,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let final_upvar_tys = self.final_upvar_tys(closure_node_id);
         debug!(
             "analyze_closure: id={:?} substs={:?} final_upvar_tys={:?}",
-            closure_node_id,
-            substs,
-            final_upvar_tys
+            closure_node_id, substs, final_upvar_tys
         );
-        for (upvar_ty, final_upvar_ty) in substs.upvar_tys(closure_def_id, self.tcx)
-                                                .zip(final_upvar_tys)
+        for (upvar_ty, final_upvar_ty) in substs
+            .upvar_tys(closure_def_id, self.tcx)
+            .zip(final_upvar_tys)
         {
             self.demand_suptype(span, upvar_ty, final_upvar_ty);
         }
@@ -249,16 +250,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     let var_hir_id = tcx.hir.node_to_hir_id(var_node_id);
                     let freevar_ty = self.node_ty(var_hir_id);
                     let upvar_id = ty::UpvarId {
-                        var_id: var_hir_id,
+                        var_path: ty::UpvarPath {
+                            hir_id: var_hir_id,
+                        },
                         closure_expr_id: LocalDefId::from_def_id(closure_def_index),
                     };
                     let capture = self.tables.borrow().upvar_capture(upvar_id);
 
                     debug!(
                         "var_id={:?} freevar_ty={:?} capture={:?}",
-                        var_node_id,
-                        freevar_ty,
-                        capture
+                        var_node_id, freevar_ty, capture
                     );
 
                     match capture {
@@ -271,8 +272,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             },
                         ),
                     }
-                })
-                .collect()
+                }).collect()
         })
     }
 }
@@ -301,12 +301,14 @@ struct InferBorrowKind<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
 }
 
 impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
-    fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: &mc::cmt_<'tcx>,
-                                            mode: euv::ConsumeMode) {
+    fn adjust_upvar_borrow_kind_for_consume(
+        &mut self,
+        cmt: &mc::cmt_<'tcx>,
+        mode: euv::ConsumeMode,
+    ) {
         debug!(
             "adjust_upvar_borrow_kind_for_consume(cmt={:?}, mode={:?})",
-            cmt,
-            mode
+            cmt, mode
         );
 
         // we only care about moves
@@ -349,7 +351,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
                         upvar_id.closure_expr_id,
                         ty::ClosureKind::FnOnce,
                         guarantor.span,
-                        var_name(tcx, upvar_id.var_id),
+                        var_name(tcx, upvar_id.var_path.hir_id),
                     );
 
                     self.adjust_upvar_captures
@@ -366,7 +368,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
                         upvar_id.closure_expr_id,
                         ty::ClosureKind::FnOnce,
                         guarantor.span,
-                        var_name(tcx, upvar_id.var_id),
+                        var_name(tcx, upvar_id.var_path.hir_id),
                     );
                 }
                 mc::NoteIndex | mc::NoteNone => {}
@@ -381,9 +383,9 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
         debug!("adjust_upvar_borrow_kind_for_mut(cmt={:?})", cmt);
 
         match cmt.cat.clone() {
-            Categorization::Deref(base, mc::Unique) |
-            Categorization::Interior(base, _) |
-            Categorization::Downcast(base, _) => {
+            Categorization::Deref(base, mc::Unique)
+            | Categorization::Interior(base, _)
+            | Categorization::Downcast(base, _) => {
                 // Interior or owned data is mutable if base is
                 // mutable, so iterate to the base.
                 self.adjust_upvar_borrow_kind_for_mut(&base);
@@ -399,12 +401,12 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
                 }
             }
 
-            Categorization::Deref(_, mc::UnsafePtr(..)) |
-            Categorization::StaticItem |
-            Categorization::ThreadLocal(..) |
-            Categorization::Rvalue(..) |
-            Categorization::Local(_) |
-            Categorization::Upvar(..) => {
+            Categorization::Deref(_, mc::UnsafePtr(..))
+            | Categorization::StaticItem
+            | Categorization::ThreadLocal(..)
+            | Categorization::Rvalue(..)
+            | Categorization::Local(_)
+            | Categorization::Upvar(..) => {
                 return;
             }
         }
@@ -414,9 +416,9 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
         debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})", cmt);
 
         match cmt.cat.clone() {
-            Categorization::Deref(base, mc::Unique) |
-            Categorization::Interior(base, _) |
-            Categorization::Downcast(base, _) => {
+            Categorization::Deref(base, mc::Unique)
+            | Categorization::Interior(base, _)
+            | Categorization::Downcast(base, _) => {
                 // Interior or owned data is unique if base is
                 // unique.
                 self.adjust_upvar_borrow_kind_for_unique(&base);
@@ -430,18 +432,20 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
                 }
             }
 
-            Categorization::Deref(_, mc::UnsafePtr(..)) |
-            Categorization::StaticItem |
-            Categorization::ThreadLocal(..) |
-            Categorization::Rvalue(..) |
-            Categorization::Local(_) |
-            Categorization::Upvar(..) => {}
+            Categorization::Deref(_, mc::UnsafePtr(..))
+            | Categorization::StaticItem
+            | Categorization::ThreadLocal(..)
+            | Categorization::Rvalue(..)
+            | Categorization::Local(_)
+            | Categorization::Upvar(..) => {}
         }
     }
 
-    fn try_adjust_upvar_deref(&mut self, cmt: &mc::cmt_<'tcx>, borrow_kind: ty::BorrowKind)
-                              -> bool
-    {
+    fn try_adjust_upvar_deref(
+        &mut self,
+        cmt: &mc::cmt_<'tcx>,
+        borrow_kind: ty::BorrowKind,
+    ) -> bool {
         assert!(match borrow_kind {
             ty::MutBorrow => true,
             ty::UniqueImmBorrow => true,
@@ -465,7 +469,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
                     upvar_id.closure_expr_id,
                     ty::ClosureKind::FnMut,
                     cmt.span,
-                    var_name(tcx, upvar_id.var_id),
+                    var_name(tcx, upvar_id.var_path.hir_id),
                 );
 
                 true
@@ -478,7 +482,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
                     upvar_id.closure_expr_id,
                     ty::ClosureKind::FnMut,
                     cmt.span,
-                    var_name(tcx, upvar_id.var_id),
+                    var_name(tcx, upvar_id.var_path.hir_id),
                 );
 
                 true
@@ -493,15 +497,14 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
     /// Here the argument `mutbl` is the borrow_kind that is required by
     /// some particular use.
     fn adjust_upvar_borrow_kind(&mut self, upvar_id: ty::UpvarId, kind: ty::BorrowKind) {
-        let upvar_capture = self.adjust_upvar_captures
+        let upvar_capture = self
+            .adjust_upvar_captures
             .get(&upvar_id)
             .cloned()
             .unwrap_or_else(|| self.fcx.tables.borrow().upvar_capture(upvar_id));
         debug!(
             "adjust_upvar_borrow_kind(upvar_id={:?}, upvar_capture={:?}, kind={:?})",
-            upvar_id,
-            upvar_capture,
-            kind
+            upvar_id, upvar_capture, kind
         );
 
         match upvar_capture {
@@ -511,18 +514,18 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
             ty::UpvarCapture::ByRef(mut upvar_borrow) => {
                 match (upvar_borrow.kind, kind) {
                     // Take RHS:
-                    (ty::ImmBorrow, ty::UniqueImmBorrow) |
-                    (ty::ImmBorrow, ty::MutBorrow) |
-                    (ty::UniqueImmBorrow, ty::MutBorrow) => {
+                    (ty::ImmBorrow, ty::UniqueImmBorrow)
+                    | (ty::ImmBorrow, ty::MutBorrow)
+                    | (ty::UniqueImmBorrow, ty::MutBorrow) => {
                         upvar_borrow.kind = kind;
                         self.adjust_upvar_captures
                             .insert(upvar_id, ty::UpvarCapture::ByRef(upvar_borrow));
                     }
                     // Take LHS:
-                    (ty::ImmBorrow, ty::ImmBorrow) |
-                    (ty::UniqueImmBorrow, ty::ImmBorrow) |
-                    (ty::UniqueImmBorrow, ty::UniqueImmBorrow) |
-                    (ty::MutBorrow, _) => {}
+                    (ty::ImmBorrow, ty::ImmBorrow)
+                    | (ty::UniqueImmBorrow, ty::ImmBorrow)
+                    | (ty::UniqueImmBorrow, ty::UniqueImmBorrow)
+                    | (ty::MutBorrow, _) => {}
                 }
             }
         }
@@ -537,10 +540,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
     ) {
         debug!(
             "adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, var_name={})",
-            closure_id,
-            new_kind,
-            upvar_span,
-            var_name
+            closure_id, new_kind, upvar_span, var_name
         );
 
         // Is this the closure whose kind is currently being inferred?
@@ -554,22 +554,20 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
 
         debug!(
             "adjust_closure_kind: closure_id={:?}, existing_kind={:?}, new_kind={:?}",
-            closure_id,
-            existing_kind,
-            new_kind
+            closure_id, existing_kind, new_kind
         );
 
         match (existing_kind, new_kind) {
-            (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
-            (ty::ClosureKind::FnMut, ty::ClosureKind::Fn) |
-            (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
-            (ty::ClosureKind::FnOnce, _) => {
+            (ty::ClosureKind::Fn, ty::ClosureKind::Fn)
+            | (ty::ClosureKind::FnMut, ty::ClosureKind::Fn)
+            | (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut)
+            | (ty::ClosureKind::FnOnce, _) => {
                 // no change needed
             }
 
-            (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) |
-            (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
-            (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
+            (ty::ClosureKind::Fn, ty::ClosureKind::FnMut)
+            | (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce)
+            | (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
                 // new kind is stronger than the old kind
                 self.current_closure_kind = new_kind;
                 self.current_origin = Some((upvar_span, var_name));
@@ -590,12 +588,20 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> {
         self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
     }
 
-    fn matched_pat(&mut self, _matched_pat: &hir::Pat, _cmt: &mc::cmt_<'tcx>,
-                   _mode: euv::MatchMode) {
+    fn matched_pat(
+        &mut self,
+        _matched_pat: &hir::Pat,
+        _cmt: &mc::cmt_<'tcx>,
+        _mode: euv::MatchMode,
+    ) {
     }
 
-    fn consume_pat(&mut self, _consume_pat: &hir::Pat, cmt: &mc::cmt_<'tcx>,
-                   mode: euv::ConsumeMode) {
+    fn consume_pat(
+        &mut self,
+        _consume_pat: &hir::Pat,
+        cmt: &mc::cmt_<'tcx>,
+        mode: euv::ConsumeMode,
+    ) {
         debug!("consume_pat(cmt={:?},mode={:?})", cmt, mode);
         self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
     }
@@ -611,9 +617,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> {
     ) {
         debug!(
             "borrow(borrow_id={}, cmt={:?}, bk={:?})",
-            borrow_id,
-            cmt,
-            bk
+            borrow_id, cmt, bk
         );
 
         match bk {
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index d968bf222aa09..4460d5f64ce26 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -306,7 +306,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                 ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
                 ty::UpvarCapture::ByRef(ref upvar_borrow) => {
                     let r = upvar_borrow.region;
-                    let r = self.resolve(&r, &upvar_id.var_id);
+                    let r = self.resolve(&r, &upvar_id.var_path.hir_id);
                     ty::UpvarCapture::ByRef(ty::UpvarBorrow {
                         kind: upvar_borrow.kind,
                         region: r,
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 471ba6345e248..f3ded2a5376a6 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -527,7 +527,7 @@ fn resolution_failure(
                 doc_comment_padding +
                     // Each subsequent leading whitespace and `///`
                     code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| {
-                        sum + doc_comment_padding + line.len() - line.trim().len()
+                        sum + doc_comment_padding + line.len() - line.trim_start().len()
                     })
             };
 
diff --git a/src/libserialize/hex.rs b/src/libserialize/hex.rs
index 7f3736e82caa6..5604729d2f8dc 100644
--- a/src/libserialize/hex.rs
+++ b/src/libserialize/hex.rs
@@ -146,7 +146,7 @@ impl FromHex for str {
         }
 
         match modulus {
-            0 => Ok(b.into_iter().collect()),
+            0 => Ok(b),
             _ => Err(InvalidHexLength),
         }
     }
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 54bfd8122b4ed..ec9207ea45b4f 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -69,7 +69,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
 ///
 /// let (tx, rx) = channel();
 /// for _ in 0..N {
-///     let (data, tx) = (data.clone(), tx.clone());
+///     let (data, tx) = (Arc::clone(&data), tx.clone());
 ///     thread::spawn(move || {
 ///         // The shared state can only be accessed once the lock is held.
 ///         // Our non-atomic increment is safe because we're the only thread
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 90ab349159915..651c874583e69 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -481,7 +481,8 @@ mod tests {
             let (a, b) = ($a, $b);
             if a != b {
                 let (a, b) = if a > b {(a, b)} else {(b, a)};
-                assert!(a - Duration::new(0, 100) <= b);
+                assert!(a - Duration::new(0, 100) <= b,
+                        "{:?} is not almost equal to {:?}", a, b);
             }
         })
     }
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 2f6b306e8f8ba..a5b12ce4c4d83 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -1200,16 +1200,14 @@ impl<'a> MethodDef<'a> {
         let sp = trait_.span;
         let variants = &enum_def.variants;
 
-        let self_arg_names = self_args.iter()
-            .enumerate()
-            .map(|(arg_count, _self_arg)| {
-                if arg_count == 0 {
-                    "__self".to_string()
-                } else {
+        let self_arg_names = iter::once("__self".to_string()).chain(
+            self_args.iter()
+                .enumerate()
+                .skip(1)
+                .map(|(arg_count, _self_arg)|
                     format!("__arg_{}", arg_count)
-                }
-            })
-            .collect::<Vec<String>>();
+                )
+            ).collect::<Vec<String>>();
 
         let self_arg_idents = self_arg_names.iter()
             .map(|name| cx.ident_of(&name[..]))
@@ -1218,7 +1216,7 @@ impl<'a> MethodDef<'a> {
         // The `vi_idents` will be bound, solely in the catch-all, to
         // a series of let statements mapping each self_arg to an int
         // value corresponding to its discriminant.
-        let vi_idents: Vec<ast::Ident> = self_arg_names.iter()
+        let vi_idents = self_arg_names.iter()
             .map(|name| {
                 let vi_suffix = format!("{}_vi", &name[..]);
                 cx.ident_of(&vi_suffix[..]).gensym()
diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs
new file mode 100644
index 0000000000000..786968128ec1b
--- /dev/null
+++ b/src/test/codegen/union-abi.rs
@@ -0,0 +1,80 @@
+// 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.
+
+// compile-flags: -C no-prepopulate-passes
+
+// This test that using union forward the abi of the inner type, as
+// discussed in #54668
+
+#![crate_type="lib"]
+#![feature(repr_simd)]
+
+#[derive(Copy, Clone)]
+pub enum Unhab {}
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct i64x4(i64, i64, i64, i64);
+
+#[derive(Copy, Clone)]
+pub union UnionI64x4{ a:(), b: i64x4 }
+
+// CHECK: define void @test_UnionI64x4(<4 x i64>* {{.*}} %arg0)
+#[no_mangle]
+pub fn test_UnionI64x4(_: UnionI64x4) { loop {} }
+
+pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 }
+
+// CHECK: define void @test_UnionI64x4_(<4 x i64>* {{.*}} %arg0)
+#[no_mangle]
+pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} }
+
+pub union UnionI64x4I64{ a: i64x4, b: i64 }
+
+// CHECK: define void @test_UnionI64x4I64(%UnionI64x4I64* {{.*}} %arg0)
+#[no_mangle]
+pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} }
+
+pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) }
+
+// CHECK: define void @test_UnionI64x4Tuple(%UnionI64x4Tuple* {{.*}} %arg0)
+#[no_mangle]
+pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} }
+
+
+pub union UnionF32{a:f32}
+
+// CHECK: define float @test_UnionF32(float %arg0)
+#[no_mangle]
+pub fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
+
+pub union UnionF32F32{a:f32, b:f32}
+
+// CHECK: define float @test_UnionF32F32(float %arg0)
+#[no_mangle]
+pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} }
+
+pub union UnionF32U32{a:f32, b:u32}
+
+// CHECK: define i32 @test_UnionF32U32(i32)
+#[no_mangle]
+pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} }
+
+pub union UnionU128{a:u128}
+// CHECK: define i128 @test_UnionU128(i128 %arg0)
+#[no_mangle]
+pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} }
+
+#[repr(C)]
+pub union CUnionU128{a:u128}
+// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %arg0)
+#[no_mangle]
+pub fn test_CUnionU128(_: CUnionU128) { loop {} }
+
diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
similarity index 71%
rename from src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs
rename to src/test/debuginfo/gdb-pretty-struct-and-enums.rs
index 158a1f17fc03d..40dd42898f81d 100644
--- a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs
+++ b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
@@ -8,34 +8,33 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-bitrig
-// ignore-solaris
-// ignore-windows failing on win32 bot
-// ignore-freebsd: gdb package too new
 // ignore-tidy-linelength
 // ignore-lldb
-// ignore-android: FIXME(#10381)
+// min-gdb-version: 7.11
+
 // compile-flags:-g
 
 // gdb-command: run
 
 // gdb-command: print regular_struct
-// gdb-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false}
+// gdbg-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false}
+// gdbr-check:$1 = gdb_pretty_struct_and_enums::RegularStruct {the_first_field: 101, the_second_field: 102.5, the_third_field: false}
 
 // gdb-command: print empty_struct
-// gdb-check:$2 = EmptyStruct
+// gdbg-check:$2 = EmptyStruct
+// gdbr-check:$2 = gdb_pretty_struct_and_enums::EmptyStruct
 
 // gdb-command: print c_style_enum1
 // gdbg-check:$3 = CStyleEnumVar1
-// gdbr-check:$3 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar1
+// gdbr-check:$3 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar1
 
 // gdb-command: print c_style_enum2
 // gdbg-check:$4 = CStyleEnumVar2
-// gdbr-check:$4 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar2
+// gdbr-check:$4 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar2
 
 // gdb-command: print c_style_enum3
 // gdbg-check:$5 = CStyleEnumVar3
-// gdbr-check:$5 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar3
+// gdbr-check:$5 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar3
 
 #![allow(dead_code, unused_variables)]
 
diff --git a/src/test/run-pass-fulldeps/auxiliary/linkage-visibility.rs b/src/test/run-pass-fulldeps/auxiliary/linkage-visibility.rs
index 4ea3d0d0d0a07..2aaa28341ad91 100644
--- a/src/test/run-pass-fulldeps/auxiliary/linkage-visibility.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/linkage-visibility.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-musl - dlsym doesn't see symbols without "-C link-arg=-Wl,--export-dynamic"
+
 #![feature(rustc_private)]
 
 // We're testing linkage visibility; the compiler warns us, but we want to
diff --git a/src/test/run-pass/mpsc_stress.rs b/src/test/run-pass/mpsc_stress.rs
new file mode 100644
index 0000000000000..aa369bb17fead
--- /dev/null
+++ b/src/test/run-pass/mpsc_stress.rs
@@ -0,0 +1,172 @@
+// 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.
+
+// compile-flags:--test
+// ignore-emscripten
+
+use std::sync::mpsc::channel;
+use std::sync::mpsc::TryRecvError;
+use std::sync::mpsc::RecvError;
+use std::sync::mpsc::RecvTimeoutError;
+use std::sync::Arc;
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering;
+
+use std::thread;
+use std::time::Duration;
+
+
+/// Simple thread synchronization utility
+struct Barrier {
+    // Not using mutex/condvar for precision
+    shared: Arc<AtomicUsize>,
+    count: usize,
+}
+
+impl Barrier {
+    fn new(count: usize) -> Vec<Barrier> {
+        let shared = Arc::new(AtomicUsize::new(0));
+        (0..count).map(|_| Barrier { shared: shared.clone(), count: count }).collect()
+    }
+
+    fn new2() -> (Barrier, Barrier) {
+        let mut v = Barrier::new(2);
+        (v.pop().unwrap(), v.pop().unwrap())
+    }
+
+    /// Returns when `count` threads enter `wait`
+    fn wait(self) {
+        self.shared.fetch_add(1, Ordering::SeqCst);
+        while self.shared.load(Ordering::SeqCst) != self.count {
+        }
+    }
+}
+
+
+fn shared_close_sender_does_not_lose_messages_iter() {
+    let (tb, rb) = Barrier::new2();
+
+    let (tx, rx) = channel();
+    let _ = tx.clone(); // convert to shared
+
+    thread::spawn(move || {
+        tb.wait();
+        thread::sleep(Duration::from_micros(1));
+        tx.send(17).expect("send");
+        drop(tx);
+    });
+
+    let i = rx.into_iter();
+    rb.wait();
+    // Make sure it doesn't return disconnected before returning an element
+    assert_eq!(vec![17], i.collect::<Vec<_>>());
+}
+
+#[test]
+fn shared_close_sender_does_not_lose_messages() {
+    for _ in 0..10000 {
+        shared_close_sender_does_not_lose_messages_iter();
+    }
+}
+
+
+// https://github.com/rust-lang/rust/issues/39364
+fn concurrent_recv_timeout_and_upgrade_iter() {
+    // 1 us
+    let sleep = Duration::new(0, 1_000);
+
+    let (a, b) = Barrier::new2();
+    let (tx, rx) = channel();
+    let th = thread::spawn(move || {
+        a.wait();
+        loop {
+            match rx.recv_timeout(sleep) {
+                Ok(_) => {
+                    break;
+                },
+                Err(_) => {},
+            }
+        }
+    });
+    b.wait();
+    thread::sleep(sleep);
+    tx.clone().send(()).expect("send");
+    th.join().unwrap();
+}
+
+#[test]
+fn concurrent_recv_timeout_and_upgrade() {
+    // FIXME: fix and enable
+    if true { return }
+
+    // at the moment of writing this test fails like this:
+    // thread '<unnamed>' panicked at 'assertion failed: `(left == right)`
+    //  left: `4561387584`,
+    // right: `0`', libstd/sync/mpsc/shared.rs:253:13
+
+    for _ in 0..10000 {
+        concurrent_recv_timeout_and_upgrade_iter();
+    }
+}
+
+
+fn concurrent_writes_iter() {
+    const THREADS: usize = 4;
+    const PER_THR: usize = 100;
+
+    let mut bs = Barrier::new(THREADS + 1);
+    let (tx, rx) = channel();
+
+    let mut threads = Vec::new();
+    for j in 0..THREADS {
+        let tx = tx.clone();
+        let b = bs.pop().unwrap();
+        threads.push(thread::spawn(move || {
+            b.wait();
+            for i in 0..PER_THR {
+                tx.send(j * 1000 + i).expect("send");
+            }
+        }));
+    }
+
+    let b = bs.pop().unwrap();
+    b.wait();
+
+    let mut v: Vec<_> = rx.iter().take(THREADS * PER_THR).collect();
+    v.sort();
+
+    for j in 0..THREADS {
+        for i in 0..PER_THR {
+            assert_eq!(j * 1000 + i, v[j * PER_THR + i]);
+        }
+    }
+
+    for t in threads {
+        t.join().unwrap();
+    }
+
+    let one_us = Duration::new(0, 1000);
+
+    assert_eq!(TryRecvError::Empty, rx.try_recv().unwrap_err());
+    assert_eq!(RecvTimeoutError::Timeout, rx.recv_timeout(one_us).unwrap_err());
+
+    drop(tx);
+
+    assert_eq!(RecvError, rx.recv().unwrap_err());
+    assert_eq!(RecvTimeoutError::Disconnected, rx.recv_timeout(one_us).unwrap_err());
+    assert_eq!(TryRecvError::Disconnected, rx.try_recv().unwrap_err());
+}
+
+#[test]
+fn concurrent_writes() {
+    for _ in 0..100 {
+        concurrent_writes_iter();
+    }
+}
diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.rs b/src/test/rustdoc-ui/intra-link-span-ice-55723.rs
new file mode 100644
index 0000000000000..12e59a4813f85
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.rs
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-end-whitespace
+
+#![deny(intra_doc_link_resolution_failure)]
+
+// An error in calculating spans while reporting intra-doc link resolution errors caused rustdoc to
+// attempt to slice in the middle of a multibyte character. See
+// https://github.com/rust-lang/rust/issues/55723
+
+/// ## For example:
+///  
+/// (arr[i])
+pub fn test_ice() {
+    unimplemented!();
+}
diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr
new file mode 100644
index 0000000000000..7ae6af4a75e8c
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr
@@ -0,0 +1,13 @@
+error: `[i]` cannot be resolved, ignoring it...
+  --> $DIR/intra-link-span-ice-55723.rs:21:10
+   |
+LL | /// (arr[i])
+   |           ^ cannot be resolved, ignoring
+   |
+note: lint level defined here
+  --> $DIR/intra-link-span-ice-55723.rs:13:9
+   |
+LL | #![deny(intra_doc_link_resolution_failure)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
+
diff --git a/src/test/ui/consts/const-eval/issue-55541.rs b/src/test/ui/consts/const-eval/issue-55541.rs
new file mode 100644
index 0000000000000..611fb89341de4
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-55541.rs
@@ -0,0 +1,27 @@
+// compile-pass
+
+// Test that we can handle newtypes wrapping extern types
+
+#![feature(extern_types, const_transmute)]
+
+use std::marker::PhantomData;
+
+extern "C" {
+  pub type ExternType;
+}
+unsafe impl Sync for ExternType {}
+static MAGIC_FFI_STATIC: u8 = 42;
+
+#[repr(transparent)]
+pub struct Wrapper(ExternType);
+pub static MAGIC_FFI_REF: &'static Wrapper = unsafe {
+  std::mem::transmute(&MAGIC_FFI_STATIC)
+};
+
+#[repr(transparent)]
+pub struct Wrapper2(PhantomData<Vec<i32>>, ExternType);
+pub static MAGIC_FFI_REF2: &'static Wrapper2 = unsafe {
+  std::mem::transmute(&MAGIC_FFI_STATIC)
+};
+
+fn main() {}
diff --git a/src/tools/cargo b/src/tools/cargo
index 241fac0e39330..b3d0b2e545b61 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 241fac0e3933063fa48a1a01f5d577e40af12e4d
+Subproject commit b3d0b2e545b61d4cd08096911724b7d49d213f73
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 72c47273e63b5..2dfb9fc68ac16 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -92,6 +92,7 @@ const WHITELIST: &[Crate] = &[
     Crate("kernel32-sys"),
     Crate("lazy_static"),
     Crate("libc"),
+    Crate("libz-sys"),
     Crate("lock_api"),
     Crate("log"),
     Crate("log_settings"),
@@ -133,6 +134,7 @@ const WHITELIST: &[Crate] = &[
     Crate("utf8-ranges"),
     Crate("version_check"),
     Crate("void"),
+    Crate("vcpkg"),
     Crate("winapi"),
     Crate("winapi-build"),
     Crate("winapi-i686-pc-windows-gnu"),