about summary refs log tree commit diff
diff options
context:
space:
mode:
authormatthewjasper <mjjasper1@gmail.com>2017-04-22 17:55:59 +0100
committermatthewjasper <mjjasper1@gmail.com>2017-04-22 17:55:59 +0100
commit8a3ea01bcae85a3ed0c90ca5603cd88c469172c3 (patch)
tree291c7e740787ea95d87ac7a39f89a99d00b41c3c
parent5fc25224da78afcfdd76783c38ad3beff42a990c (diff)
parent6d841da4a0d7629f826117f99052e3d4a7997a7e (diff)
downloadrust-8a3ea01bcae85a3ed0c90ca5603cd88c469172c3.tar.gz
rust-8a3ea01bcae85a3ed0c90ca5603cd88c469172c3.zip
Resolve merge conflict
-rwxr-xr-xconfigure2
m---------rls0
-rw-r--r--src/bootstrap/compile.rs1
-rw-r--r--src/bootstrap/config.rs6
-rw-r--r--src/ci/docker/dist-android/Dockerfile6
-rw-r--r--src/ci/docker/dist-android/install-ndk.sh8
-rw-r--r--src/doc/unstable-book/src/SUMMARY.md2
-rw-r--r--src/doc/unstable-book/src/language-features/repr-align.md11
-rwxr-xr-xsrc/etc/rust-gdb5
-rw-r--r--src/libcollections/btree/set.rs12
-rw-r--r--src/libcollections/enum_set.rs3
-rw-r--r--src/libcollections/linked_list.rs11
-rw-r--r--src/libcollections/tests/vec.rs22
-rw-r--r--src/libcollections/vec.rs27
-rw-r--r--src/libcollections/vec_deque.rs14
-rw-r--r--src/libcore/convert.rs183
-rw-r--r--src/libcore/marker.rs17
m---------src/liblibc0
-rw-r--r--src/librustc/diagnostics.rs3
-rw-r--r--src/librustc/hir/check_attr.rs17
-rw-r--r--src/librustc/middle/lang_items.rs1
-rw-r--r--src/librustc/ty/contents.rs255
-rw-r--r--src/librustc/ty/context.rs4
-rw-r--r--src/librustc/ty/layout.rs89
-rw-r--r--src/librustc/ty/mod.rs57
-rw-r--r--src/librustc/ty/util.rs161
-rw-r--r--src/librustc_back/target/mod.rs1
-rw-r--r--src/librustc_back/target/x86_64_linux_android.rs34
-rw-r--r--src/librustc_borrowck/borrowck/mir/mod.rs2
-rw-r--r--src/librustc_errors/emitter.rs67
-rw-r--r--src/librustc_errors/snippet.rs22
-rw-r--r--src/librustc_lint/builtin.rs2
-rw-r--r--src/librustc_mir/hair/cx/mod.rs2
-rw-r--r--src/librustc_mir/transform/inline.rs2
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs4
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs3
-rw-r--r--src/librustc_passes/consts.rs6
-rw-r--r--src/librustc_trans/abi.rs8
-rw-r--r--src/librustc_trans/adt.rs91
-rw-r--r--src/librustc_trans/builder.rs12
-rw-r--r--src/librustc_trans/consts.rs3
-rw-r--r--src/librustc_trans/context.rs6
-rw-r--r--src/librustc_trans/intrinsic.rs2
-rw-r--r--src/librustc_trans/mir/block.rs12
-rw-r--r--src/librustc_trans/mir/lvalue.rs17
-rw-r--r--src/librustc_trans/mir/mod.rs2
-rw-r--r--src/librustc_trans/mir/operand.rs36
-rw-r--r--src/librustc_trans/mir/rvalue.rs16
-rw-r--r--src/librustc_trans/type_of.rs10
-rw-r--r--src/librustc_typeck/check/coercion.rs11
-rw-r--r--src/librustc_typeck/check/demand.rs89
-rw-r--r--src/librustc_typeck/check/mod.rs47
-rw-r--r--src/librustc_typeck/diagnostics.rs1
-rw-r--r--src/librustdoc/html/markdown.rs10
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/librustdoc/test.rs35
-rw-r--r--src/libstd/os/android/raw.rs63
-rw-r--r--src/libstd/path.rs17
-rw-r--r--src/libstd/process.rs20
-rw-r--r--src/libsyntax/attr.rs55
-rw-r--r--src/libsyntax/diagnostic_list.rs2
-rw-r--r--src/libsyntax/ext/expand.rs14
-rw-r--r--src/libsyntax/feature_gate.rs8
-rw-r--r--src/libsyntax/test_snippet.rs93
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs2
-rw-r--r--src/rtstartup/rsbegin.rs7
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/auxiliary/issue-41211.rs23
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/issue-41211.rs22
-rw-r--r--src/test/compile-fail/attr-usage-repr.rs4
-rw-r--r--src/test/compile-fail/coercion-slice.rs1
-rw-r--r--src/test/compile-fail/conflicting-repr-hints.rs9
-rw-r--r--src/test/compile-fail/cross-borrow-trait.rs2
-rw-r--r--src/test/compile-fail/feature-gate-repr_align.rs15
-rw-r--r--src/test/compile-fail/issue-11374.rs2
-rw-r--r--src/test/compile-fail/issue-13058.rs1
-rw-r--r--src/test/compile-fail/repr-align.rs23
-rw-r--r--src/test/compile-fail/repr-packed-contains-align.rs25
-rw-r--r--src/test/run-make/simd-ffi/simd.rs6
-rw-r--r--src/test/run-make/target-specs/foo.rs6
-rw-r--r--src/test/run-pass/align-struct.rs196
-rw-r--r--src/test/ui/compare-method/region-extra-2.stderr5
-rw-r--r--src/test/ui/compare-method/traits-misc-mismatch-2.stderr5
-rw-r--r--src/test/ui/did_you_mean/issue-40006.stderr16
-rw-r--r--src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr10
-rw-r--r--src/test/ui/issue-37311-type-length-limit/issue-37311.stderr5
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr8
-rw-r--r--src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr8
-rw-r--r--src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr8
-rw-r--r--src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr8
-rw-r--r--src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr8
-rw-r--r--src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr8
-rw-r--r--src/test/ui/mismatched_types/abridged.stderr10
-rw-r--r--src/test/ui/mismatched_types/main.stderr4
-rw-r--r--src/test/ui/missing-items/m2.stderr5
-rw-r--r--src/test/ui/print_type_sizes/repr-align.rs43
-rw-r--r--src/test/ui/print_type_sizes/repr-align.stdout16
-rw-r--r--src/test/ui/span/coerce-suggestions.rs1
-rw-r--r--src/test/ui/span/coerce-suggestions.stderr14
-rw-r--r--src/test/ui/span/impl-wrong-item-for-trait.stderr20
-rw-r--r--src/test/ui/span/issue-23729.stderr5
-rw-r--r--src/test/ui/span/issue-23827.stderr5
-rw-r--r--src/test/ui/span/issue-24356.stderr5
-rw-r--r--src/test/ui/span/issue-33884.rs27
-rw-r--r--src/test/ui/span/issue-33884.stderr12
-rw-r--r--src/test/ui/span/issue-7575.stderr10
-rw-r--r--src/test/ui/span/lint-unused-unsafe.stderr30
-rw-r--r--src/test/ui/span/multiline-span-E0072.stderr5
-rw-r--r--src/test/ui/span/multiline-span-simple.stderr4
-rw-r--r--src/test/ui/type-check/issue-40294.stderr5
-rw-r--r--src/tools/build-manifest/src/main.rs1
110 files changed, 1688 insertions, 710 deletions
diff --git a/configure b/configure
index 35b376d5f27..c5ecc223689 100755
--- a/configure
+++ b/configure
@@ -479,6 +479,7 @@ valopt i686-linux-android-ndk "" "i686-linux-android NDK standalone path"
 valopt arm-linux-androideabi-ndk "" "arm-linux-androideabi NDK standalone path"
 valopt armv7-linux-androideabi-ndk "" "armv7-linux-androideabi NDK standalone path"
 valopt aarch64-linux-android-ndk "" "aarch64-linux-android NDK standalone path"
+valopt x86_64-linux-android-ndk "" "x86_64-linux-android NDK standalone path"
 valopt nacl-cross-path  "" "NaCl SDK path (Pepper Canary is recommended). Must be absolute!"
 valopt musl-root "/usr/local" "MUSL root installation directory (deprecated)"
 valopt musl-root-x86_64 "" "x86_64-unknown-linux-musl install directory"
@@ -746,6 +747,7 @@ putvar CFG_AARCH64_LINUX_ANDROID_NDK
 putvar CFG_ARM_LINUX_ANDROIDEABI_NDK
 putvar CFG_ARMV7_LINUX_ANDROIDEABI_NDK
 putvar CFG_I686_LINUX_ANDROID_NDK
+putvar CFG_X86_64_LINUX_ANDROID_NDK
 putvar CFG_NACL_CROSS_PATH
 putvar CFG_MANDIR
 putvar CFG_DOCDIR
diff --git a/rls b/rls
-Subproject 016cbc514cf44a2bd3fe806e8afa6b9c5028737
+Subproject 6ecff95fdc3ee7ceed2b9b0cc1a3a64876860bc
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index bddd570a13d..cd87b27d4f1 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -151,6 +151,7 @@ pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &st
         if !up_to_date(src_file, dst_file) {
             let mut cmd = Command::new(&compiler_path);
             build.run(cmd.env("RUSTC_BOOTSTRAP", "1")
+                        .arg("--cfg").arg(format!("stage{}", compiler.stage))
                         .arg("--target").arg(target)
                         .arg("--emit=obj")
                         .arg("--out-dir").arg(dst_dir)
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 693114d01ad..34fbc33d981 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -570,6 +570,12 @@ impl Config {
                                      .or_insert(Target::default());
                     target.ndk = Some(parse_configure_path(value));
                 }
+                "CFG_X86_64_LINUX_ANDROID_NDK" if value.len() > 0 => {
+                    let target = "x86_64-linux-android".to_string();
+                    let target = self.target_config.entry(target)
+                                     .or_insert(Target::default());
+                    target.ndk = Some(parse_configure_path(value));
+                }
                 "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => {
                     let path = parse_configure_path(value);
                     self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"]));
diff --git a/src/ci/docker/dist-android/Dockerfile b/src/ci/docker/dist-android/Dockerfile
index 99c176aa820..28cc885ed30 100644
--- a/src/ci/docker/dist-android/Dockerfile
+++ b/src/ci/docker/dist-android/Dockerfile
@@ -36,9 +36,10 @@ RUN curl -o /usr/local/bin/sccache \
       chmod +x /usr/local/bin/sccache
 
 ENV TARGETS=arm-linux-androideabi
+ENV TARGETS=$TARGETS,armv7-linux-androideabi
 ENV TARGETS=$TARGETS,i686-linux-android
 ENV TARGETS=$TARGETS,aarch64-linux-android
-ENV TARGETS=$TARGETS,armv7-linux-androideabi
+ENV TARGETS=$TARGETS,x86_64-linux-android
 
 ENV RUST_CONFIGURE_ARGS \
       --target=$TARGETS \
@@ -46,6 +47,7 @@ ENV RUST_CONFIGURE_ARGS \
       --arm-linux-androideabi-ndk=/android/ndk-arm-9 \
       --armv7-linux-androideabi-ndk=/android/ndk-arm-9 \
       --i686-linux-android-ndk=/android/ndk-x86-9 \
-      --aarch64-linux-android-ndk=/android/ndk-aarch64
+      --aarch64-linux-android-ndk=/android/ndk-arm64-21 \
+      --x86_64-linux-android-ndk=/android/ndk-x86_64-21
 
 ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
diff --git a/src/ci/docker/dist-android/install-ndk.sh b/src/ci/docker/dist-android/install-ndk.sh
index 19c1b94e784..d3a2d317545 100644
--- a/src/ci/docker/dist-android/install-ndk.sh
+++ b/src/ci/docker/dist-android/install-ndk.sh
@@ -25,7 +25,7 @@ bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \
 bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \
         --platform=android-21 \
         --toolchain=aarch64-linux-android-4.9 \
-        --install-dir=/android/ndk-aarch64 \
+        --install-dir=/android/ndk-arm64-21 \
         --ndk-dir=/android/android-ndk-r11c \
         --arch=arm64
 bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \
@@ -34,5 +34,11 @@ bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \
         --install-dir=/android/ndk-x86-9 \
         --ndk-dir=/android/android-ndk-r11c \
         --arch=x86
+bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \
+        --platform=android-21 \
+        --toolchain=x86_64-4.9 \
+        --install-dir=/android/ndk-x86_64-21 \
+        --ndk-dir=/android/android-ndk-r11c \
+        --arch=x86_64
 
 rm -rf ./android-ndk-r11c-linux-x86_64.zip ./android-ndk-r11c
diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md
index fa8be7bb23f..1cfb4653023 100644
--- a/src/doc/unstable-book/src/SUMMARY.md
+++ b/src/doc/unstable-book/src/SUMMARY.md
@@ -71,6 +71,7 @@
     - [prelude_import](language-features/prelude-import.md)
     - [proc_macro](language-features/proc-macro.md)
     - [quote](language-features/quote.md)
+    - [repr_align](language-features/repr-align.md)
     - [repr_simd](language-features/repr-simd.md)
     - [rustc_attrs](language-features/rustc-attrs.md)
     - [rustc_diagnostic_macros](language-features/rustc-diagnostic-macros.md)
@@ -224,4 +225,3 @@
     - [windows_net](library-features/windows-net.md)
     - [windows_stdio](library-features/windows-stdio.md)
     - [zero_one](library-features/zero-one.md)
->>>>>> Add top level sections to the Unstable Book.
diff --git a/src/doc/unstable-book/src/language-features/repr-align.md b/src/doc/unstable-book/src/language-features/repr-align.md
new file mode 100644
index 00000000000..deea04f4c51
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/repr-align.md
@@ -0,0 +1,11 @@
+# `repr_align`
+
+The tracking issue for this feature is: [#33626]
+
+[#33626]: https://github.com/rust-lang/rust/issues/33626
+
+------------------------
+
+
+
+
diff --git a/src/etc/rust-gdb b/src/etc/rust-gdb
index 520a108da91..52601cd96f8 100755
--- a/src/etc/rust-gdb
+++ b/src/etc/rust-gdb
@@ -17,7 +17,10 @@ RUSTC_SYSROOT=`rustc --print=sysroot`
 GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc"
 
 # Run GDB with the additional arguments that load the pretty printers
-PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" gdb \
+# Set the environment variable `RUST_GDB` to overwrite the call to a
+# different/specific command (defaults to `gdb`).
+RUST_GDB="${RUST_GDB:-gdb}"
+PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" ${RUST_GDB} \
   -d "$GDB_PYTHON_MODULE_DIRECTORY" \
   -iex "add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY" \
   "$@"
diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs
index dfff44e30c5..e05533aa50e 100644
--- a/src/libcollections/btree/set.rs
+++ b/src/libcollections/btree/set.rs
@@ -138,7 +138,8 @@ pub struct Difference<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for Difference<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("Difference")
-         .field(&self.clone())
+         .field(&self.a)
+         .field(&self.b)
          .finish()
     }
 }
@@ -160,7 +161,8 @@ pub struct SymmetricDifference<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for SymmetricDifference<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("SymmetricDifference")
-         .field(&self.clone())
+         .field(&self.a)
+         .field(&self.b)
          .finish()
     }
 }
@@ -182,7 +184,8 @@ pub struct Intersection<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for Intersection<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("Intersection")
-         .field(&self.clone())
+         .field(&self.a)
+         .field(&self.b)
          .finish()
     }
 }
@@ -204,7 +207,8 @@ pub struct Union<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for Union<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("Union")
-         .field(&self.clone())
+         .field(&self.a)
+         .field(&self.b)
          .finish()
     }
 }
diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs
index ebee75d1a1a..aaee567bf1d 100644
--- a/src/libcollections/enum_set.rs
+++ b/src/libcollections/enum_set.rs
@@ -225,7 +225,8 @@ pub struct Iter<E> {
 impl<E: fmt::Debug> fmt::Debug for Iter<E> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("Iter")
-         .field(&self.clone())
+         .field(&self.index)
+         .field(&self.bits)
          .finish()
     }
 }
diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs
index bfb03a5b23f..1cc5e10418f 100644
--- a/src/libcollections/linked_list.rs
+++ b/src/libcollections/linked_list.rs
@@ -75,7 +75,7 @@ pub struct Iter<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("Iter")
-         .field(&self.clone())
+         .field(&self.len)
          .finish()
     }
 }
@@ -107,7 +107,8 @@ pub struct IterMut<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("IterMut")
-         .field(self.clone())
+         .field(&self.list)
+         .field(&self.len)
          .finish()
     }
 }
@@ -129,7 +130,7 @@ pub struct IntoIter<T> {
 impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("IntoIter")
-         .field(self.clone())
+         .field(&self.list)
          .finish()
     }
 }
@@ -1128,7 +1129,7 @@ pub struct FrontPlace<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for FrontPlace<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("FrontPlace")
-         .field(self.clone())
+         .field(&self.list)
          .finish()
     }
 }
@@ -1183,7 +1184,7 @@ pub struct BackPlace<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for BackPlace<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("BackPlace")
-         .field(self.clone())
+         .field(&self.list)
          .finish()
     }
 }
diff --git a/src/libcollections/tests/vec.rs b/src/libcollections/tests/vec.rs
index 63df0eb7305..64c76142b59 100644
--- a/src/libcollections/tests/vec.rs
+++ b/src/libcollections/tests/vec.rs
@@ -84,6 +84,9 @@ fn test_extend() {
     let mut v = Vec::new();
     let mut w = Vec::new();
 
+    v.extend(w.clone());
+    assert_eq!(v, &[]);
+
     v.extend(0..3);
     for i in 0..3 {
         w.push(i)
@@ -100,6 +103,25 @@ fn test_extend() {
 
     v.extend(w.clone()); // specializes to `append`
     assert!(v.iter().eq(w.iter().chain(w.iter())));
+
+    // Zero sized types
+    #[derive(PartialEq, Debug)]
+    struct Foo;
+
+    let mut a = Vec::new();
+    let b = vec![Foo, Foo];
+
+    a.extend(b);
+    assert_eq!(a, &[Foo, Foo]);
+
+    // Double drop
+    let mut count_x = 0;
+    {
+        let mut x = Vec::new();
+        let y = vec![DropCounter { count: &mut count_x }];
+        x.extend(y);
+    }
+    assert_eq!(count_x, 1);
 }
 
 #[test]
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index a3c529f3585..6deb87ae772 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -1041,18 +1041,22 @@ impl<T> Vec<T> {
     #[inline]
     #[stable(feature = "append", since = "1.4.0")]
     pub fn append(&mut self, other: &mut Self) {
-        self.reserve(other.len());
-        let len = self.len();
-        unsafe {
-            ptr::copy_nonoverlapping(other.as_ptr(), self.get_unchecked_mut(len), other.len());
-        }
-
-        self.len += other.len();
         unsafe {
+            self.append_elements(other.as_slice() as _);
             other.set_len(0);
         }
     }
 
+    /// Appends elements to `Self` from other buffer.
+    #[inline]
+    unsafe fn append_elements(&mut self, other: *const [T]) {
+        let count = (*other).len();
+        self.reserve(count);
+        let len = self.len();
+        ptr::copy_nonoverlapping(other as *const T, self.get_unchecked_mut(len), count);
+        self.len += count;
+    }
+
     /// Create a draining iterator that removes the specified range in the vector
     /// and yields the removed items.
     ///
@@ -1738,7 +1742,7 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
         vector
     }
 
-    fn spec_extend(&mut self, iterator: I) {
+    default fn spec_extend(&mut self, iterator: I) {
         // This is the case for a TrustedLen iterator.
         let (low, high) = iterator.size_hint();
         if let Some(high_value) = high {
@@ -1783,6 +1787,13 @@ impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
             vector
         }
     }
+
+    fn spec_extend(&mut self, mut iterator: IntoIter<T>) {
+        unsafe {
+            self.append_elements(iterator.as_slice() as _);
+        }
+        iterator.ptr = iterator.end;
+    }
 }
 
 impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec<T>
diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs
index 2a73a78adbe..a9e795f9378 100644
--- a/src/libcollections/vec_deque.rs
+++ b/src/libcollections/vec_deque.rs
@@ -1913,7 +1913,9 @@ pub struct Iter<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("Iter")
-         .field(&self.clone())
+         .field(&self.ring)
+         .field(&self.tail)
+         .field(&self.head)
          .finish()
     }
 }
@@ -2000,7 +2002,9 @@ pub struct IterMut<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("IterMut")
-         .field(&self.clone())
+         .field(&self.ring)
+         .field(&self.tail)
+         .field(&self.head)
          .finish()
     }
 }
@@ -2081,7 +2085,7 @@ pub struct IntoIter<T> {
 impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("IntoIter")
-         .field(&self.clone())
+         .field(&self.inner)
          .finish()
     }
 }
@@ -2139,7 +2143,9 @@ pub struct Drain<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for Drain<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("Drain")
-         .field(&self.clone())
+         .field(&self.after_tail)
+         .field(&self.after_head)
+         .field(&self.iter)
          .finish()
     }
 }
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index 0b0f831f093..084736685e3 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -17,8 +17,8 @@
 //! Like many traits, these are often used as bounds for generic functions, to
 //! support arguments of multiple types.
 //!
-//! - Impl the `As*` traits for reference-to-reference conversions
-//! - Impl the [`Into`] trait when you want to consume the value in the conversion
+//! - Implement the `As*` traits for reference-to-reference conversions
+//! - Implement the [`Into`] trait when you want to consume the value in the conversion
 //! - The [`From`] trait is the most flexible, useful for value _and_ reference conversions
 //! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`], but allow for the
 //!   conversion to fail
@@ -26,16 +26,16 @@
 //! As a library author, you should prefer implementing [`From<T>`][`From`] or
 //! [`TryFrom<T>`][`TryFrom`] rather than [`Into<U>`][`Into`] or [`TryInto<U>`][`TryInto`],
 //! as [`From`] and [`TryFrom`] provide greater flexibility and offer
-//! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a blanket implementation
-//! in the standard library.
+//! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a
+//! blanket implementation in the standard library.
 //!
-//! # Generic impl
+//! # Generic Implementations
 //!
 //! - [`AsRef`] and [`AsMut`] auto-dereference if the inner type is a reference
 //! - [`From`]`<U> for T` implies [`Into`]`<T> for U`
 //! - [`TryFrom`]`<U> for T` implies [`TryInto`]`<T> for U`
-//! - [`From`] and [`Into`] are reflexive, which means that all types can `into()`
-//!   themselves and `from()` themselves
+//! - [`From`] and [`Into`] are reflexive, which means that all types can
+//!   `into` themselves and `from` themselves
 //!
 //! See each trait for usage examples.
 //!
@@ -50,20 +50,42 @@
 
 use str::FromStr;
 
-/// A cheap, reference-to-reference conversion.
+/// A cheap reference-to-reference conversion. Used to convert a value to a
+/// reference value within generic code.
 ///
-/// `AsRef` is very similar to, but different than, [`Borrow`]. See
-/// [the book][book] for more.
+/// `AsRef` is very similar to, but serves a slightly different purpose than,
+/// [`Borrow`].
+///
+/// `AsRef` is to be used when wishing to convert to a reference of another
+/// type.
+/// `Borrow` is more related to the notion of taking the reference. It is
+/// useful when wishing to abstract over the type of reference
+/// (`&T`, `&mut T`) or allow both the referenced and owned type to be treated
+/// in the same manner.
+///
+/// The key difference between the two traits is the intention:
+///
+/// - Use `AsRef` when goal is to simply convert into a reference
+/// - Use `Borrow` when goal is related to writing code that is agnostic to the
+///   type of borrow and if is reference or value
+///
+/// See [the book][book] for a more detailed comparison.
 ///
 /// [book]: ../../book/borrow-and-asref.html
 /// [`Borrow`]: ../../std/borrow/trait.Borrow.html
 ///
-/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which
-/// returns an [`Option<T>`] or a [`Result<T, E>`].
+/// **Note: this trait must not fail**. If the conversion can fail, use a
+/// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
 ///
 /// [`Option<T>`]: ../../std/option/enum.Option.html
 /// [`Result<T, E>`]: ../../std/result/enum.Result.html
 ///
+/// # Generic Implementations
+///
+/// - `AsRef` auto-dereferences if the inner type is a reference or a mutable
+///   reference (e.g.: `foo.as_ref()` will work the same if `foo` has type
+///   `&mut Foo` or `&&mut Foo`)
+///
 /// # Examples
 ///
 /// Both [`String`] and `&str` implement `AsRef<str>`:
@@ -82,11 +104,6 @@ use str::FromStr;
 /// is_hello(s);
 /// ```
 ///
-/// # Generic Impls
-///
-/// - `AsRef` auto-dereferences if the inner type is a reference or a mutable
-/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`)
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsRef<T: ?Sized> {
     /// Performs the conversion.
@@ -96,12 +113,21 @@ pub trait AsRef<T: ?Sized> {
 
 /// A cheap, mutable reference-to-mutable reference conversion.
 ///
-/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which
-/// returns an [`Option<T>`] or a [`Result<T, E>`].
+/// This trait is similar to `AsRef` but used for converting between mutable
+/// references.
+///
+/// **Note: this trait must not fail**. If the conversion can fail, use a
+/// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
 ///
 /// [`Option<T>`]: ../../std/option/enum.Option.html
 /// [`Result<T, E>`]: ../../std/result/enum.Result.html
 ///
+/// # Generic Implementations
+///
+/// - `AsMut` auto-dereferences if the inner type is a reference or a mutable
+///   reference (e.g.: `foo.as_ref()` will work the same if `foo` has type
+///   `&mut Foo` or `&&mut Foo`)
+///
 /// # Examples
 ///
 /// [`Box<T>`] implements `AsMut<T>`:
@@ -118,10 +144,6 @@ pub trait AsRef<T: ?Sized> {
 /// assert_eq!(*boxed_num, 1);
 /// ```
 ///
-/// # Generic Impls
-///
-/// - `AsMut` auto-dereferences if the inner type is a reference or a mutable
-/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`)
 ///
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsMut<T: ?Sized> {
@@ -130,14 +152,22 @@ pub trait AsMut<T: ?Sized> {
     fn as_mut(&mut self) -> &mut T;
 }
 
-/// A conversion that consumes `self`, which may or may not be expensive.
+/// A conversion that consumes `self`, which may or may not be expensive. The
+/// reciprocal of [`From`][From].
+///
+/// **Note: this trait must not fail**. If the conversion can fail, use
+/// [`TryInto`] or a dedicated method which returns an [`Option<T>`] or a
+/// [`Result<T, E>`].
 ///
-/// **Note: this trait must not fail**. If the conversion can fail, use [`TryInto`] or a dedicated
-/// method which returns an [`Option<T>`] or a [`Result<T, E>`].
+/// Library authors should not directly implement this trait, but should prefer
+/// implementing the [`From`][From] trait, which offers greater flexibility and
+/// provides an equivalent `Into` implementation for free, thanks to a blanket
+/// implementation in the standard library.
 ///
-/// Library authors should not directly implement this trait, but should prefer implementing
-/// the [`From`][From] trait, which offers greater flexibility and provides an equivalent `Into`
-/// implementation for free, thanks to a blanket implementation in the standard library.
+/// # Generic Implementations
+///
+/// - [`From<T>`][From]` for U` implies `Into<U> for T`
+/// - [`into`] is reflexive, which means that `Into<T> for T` is implemented
 ///
 /// # Examples
 ///
@@ -153,11 +183,6 @@ pub trait AsMut<T: ?Sized> {
 /// is_hello(s);
 /// ```
 ///
-/// # Generic Impls
-///
-/// - [`From<T>`][From]` for U` implies `Into<U> for T`
-/// - [`into`] is reflexive, which means that `Into<T> for T` is implemented
-///
 /// [`TryInto`]: trait.TryInto.html
 /// [`Option<T>`]: ../../std/option/enum.Option.html
 /// [`Result<T, E>`]: ../../std/result/enum.Result.html
@@ -171,10 +196,31 @@ pub trait Into<T>: Sized {
     fn into(self) -> T;
 }
 
-/// Construct `Self` via a conversion.
+/// Simple and safe type conversions in to `Self`. It is the reciprocal of
+/// `Into`.
+///
+/// This trait is useful when performing error handling as described by
+/// [the book][book] and is closely related to the `?` operator.
+///
+/// When constructing a function that is capable of failing the return type
+/// will generally be of the form `Result<T, E>`.
+///
+/// The `From` trait allows for simplification of error handling by providing a
+/// means of returning a single error type that encapsulates numerous possible
+/// erroneous situations.
+///
+/// This trait is not limited to error handling, rather the general case for
+/// this trait would be in any type conversions to have an explicit definition
+/// of how they are performed.
+///
+/// **Note: this trait must not fail**. If the conversion can fail, use
+/// [`TryFrom`] or a dedicated method which returns an [`Option<T>`] or a
+/// [`Result<T, E>`].
 ///
-/// **Note: this trait must not fail**. If the conversion can fail, use [`TryFrom`] or a dedicated
-/// method which returns an [`Option<T>`] or a [`Result<T, E>`].
+/// # Generic Implementations
+///
+/// - `From<T> for U` implies [`Into<U>`]` for T`
+/// - [`from`] is reflexive, which means that `From<T> for T` is implemented
 ///
 /// # Examples
 ///
@@ -186,10 +232,38 @@ pub trait Into<T>: Sized {
 ///
 /// assert_eq!(string, other_string);
 /// ```
-/// # Generic impls
 ///
-/// - `From<T> for U` implies [`Into<U>`]` for T`
-/// - [`from`] is reflexive, which means that `From<T> for T` is implemented
+/// An example usage for error handling:
+///
+/// ```
+/// use std::io::{self, Read};
+/// use std::num;
+///
+/// enum CliError {
+///     IoError(io::Error),
+///     ParseError(num::ParseIntError),
+/// }
+///
+/// impl From<io::Error> for CliError {
+///     fn from(error: io::Error) -> Self {
+///         CliError::IoError(error)
+///     }
+/// }
+///
+/// impl From<num::ParseIntError> for CliError {
+///     fn from(error: num::ParseIntError) -> Self {
+///         CliError::ParseError(error)
+///     }
+/// }
+///
+/// fn open_and_parse_file(file_name: &str) -> Result<i32, CliError> {
+///     let mut file = std::fs::File::open("test")?;
+///     let mut contents = String::new();
+///     file.read_to_string(&mut contents)?;
+///     let num: i32 = contents.trim().parse()?;
+///     Ok(num)
+/// }
+/// ```
 ///
 /// [`TryFrom`]: trait.TryFrom.html
 /// [`Option<T>`]: ../../std/option/enum.Option.html
@@ -197,6 +271,7 @@ pub trait Into<T>: Sized {
 /// [`String`]: ../../std/string/struct.String.html
 /// [`Into<U>`]: trait.Into.html
 /// [`from`]: trait.From.html#tymethod.from
+/// [book]: ../../book/error-handling.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait From<T>: Sized {
     /// Performs the conversion.
@@ -204,11 +279,13 @@ pub trait From<T>: Sized {
     fn from(T) -> Self;
 }
 
-/// An attempted conversion that consumes `self`, which may or may not be expensive.
+/// An attempted conversion that consumes `self`, which may or may not be
+/// expensive.
 ///
-/// Library authors should not directly implement this trait, but should prefer implementing
-/// the [`TryFrom`] trait, which offers greater flexibility and provides an equivalent `TryInto`
-/// implementation for free, thanks to a blanket implementation in the standard library.
+/// Library authors should not directly implement this trait, but should prefer
+/// implementing the [`TryFrom`] trait, which offers greater flexibility and
+/// provides an equivalent `TryInto` implementation for free, thanks to a
+/// blanket implementation in the standard library.
 ///
 /// [`TryFrom`]: trait.TryFrom.html
 #[unstable(feature = "try_from", issue = "33417")]
@@ -236,7 +313,8 @@ pub trait TryFrom<T>: Sized {
 
 // As lifts over &
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> {
+impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U>
+{
     fn as_ref(&self) -> &U {
         <T as AsRef<U>>::as_ref(*self)
     }
@@ -244,7 +322,8 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> {
 
 // As lifts over &mut
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> {
+impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U>
+{
     fn as_ref(&self) -> &U {
         <T as AsRef<U>>::as_ref(*self)
     }
@@ -260,7 +339,8 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> {
 
 // AsMut lifts over &mut
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> {
+impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U>
+{
     fn as_mut(&mut self) -> &mut U {
         (*self).as_mut()
     }
@@ -276,7 +356,8 @@ impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> {
 
 // From implies Into
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, U> Into<U> for T where U: From<T> {
+impl<T, U> Into<U> for T where U: From<T>
+{
     fn into(self) -> U {
         U::from(self)
     }
@@ -291,7 +372,8 @@ impl<T> From<T> for T {
 
 // TryFrom implies TryInto
 #[unstable(feature = "try_from", issue = "33417")]
-impl<T, U> TryInto<U> for T where U: TryFrom<T> {
+impl<T, U> TryInto<U> for T where U: TryFrom<T>
+{
     type Error = U::Error;
 
     fn try_into(self) -> Result<U, U::Error> {
@@ -327,7 +409,8 @@ impl AsRef<str> for str {
 
 // FromStr implies TryFrom<&str>
 #[unstable(feature = "try_from", issue = "33417")]
-impl<'a, T> TryFrom<&'a str> for T where T: FromStr {
+impl<'a, T> TryFrom<&'a str> for T where T: FromStr
+{
     type Error = <T as FromStr>::Err;
 
     fn try_from(s: &'a str) -> Result<T, Self::Error> {
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 393c01b0105..c0aa650a1e8 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -16,6 +16,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use cell::UnsafeCell;
 use cmp;
 use hash::Hash;
 use hash::Hasher;
@@ -553,3 +554,19 @@ mod impls {
     #[stable(feature = "rust1", since = "1.0.0")]
     unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
 }
+
+/// Compiler-internal trait used to determine whether a type contains
+/// any `UnsafeCell` internally, but not through an indirection.
+/// This affects, for example, whether a `static` of that type is
+/// placed in read-only static memory or writable static memory.
+#[cfg_attr(not(stage0), lang = "freeze")]
+unsafe trait Freeze {}
+
+unsafe impl Freeze for .. {}
+
+impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
+unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
+unsafe impl<T: ?Sized> Freeze for *const T {}
+unsafe impl<T: ?Sized> Freeze for *mut T {}
+unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
+unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
diff --git a/src/liblibc b/src/liblibc
-Subproject 05a2d197356ef253dfd985166576619ac9b6947
+Subproject c34a802d1eb037b44c5252078c7270b5472e0f6
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 618561f3b02..2851191dc14 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -1847,5 +1847,6 @@ register_diagnostics! {
     E0489, // type/lifetime parameter not in scope here
     E0490, // a value of type `..` is borrowed for too long
     E0495, // cannot infer an appropriate lifetime due to conflicting requirements
-    E0566  // conflicting representation hints
+    E0566, // conflicting representation hints
+    E0587, // conflicting packed and align representation hints
 }
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 54ae9472140..bf292ccb8d8 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -57,6 +57,9 @@ impl<'a> CheckAttrVisitor<'a> {
         };
 
         let mut conflicting_reprs = 0;
+        let mut found_packed = false;
+        let mut found_align = false;
+
         for word in words {
 
             let name = match word.name() {
@@ -84,6 +87,7 @@ impl<'a> CheckAttrVisitor<'a> {
                                 ("attribute should be applied to struct or union",
                                  "a struct or union")
                     } else {
+                        found_packed = true;
                         continue
                     }
                 }
@@ -96,6 +100,15 @@ impl<'a> CheckAttrVisitor<'a> {
                         continue
                     }
                 }
+                "align" => {
+                    found_align = true;
+                    if target != Target::Struct {
+                        ("attribute should be applied to struct",
+                         "a struct")
+                    } else {
+                        continue
+                    }
+                }
                 "i8" | "u8" | "i16" | "u16" |
                 "i32" | "u32" | "i64" | "u64" |
                 "isize" | "usize" => {
@@ -117,6 +130,10 @@ impl<'a> CheckAttrVisitor<'a> {
             span_warn!(self.sess, attr.span, E0566,
                        "conflicting representation hints");
         }
+        if found_align && found_packed {
+            struct_span_err!(self.sess, attr.span, E0587,
+                             "conflicting packed and align representation hints").emit();
+        }
     }
 
     fn check_attribute(&self, attr: &ast::Attribute, target: Target) {
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 5989fa9007c..32dfb63d615 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -274,6 +274,7 @@ language_item_table! {
     UnsizeTraitLangItem,             "unsize",                  unsize_trait;
     CopyTraitLangItem,               "copy",                    copy_trait;
     SyncTraitLangItem,               "sync",                    sync_trait;
+    FreezeTraitLangItem,             "freeze",                  freeze_trait;
 
     DropTraitLangItem,               "drop",                    drop_trait;
 
diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs
deleted file mode 100644
index e1429598291..00000000000
--- a/src/librustc/ty/contents.rs
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright 2012-2015 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 hir::def_id::{DefId};
-use ty::{self, Ty, TyCtxt};
-use util::common::MemoizationMap;
-use util::nodemap::FxHashMap;
-
-use std::fmt;
-use std::ops;
-
-use syntax::ast;
-
-/// Type contents is how the type checker reasons about kinds.
-/// They track what kinds of things are found within a type.  You can
-/// think of them as kind of an "anti-kind".  They track the kinds of values
-/// and thinks that are contained in types.  Having a larger contents for
-/// a type tends to rule that type *out* from various kinds.  For example,
-/// a type that contains a reference is not sendable.
-///
-/// The reason we compute type contents and not kinds is that it is
-/// easier for me (nmatsakis) to think about what is contained within
-/// a type than to think about what is *not* contained within a type.
-#[derive(Clone, Copy)]
-pub struct TypeContents {
-    pub bits: u64
-}
-
-macro_rules! def_type_content_sets {
-    (mod $mname:ident { $($name:ident = $bits:expr),+ }) => {
-        #[allow(non_snake_case)]
-        mod $mname {
-            use super::TypeContents;
-            $(
-                #[allow(non_upper_case_globals)]
-                pub const $name: TypeContents = TypeContents { bits: $bits };
-             )+
-        }
-    }
-}
-
-def_type_content_sets! {
-    mod TC {
-        None                                = 0b0000_0000__0000_0000__0000,
-
-        // Things that are interior to the value (first nibble):
-        InteriorUnsafe                      = 0b0000_0000__0000_0000__0010,
-        InteriorParam                       = 0b0000_0000__0000_0000__0100,
-        // InteriorAll                         = 0b00000000__00000000__1111,
-
-        // Things that are owned by the value (second and third nibbles):
-        OwnsDtor                            = 0b0000_0000__0000_0010__0000,
-        // OwnsAll                             = 0b0000_0000__1111_1111__0000,
-
-        // All bits
-        All                                 = 0b1111_1111__1111_1111__1111
-    }
-}
-
-impl TypeContents {
-    pub fn when(&self, cond: bool) -> TypeContents {
-        if cond {*self} else {TC::None}
-    }
-
-    pub fn intersects(&self, tc: TypeContents) -> bool {
-        (self.bits & tc.bits) != 0
-    }
-
-    pub fn interior_param(&self) -> bool {
-        self.intersects(TC::InteriorParam)
-    }
-
-    pub fn interior_unsafe(&self) -> bool {
-        self.intersects(TC::InteriorUnsafe)
-    }
-
-    pub fn needs_drop(&self, _: TyCtxt) -> bool {
-        self.intersects(TC::OwnsDtor)
-    }
-
-    pub fn union<I, T, F>(v: I, mut f: F) -> TypeContents where
-        I: IntoIterator<Item=T>,
-        F: FnMut(T) -> TypeContents,
-    {
-        v.into_iter().fold(TC::None, |tc, ty| tc | f(ty))
-    }
-}
-
-impl ops::BitOr for TypeContents {
-    type Output = TypeContents;
-
-    fn bitor(self, other: TypeContents) -> TypeContents {
-        TypeContents {bits: self.bits | other.bits}
-    }
-}
-
-impl ops::BitAnd for TypeContents {
-    type Output = TypeContents;
-
-    fn bitand(self, other: TypeContents) -> TypeContents {
-        TypeContents {bits: self.bits & other.bits}
-    }
-}
-
-impl ops::Sub for TypeContents {
-    type Output = TypeContents;
-
-    fn sub(self, other: TypeContents) -> TypeContents {
-        TypeContents {bits: self.bits & !other.bits}
-    }
-}
-
-impl fmt::Debug for TypeContents {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "TypeContents({:b})", self.bits)
-    }
-}
-
-impl<'a, 'tcx> ty::TyS<'tcx> {
-    pub fn type_contents(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> TypeContents {
-        return tcx.tc_cache.memoize(self, || tc_ty(tcx, self, &mut FxHashMap()));
-
-        fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                           ty: Ty<'tcx>,
-                           cache: &mut FxHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
-        {
-            // Subtle: Note that we are *not* using tcx.tc_cache here but rather a
-            // private cache for this walk.  This is needed in the case of cyclic
-            // types like:
-            //
-            //     struct List { next: Box<Option<List>>, ... }
-            //
-            // When computing the type contents of such a type, we wind up deeply
-            // recursing as we go.  So when we encounter the recursive reference
-            // to List, we temporarily use TC::None as its contents.  Later we'll
-            // patch up the cache with the correct value, once we've computed it
-            // (this is basically a co-inductive process, if that helps).  So in
-            // the end we'll compute TC::OwnsOwned, in this case.
-            //
-            // The problem is, as we are doing the computation, we will also
-            // compute an *intermediate* contents for, e.g., Option<List> of
-            // TC::None.  This is ok during the computation of List itself, but if
-            // we stored this intermediate value into tcx.tc_cache, then later
-            // requests for the contents of Option<List> would also yield TC::None
-            // which is incorrect.  This value was computed based on the crutch
-            // value for the type contents of list.  The correct value is
-            // TC::OwnsOwned.  This manifested as issue #4821.
-            if let Some(tc) = cache.get(&ty) {
-                return *tc;
-            }
-            // Must check both caches!
-            if let Some(tc) = tcx.tc_cache.borrow().get(&ty) {
-                return *tc;
-            }
-            cache.insert(ty, TC::None);
-
-            let result = match ty.sty {
-                // usize and isize are ffi-unsafe
-                ty::TyUint(ast::UintTy::Us) | ty::TyInt(ast::IntTy::Is) => {
-                    TC::None
-                }
-
-                // Scalar and unique types are sendable, and durable
-                ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
-                ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
-                ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar => {
-                    TC::None
-                }
-
-                ty::TyDynamic(..) => {
-                    TC::All - TC::InteriorParam
-                }
-
-                ty::TyRawPtr(_) => {
-                    TC::None
-                }
-
-                ty::TyRef(..) => {
-                    TC::None
-                }
-
-                ty::TyArray(ty, _) => {
-                    tc_ty(tcx, ty, cache)
-                }
-
-                ty::TySlice(ty) => {
-                    tc_ty(tcx, ty, cache)
-                }
-                ty::TyStr => TC::None,
-
-                ty::TyClosure(def_id, ref substs) => {
-                    TypeContents::union(
-                        substs.upvar_tys(def_id, tcx),
-                        |ty| tc_ty(tcx, &ty, cache))
-                }
-
-                ty::TyTuple(ref tys, _) => {
-                    TypeContents::union(&tys[..],
-                                        |ty| tc_ty(tcx, *ty, cache))
-                }
-
-                ty::TyAdt(def, substs) => {
-                    let mut res =
-                        TypeContents::union(&def.variants, |v| {
-                            TypeContents::union(&v.fields, |f| {
-                                tc_ty(tcx, f.ty(tcx, substs), cache)
-                            })
-                        });
-
-                    if def.is_union() {
-                        // unions don't have destructors regardless of the child types
-                        res = res - TC::OwnsDtor;
-                    }
-
-                    if def.has_dtor(tcx) {
-                        res = res | TC::OwnsDtor;
-                    }
-
-                    apply_lang_items(tcx, def.did, res)
-                }
-
-                ty::TyProjection(..) |
-                ty::TyParam(_) |
-                ty::TyAnon(..) => {
-                    TC::All
-                }
-
-                ty::TyInfer(_) |
-                ty::TyError => {
-                    bug!("asked to compute contents of error type");
-                }
-            };
-
-            cache.insert(ty, result);
-            result
-        }
-
-        fn apply_lang_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                      did: DefId, tc: TypeContents)
-                                      -> TypeContents {
-            if Some(did) == tcx.lang_items.unsafe_cell_type() {
-                tc | TC::InteriorUnsafe
-            } else {
-                tc
-            }
-        }
-    }
-}
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 8b7438c0bfa..a4162925871 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -436,9 +436,6 @@ pub struct GlobalCtxt<'tcx> {
     // Internal cache for metadata decoding. No need to track deps on this.
     pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
 
-    // Cache for the type-contents routine. FIXME -- track deps?
-    pub tc_cache: RefCell<FxHashMap<Ty<'tcx>, ty::contents::TypeContents>>,
-
     // FIXME dep tracking -- should be harmless enough
     pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
 
@@ -708,7 +705,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             freevars: RefCell::new(resolutions.freevars),
             maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
             rcache: RefCell::new(FxHashMap()),
-            tc_cache: RefCell::new(FxHashMap()),
             normalized_cache: RefCell::new(FxHashMap()),
             inhabitedness_cache: RefCell::new(FxHashMap()),
             lang_items: lang_items,
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index df60eee8c02..6a206640b3b 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -548,8 +548,12 @@ pub type FieldPath = Vec<u32>;
 /// A structure, a product type in ADT terms.
 #[derive(PartialEq, Eq, Hash, Debug)]
 pub struct Struct {
+    /// Maximum alignment of fields and repr alignment.
     pub align: Align,
 
+    /// Primitive alignment of fields without repr alignment.
+    pub primitive_align: Align,
+
     /// If true, no alignment padding is used.
     pub packed: bool,
 
@@ -583,10 +587,20 @@ impl<'a, 'gcx, 'tcx> Struct {
     fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
                   repr: &ReprOptions, kind: StructKind,
                   scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
-        let packed = repr.packed();
+        if repr.packed() && repr.align > 0 {
+            bug!("Struct cannot be packed and aligned");
+        }
+
+        let align = if repr.packed() {
+            dl.i8_align
+        } else {
+            dl.aggregate_align
+        };
+
         let mut ret = Struct {
-            align: if packed { dl.i8_align } else { dl.aggregate_align },
-            packed: packed,
+            align: align,
+            primitive_align: align,
+            packed: repr.packed(),
             sized: true,
             offsets: vec![],
             memory_index: vec![],
@@ -660,7 +674,9 @@ impl<'a, 'gcx, 'tcx> Struct {
             // Invariant: offset < dl.obj_size_bound() <= 1<<61
             if !ret.packed {
                 let align = field.align(dl);
+                let primitive_align = field.primitive_align(dl);
                 ret.align = ret.align.max(align);
+                ret.primitive_align = ret.primitive_align.max(primitive_align);
                 offset = offset.abi_align(align);
             }
 
@@ -671,6 +687,11 @@ impl<'a, 'gcx, 'tcx> Struct {
                            .map_or(Err(LayoutError::SizeOverflow(scapegoat)), Ok)?;
         }
 
+        if repr.align > 0 {
+            let repr_align = repr.align as u64;
+            ret.align = ret.align.max(Align::from_bytes(repr_align, repr_align).unwrap());
+            debug!("Struct::new repr_align: {:?}", repr_align);
+        }
 
         debug!("Struct::new min_size: {:?}", offset);
         ret.min_size = offset;
@@ -836,12 +857,23 @@ impl<'a, 'gcx, 'tcx> Struct {
         }
         Ok(None)
     }
+
+    pub fn over_align(&self) -> Option<u32> {
+        let align = self.align.abi();
+        let primitive_align = self.primitive_align.abi();
+        if align > primitive_align {
+            Some(align as u32)
+        } else {
+            None
+        }
+    }
 }
 
 /// An untagged union.
 #[derive(PartialEq, Eq, Hash, Debug)]
 pub struct Union {
     pub align: Align,
+    pub primitive_align: Align,
 
     pub min_size: Size,
 
@@ -851,8 +883,10 @@ pub struct Union {
 
 impl<'a, 'gcx, 'tcx> Union {
     fn new(dl: &TargetDataLayout, packed: bool) -> Union {
+        let align = if packed { dl.i8_align } else { dl.aggregate_align };
         Union {
-            align: if packed { dl.i8_align } else { dl.aggregate_align },
+            align: align,
+            primitive_align: align,
             min_size: Size::from_bytes(0),
             packed: packed,
         }
@@ -875,6 +909,7 @@ impl<'a, 'gcx, 'tcx> Union {
 
             if !self.packed {
                 self.align = self.align.max(field.align(dl));
+                self.primitive_align = self.primitive_align.max(field.primitive_align(dl));
             }
             self.min_size = cmp::max(self.min_size, field.size(dl));
         }
@@ -888,6 +923,16 @@ impl<'a, 'gcx, 'tcx> Union {
     pub fn stride(&self) -> Size {
         self.min_size.abi_align(self.align)
     }
+
+    pub fn over_align(&self) -> Option<u32> {
+        let align = self.align.abi();
+        let primitive_align = self.primitive_align.abi();
+        if align > primitive_align {
+            Some(align as u32)
+        } else {
+            None
+        }
+    }
 }
 
 /// The first half of a fat pointer.
@@ -924,6 +969,7 @@ pub enum Layout {
         /// If true, the size is exact, otherwise it's only a lower bound.
         sized: bool,
         align: Align,
+        primitive_align: Align,
         element_size: Size,
         count: u64
     },
@@ -970,7 +1016,8 @@ pub enum Layout {
         discr: Integer,
         variants: Vec<Struct>,
         size: Size,
-        align: Align
+        align: Align,
+        primitive_align: Align,
     },
 
     /// Two cases distinguished by a nullable pointer: the case with discriminant
@@ -1118,6 +1165,7 @@ impl<'a, 'gcx, 'tcx> Layout {
                 Array {
                     sized: true,
                     align: element.align(dl),
+                    primitive_align: element.primitive_align(dl),
                     element_size: element_size,
                     count: count
                 }
@@ -1127,6 +1175,7 @@ impl<'a, 'gcx, 'tcx> Layout {
                 Array {
                     sized: false,
                     align: element.align(dl),
+                    primitive_align: element.primitive_align(dl),
                     element_size: element.size(dl),
                     count: 0
                 }
@@ -1135,6 +1184,7 @@ impl<'a, 'gcx, 'tcx> Layout {
                 Array {
                     sized: false,
                     align: dl.i8_align,
+                    primitive_align: dl.i8_align,
                     element_size: Size::from_bytes(1),
                     count: 0
                 }
@@ -1340,6 +1390,7 @@ impl<'a, 'gcx, 'tcx> Layout {
                 assert!(discr_max >= 0);
                 let (min_ity, _) = Integer::repr_discr(tcx, ty, &def.repr, 0, discr_max);
                 let mut align = dl.aggregate_align;
+                let mut primitive_align = dl.aggregate_align;
                 let mut size = Size::from_bytes(0);
 
                 // We're interested in the smallest alignment, so start large.
@@ -1369,6 +1420,7 @@ impl<'a, 'gcx, 'tcx> Layout {
                     }
                     size = cmp::max(size, st.min_size);
                     align = align.max(st.align);
+                    primitive_align = primitive_align.max(st.primitive_align);
                     Ok(st)
                 }).collect::<Result<Vec<_>, _>>()?;
 
@@ -1435,7 +1487,8 @@ impl<'a, 'gcx, 'tcx> Layout {
                     discr: ity,
                     variants: variants,
                     size: size,
-                    align: align
+                    align: align,
+                    primitive_align: primitive_align
                 }
             }
 
@@ -1557,6 +1610,30 @@ impl<'a, 'gcx, 'tcx> Layout {
         }
     }
 
+    /// Returns alignment before repr alignment is applied
+    pub fn primitive_align(&self, dl: &TargetDataLayout) -> Align {
+        match *self {
+            Array { primitive_align, .. } | General { primitive_align, .. } => primitive_align,
+            Univariant { ref variant, .. } |
+            StructWrappedNullablePointer { nonnull: ref variant, .. } => {
+                variant.primitive_align
+            },
+
+            _ => self.align(dl)
+        }
+    }
+
+    /// Returns repr alignment if it is greater than the primitive alignment.
+    pub fn over_align(&self, dl: &TargetDataLayout) -> Option<u32> {
+        let align = self.align(dl);
+        let primitive_align = self.primitive_align(dl);
+        if align.abi() > primitive_align.abi() {
+            Some(align.abi() as u32)
+        } else {
+            None
+        }
+    }
+
     pub fn field_offset<C: HasDataLayout>(&self,
                                           cx: C,
                                           i: usize,
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index ab1a06aeacd..5be73542b93 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -37,6 +37,7 @@ use serialize::{self, Encodable, Encoder};
 use std::borrow::Cow;
 use std::cell::{Cell, RefCell, Ref};
 use std::collections::BTreeMap;
+use std::cmp;
 use std::hash::{Hash, Hasher};
 use std::ops::Deref;
 use std::rc::Rc;
@@ -71,7 +72,6 @@ pub use self::sty::InferTy::*;
 pub use self::sty::Region::*;
 pub use self::sty::TypeVariants::*;
 
-pub use self::contents::TypeContents;
 pub use self::context::{TyCtxt, GlobalArenas, tls};
 pub use self::context::{Lift, TypeckTables};
 
@@ -99,7 +99,6 @@ pub mod walk;
 pub mod wf;
 pub mod util;
 
-mod contents;
 mod context;
 mod flags;
 mod instance;
@@ -425,6 +424,10 @@ bitflags! {
         const IS_SIZED          = 1 << 17,
         const MOVENESS_CACHED   = 1 << 18,
         const MOVES_BY_DEFAULT  = 1 << 19,
+        const FREEZENESS_CACHED = 1 << 20,
+        const IS_FREEZE         = 1 << 21,
+        const NEEDS_DROP_CACHED = 1 << 22,
+        const NEEDS_DROP        = 1 << 23,
     }
 }
 
@@ -1181,6 +1184,9 @@ pub struct ParameterEnvironment<'tcx> {
 
     /// A cache for `type_is_sized`
     pub is_sized_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+
+    /// A cache for `type_is_freeze`
+    pub is_freeze_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
 }
 
 impl<'a, 'tcx> ParameterEnvironment<'tcx> {
@@ -1195,6 +1201,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
             free_id_outlive: self.free_id_outlive,
             is_copy_cache: RefCell::new(FxHashMap()),
             is_sized_cache: RefCell::new(FxHashMap()),
+            is_freeze_cache: RefCell::new(FxHashMap()),
         }
     }
 
@@ -1464,10 +1471,12 @@ impl_stable_hash_for!(struct ReprFlags {
 #[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)]
 pub struct ReprOptions {
     pub int: Option<attr::IntType>,
+    pub align: u16,
     pub flags: ReprFlags,
 }
 
 impl_stable_hash_for!(struct ReprOptions {
+    align,
     int,
     flags
 });
@@ -1476,7 +1485,7 @@ impl ReprOptions {
     pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions {
         let mut flags = ReprFlags::empty();
         let mut size = None;
-
+        let mut max_align = 0;
         for attr in tcx.get_attrs(did).iter() {
             for r in attr::find_repr_attrs(tcx.sess.diagnostic(), attr) {
                 flags.insert(match r {
@@ -1487,6 +1496,10 @@ impl ReprOptions {
                         size = Some(i);
                         ReprFlags::empty()
                     },
+                    attr::ReprAlign(align) => {
+                        max_align = cmp::max(align, max_align);
+                        ReprFlags::empty()
+                    },
                 });
             }
         }
@@ -1500,7 +1513,7 @@ impl ReprOptions {
         if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.item_path_str(did))) {
             flags.insert(ReprFlags::IS_LINEAR);
         }
-        ReprOptions { int: size, flags: flags }
+        ReprOptions { int: size, align: max_align, flags: flags }
     }
 
     #[inline]
@@ -2375,40 +2388,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         Some(self.item_mir(did))
     }
 
-    /// If `type_needs_drop` returns true, then `ty` is definitely
-    /// non-copy and *might* have a destructor attached; if it returns
-    /// false, then `ty` definitely has no destructor (i.e. no drop glue).
-    ///
-    /// (Note that this implies that if `ty` has a destructor attached,
-    /// then `type_needs_drop` will definitely return `true` for `ty`.)
-    pub fn type_needs_drop_given_env(self,
-                                     ty: Ty<'gcx>,
-                                     param_env: &ty::ParameterEnvironment<'gcx>) -> bool {
-        // Issue #22536: We first query type_moves_by_default.  It sees a
-        // normalized version of the type, and therefore will definitely
-        // know whether the type implements Copy (and thus needs no
-        // cleanup/drop/zeroing) ...
-        let tcx = self.global_tcx();
-        let implements_copy = !ty.moves_by_default(tcx, param_env, DUMMY_SP);
-
-        if implements_copy { return false; }
-
-        // ... (issue #22536 continued) but as an optimization, still use
-        // prior logic of asking if the `needs_drop` bit is set; we need
-        // not zero non-Copy types if they have no destructor.
-
-        // FIXME(#22815): Note that calling `ty::type_contents` is a
-        // conservative heuristic; it may report that `needs_drop` is set
-        // when actual type does not actually have a destructor associated
-        // with it. But since `ty` absolutely did not have the `Copy`
-        // bound attached (see above), it is sound to treat it as having a
-        // destructor (e.g. zero its memory on move).
-
-        let contents = ty.type_contents(tcx);
-        debug!("type_needs_drop ty={:?} contents={:?}", ty, contents);
-        contents.needs_drop(tcx)
-    }
-
     /// Get the attributes of a definition.
     pub fn get_attrs(self, did: DefId) -> Cow<'gcx, [ast::Attribute]> {
         if let Some(id) = self.hir.as_local_node_id(did) {
@@ -2531,6 +2510,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             free_id_outlive: free_id_outlive,
             is_copy_cache: RefCell::new(FxHashMap()),
             is_sized_cache: RefCell::new(FxHashMap()),
+            is_freeze_cache: RefCell::new(FxHashMap()),
         }
     }
 
@@ -2603,6 +2583,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             free_id_outlive: free_id_outlive,
             is_copy_cache: RefCell::new(FxHashMap()),
             is_sized_cache: RefCell::new(FxHashMap()),
+            is_freeze_cache: RefCell::new(FxHashMap()),
         };
 
         let cause = traits::ObligationCause::misc(span, free_id_outlive.node_id(&self.region_maps));
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 5334ee2835d..49d79f6545e 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -21,7 +21,7 @@ use ty::fold::TypeVisitor;
 use ty::layout::{Layout, LayoutError};
 use ty::TypeVariants::*;
 use util::common::ErrorReported;
-use util::nodemap::FxHashMap;
+use util::nodemap::{FxHashMap, FxHashSet};
 use middle::lang_items;
 
 use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
@@ -655,6 +655,165 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
         result
     }
 
+    /// Returns `true` if and only if there are no `UnsafeCell`s
+    /// nested within the type (ignoring `PhantomData` or pointers).
+    #[inline]
+    pub fn is_freeze(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                     param_env: &ParameterEnvironment<'tcx>,
+                     span: Span) -> bool
+    {
+        if self.flags.get().intersects(TypeFlags::FREEZENESS_CACHED) {
+            return self.flags.get().intersects(TypeFlags::IS_FREEZE);
+        }
+
+        self.is_freeze_uncached(tcx, param_env, span)
+    }
+
+    fn is_freeze_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          param_env: &ParameterEnvironment<'tcx>,
+                          span: Span) -> bool {
+        assert!(!self.needs_infer());
+
+        // Fast-path for primitive types
+        let result = match self.sty {
+            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
+            TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
+            TyStr | TyNever => Some(true),
+
+            TyArray(..) | TySlice(_) |
+            TyTuple(..) | TyClosure(..) | TyAdt(..) |
+            TyDynamic(..) | TyProjection(..) | TyParam(..) |
+            TyInfer(..) | TyAnon(..) | TyError => None
+        }.unwrap_or_else(|| {
+            self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::FreezeTraitLangItem),
+                              &param_env.is_freeze_cache, span) });
+
+        if !self.has_param_types() && !self.has_self_ty() {
+            self.flags.set(self.flags.get() | if result {
+                TypeFlags::FREEZENESS_CACHED | TypeFlags::IS_FREEZE
+            } else {
+                TypeFlags::FREEZENESS_CACHED
+            });
+        }
+
+        result
+    }
+
+    /// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely
+    /// non-copy and *might* have a destructor attached; if it returns
+    /// `false`, then `ty` definitely has no destructor (i.e. no drop glue).
+    ///
+    /// (Note that this implies that if `ty` has a destructor attached,
+    /// then `needs_drop` will definitely return `true` for `ty`.)
+    #[inline]
+    pub fn needs_drop(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    param_env: &ty::ParameterEnvironment<'tcx>) -> bool {
+        if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
+            return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
+        }
+
+        self.needs_drop_uncached(tcx, param_env, &mut FxHashSet())
+    }
+
+    fn needs_drop_inner(&'tcx self,
+                        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                        param_env: &ty::ParameterEnvironment<'tcx>,
+                        stack: &mut FxHashSet<Ty<'tcx>>)
+                        -> bool {
+        if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
+            return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
+        }
+
+        // This should be reported as an error by `check_representable`.
+        //
+        // Consider the type as not needing drop in the meanwhile to avoid
+        // further errors.
+        if let Some(_) = stack.replace(self) {
+            return false;
+        }
+
+        let needs_drop = self.needs_drop_uncached(tcx, param_env, stack);
+
+        // "Pop" the cycle detection "stack".
+        stack.remove(self);
+
+        needs_drop
+    }
+
+    fn needs_drop_uncached(&'tcx self,
+                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                           param_env: &ty::ParameterEnvironment<'tcx>,
+                           stack: &mut FxHashSet<Ty<'tcx>>)
+                           -> bool {
+        assert!(!self.needs_infer());
+
+        let result = match self.sty {
+            // Fast-path for primitive types
+            ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
+            ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
+            ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
+            ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
+
+            // Issue #22536: We first query type_moves_by_default.  It sees a
+            // normalized version of the type, and therefore will definitely
+            // know whether the type implements Copy (and thus needs no
+            // cleanup/drop/zeroing) ...
+            _ if !self.moves_by_default(tcx, param_env, DUMMY_SP) => false,
+
+            // ... (issue #22536 continued) but as an optimization, still use
+            // prior logic of asking for the structural "may drop".
+
+            // FIXME(#22815): Note that this is a conservative heuristic;
+            // it may report that the type "may drop" when actual type does
+            // not actually have a destructor associated with it. But since
+            // the type absolutely did not have the `Copy` bound attached
+            // (see above), it is sound to treat it as having a destructor.
+
+            // User destructors are the only way to have concrete drop types.
+            ty::TyAdt(def, _) if def.has_dtor(tcx) => true,
+
+            // Can refer to a type which may drop.
+            // FIXME(eddyb) check this against a ParameterEnvironment.
+            ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) |
+            ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true,
+
+            // Structural recursion.
+            ty::TyArray(ty, _) | ty::TySlice(ty) => {
+                ty.needs_drop_inner(tcx, param_env, stack)
+            }
+
+            ty::TyClosure(def_id, ref substs) => {
+                substs.upvar_tys(def_id, tcx)
+                    .any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
+            }
+
+            ty::TyTuple(ref tys, _) => {
+                tys.iter().any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
+            }
+
+            // unions don't have destructors regardless of the child types
+            ty::TyAdt(def, _) if def.is_union() => false,
+
+            ty::TyAdt(def, substs) => {
+                def.variants.iter().any(|v| {
+                    v.fields.iter().any(|f| {
+                        f.ty(tcx, substs).needs_drop_inner(tcx, param_env, stack)
+                    })
+                })
+            }
+        };
+
+        if !self.has_param_types() && !self.has_self_ty() {
+            self.flags.set(self.flags.get() | if result {
+                TypeFlags::NEEDS_DROP_CACHED | TypeFlags::NEEDS_DROP
+            } else {
+                TypeFlags::NEEDS_DROP_CACHED
+            });
+        }
+
+        result
+    }
+
     #[inline]
     pub fn layout<'lcx>(&'tcx self, infcx: &InferCtxt<'a, 'tcx, 'lcx>)
                         -> Result<&'tcx Layout, LayoutError<'tcx>> {
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index ca6894a7b70..e60fdc386ce 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -162,6 +162,7 @@ supported_targets! {
     ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
 
     ("i686-linux-android", i686_linux_android),
+    ("x86_64-linux-android", x86_64_linux_android),
     ("arm-linux-androideabi", arm_linux_androideabi),
     ("armv7-linux-androideabi", armv7_linux_androideabi),
     ("aarch64-linux-android", aarch64_linux_android),
diff --git a/src/librustc_back/target/x86_64_linux_android.rs b/src/librustc_back/target/x86_64_linux_android.rs
new file mode 100644
index 00000000000..75cf3e12438
--- /dev/null
+++ b/src/librustc_back/target/x86_64_linux_android.rs
@@ -0,0 +1,34 @@
+// 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.
+
+use LinkerFlavor;
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::android_base::opts();
+    base.cpu = "x86-64".to_string();
+    // https://developer.android.com/ndk/guides/abis.html#86-64
+    base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".to_string();
+    base.max_atomic_width = Some(64);
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
+
+    Ok(Target {
+        llvm_target: "x86_64-linux-android".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "android".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs
index dc01cbe5e76..de5613dbfaa 100644
--- a/src/librustc_borrowck/borrowck/mir/mod.rs
+++ b/src/librustc_borrowck/borrowck/mir/mod.rs
@@ -322,7 +322,7 @@ fn on_all_drop_children_bits<'a, 'tcx, F>(
         let ty = lvalue.ty(mir, tcx).to_ty(tcx);
         debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, lvalue, ty);
 
-        if tcx.type_needs_drop_given_env(ty, &ctxt.param_env) {
+        if ty.needs_drop(tcx, &ctxt.param_env) {
             each_child(child);
         } else {
             debug!("on_all_drop_children_bits - skipping")
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index a52628ceb47..64652bb308b 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -263,6 +263,41 @@ impl EmitterWriter {
 
         draw_col_separator(buffer, line_offset, width_offset - 2);
 
+        // Special case when there's only one annotation involved, it is the start of a multiline
+        // span and there's no text at the beginning of the code line. Instead of doing the whole
+        // graph:
+        //
+        // 2 |   fn foo() {
+        //   |  _^
+        // 3 | |
+        // 4 | | }
+        //   | |_^ test
+        //
+        // we simplify the output to:
+        //
+        // 2 | / fn foo() {
+        // 3 | |
+        // 4 | | }
+        //   | |_^ test
+        if line.annotations.len() == 1 {
+            if let Some(ref ann) = line.annotations.get(0) {
+                if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
+                    if source_string[0..ann.start_col].trim() == "" {
+                        let style = if ann.is_primary {
+                            Style::UnderlinePrimary
+                        } else {
+                            Style::UnderlineSecondary
+                        };
+                        buffer.putc(line_offset,
+                                    width_offset + depth - 1,
+                                    '/',
+                                    style);
+                        return vec![(depth, style)];
+                    }
+                }
+            }
+        }
+
         // We want to display like this:
         //
         //      vec.push(vec.pop().unwrap());
@@ -355,10 +390,8 @@ impl EmitterWriter {
         for (i, annotation) in annotations.iter().enumerate() {
             for (j, next) in annotations.iter().enumerate() {
                 if overlaps(next, annotation, 0)  // This label overlaps with another one and both
-                    && !annotation.is_line()      // take space (they have text and are not
-                    && !next.is_line()            // multiline lines).
-                    && annotation.has_label()
-                    && j > i
+                    && annotation.has_label()     // take space (they have text and are not
+                    && j > i                      // multiline lines).
                     && p == 0  // We're currently on the first line, move the label one line down
                 {
                     // This annotation needs a new line in the output.
@@ -374,7 +407,7 @@ impl EmitterWriter {
                     } else {
                         0
                     };
-                    if overlaps(next, annotation, l) // Do not allow two labels to be in the same
+                    if (overlaps(next, annotation, l) // Do not allow two labels to be in the same
                                                      // line if they overlap including padding, to
                                                      // avoid situations like:
                                                      //
@@ -383,11 +416,18 @@ impl EmitterWriter {
                                                      //      |      |
                                                      //      fn_spanx_span
                                                      //
-                        && !annotation.is_line()     // Do not add a new line if this annotation
-                        && !next.is_line()           // or the next are vertical line placeholders.
                         && annotation.has_label()    // Both labels must have some text, otherwise
-                        && next.has_label()          // they are not overlapping.
+                        && next.has_label())         // they are not overlapping.
+                                                     // Do not add a new line if this annotation
+                                                     // or the next are vertical line placeholders.
+                        || (annotation.takes_space() // If either this or the next annotation is
+                            && next.has_label())     // multiline start/end, move it to a new line
+                        || (annotation.has_label()   // so as not to overlap the orizontal lines.
+                            && next.takes_space())
+                        || (annotation.takes_space()
+                            && next.takes_space())
                     {
+                        // This annotation needs a new line in the output.
                         p += 1;
                         break;
                     }
@@ -397,6 +437,7 @@ impl EmitterWriter {
                 line_len = p;
             }
         }
+
         if line_len != 0 {
             line_len += 1;
         }
@@ -480,7 +521,7 @@ impl EmitterWriter {
             };
             let pos = pos + 1;
 
-            if pos > 1 && annotation.has_label() {
+            if pos > 1 && (annotation.has_label() || annotation.takes_space()) {
                 for p in line_offset + 1..line_offset + pos + 1 {
                     buffer.putc(p,
                                 code_offset + annotation.start_col,
@@ -514,12 +555,12 @@ impl EmitterWriter {
         // After this we will have:
         //
         // 2 |   fn foo() {
-        //   |  __________ starting here...
+        //   |  __________
         //   |      |
         //   |      something about `foo`
         // 3 |
         // 4 |   }
-        //   |  _  ...ending here: test
+        //   |  _  test
         for &(pos, annotation) in &annotations_position {
             let style = if annotation.is_primary {
                 Style::LabelPrimary
@@ -557,12 +598,12 @@ impl EmitterWriter {
         // After this we will have:
         //
         // 2 |   fn foo() {
-        //   |  ____-_____^ starting here...
+        //   |  ____-_____^
         //   |      |
         //   |      something about `foo`
         // 3 |
         // 4 |   }
-        //   |  _^  ...ending here: test
+        //   |  _^  test
         for &(_, annotation) in &annotations_position {
             let (underline, style) = if annotation.is_primary {
                 ('^', Style::UnderlinePrimary)
diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs
index 9aa4682e1af..7401ead2208 100644
--- a/src/librustc_errors/snippet.rs
+++ b/src/librustc_errors/snippet.rs
@@ -63,7 +63,7 @@ impl MultilineAnnotation {
             start_col: self.start_col,
             end_col: self.start_col + 1,
             is_primary: self.is_primary,
-            label: Some("starting here...".to_owned()),
+            label: None,
             annotation_type: AnnotationType::MultilineStart(self.depth)
         }
     }
@@ -73,10 +73,7 @@ impl MultilineAnnotation {
             start_col: self.end_col - 1,
             end_col: self.end_col,
             is_primary: self.is_primary,
-            label: match self.label {
-                Some(ref label) => Some(format!("...ending here: {}", label)),
-                None => Some("...ending here".to_owned()),
-            },
+            label: self.label.clone(),
             annotation_type: AnnotationType::MultilineEnd(self.depth)
         }
     }
@@ -106,9 +103,9 @@ pub enum AnnotationType {
     // Each of these corresponds to one part of the following diagram:
     //
     //     x |   foo(1 + bar(x,
-    //       |  _________^ starting here...           < MultilineStart
-    //     x | |             y),                      < MultilineLine
-    //       | |______________^ ...ending here: label < MultilineEnd
+    //       |  _________^              < MultilineStart
+    //     x | |             y),        < MultilineLine
+    //       | |______________^ label   < MultilineEnd
     //     x |       z);
     /// Annotation marking the first character of a fully shown multiline span
     MultilineStart(usize),
@@ -189,6 +186,15 @@ impl Annotation {
             false
         }
     }
+
+    pub fn takes_space(&self) -> bool {
+        // Multiline annotations always have to keep vertical space.
+        match self.annotation_type {
+            AnnotationType::MultilineStart(_) |
+            AnnotationType::MultilineEnd(_) => true,
+            _ => false,
+        }
+    }
 }
 
 #[derive(Debug)]
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 0ee9d4a42c7..1c69f3cff17 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1152,7 +1152,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
             let param_env = &ty::ParameterEnvironment::for_item(ctx.tcx, item.id);
             for field in vdata.fields() {
                 let field_ty = ctx.tcx.item_type(ctx.tcx.hir.local_def_id(field.id));
-                if ctx.tcx.type_needs_drop_given_env(field_ty, param_env) {
+                if field_ty.needs_drop(ctx.tcx, param_env) {
                     ctx.span_lint(UNIONS_WITH_DROP_FIELDS,
                                   field.span,
                                   "union contains a field with possibly non-trivial drop code, \
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 5f9fb8e1b12..db9da2a280b 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -168,7 +168,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
                   type with inference types/regions",
                  ty);
         });
-        self.tcx.type_needs_drop_given_env(ty, &self.infcx.parameter_environment)
+        ty.needs_drop(self.tcx.global_tcx(), &self.infcx.parameter_environment)
     }
 
     pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index ac2bdaad24f..892d67ac237 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -357,7 +357,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     // a regular goto.
                     let ty = location.ty(&callee_mir, tcx).subst(tcx, callsite.substs);
                     let ty = ty.to_ty(tcx);
-                    if tcx.type_needs_drop_given_env(ty, &param_env) {
+                    if ty.needs_drop(tcx, &param_env) {
                         cost += CALL_PENALTY;
                         if let Some(unwind) = unwind {
                             work_list.push(unwind);
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 1313b24fa74..526c1488ab4 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -80,10 +80,10 @@ impl<'a, 'tcx> Qualif {
     fn restrict(&mut self, ty: Ty<'tcx>,
                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 param_env: &ty::ParameterEnvironment<'tcx>) {
-        if !ty.type_contents(tcx).interior_unsafe() {
+        if ty.is_freeze(tcx, param_env, DUMMY_SP) {
             *self = *self - Qualif::MUTABLE_INTERIOR;
         }
-        if !tcx.type_needs_drop_given_env(ty, param_env) {
+        if !ty.needs_drop(tcx, param_env) {
             *self = *self - Qualif::NEEDS_DROP;
         }
     }
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 04a1fc891cf..07025fcfdb9 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -277,8 +277,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
 
         let mut fields = fields;
         fields.retain(|&(ref lvalue, _)| {
-            self.tcx().type_needs_drop_given_env(
-                self.lvalue_ty(lvalue), self.elaborator.param_env())
+            self.lvalue_ty(lvalue).needs_drop(self.tcx(), self.elaborator.param_env())
         });
 
         debug!("drop_ladder - fields needing drop: {:?}", fields);
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 2c4439f80a2..fdb67522133 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -46,7 +46,7 @@ use rustc::lint::builtin::CONST_ERR;
 
 use rustc::hir::{self, PatKind, RangeEnd};
 use syntax::ast;
-use syntax_pos::Span;
+use syntax_pos::{Span, DUMMY_SP};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 
 use std::collections::hash_map::Entry;
@@ -85,11 +85,11 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
 
     // Adds the worst effect out of all the values of one type.
     fn add_type(&mut self, ty: Ty<'gcx>) {
-        if ty.type_contents(self.tcx).interior_unsafe() {
+        if !ty.is_freeze(self.tcx, &self.param_env, DUMMY_SP) {
             self.promotable = false;
         }
 
-        if self.tcx.type_needs_drop_given_env(ty, &self.param_env) {
+        if ty.needs_drop(self.tcx, &self.param_env) {
             self.promotable = false;
         }
     }
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index c4fdc46d030..998e392b1f9 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -553,7 +553,7 @@ impl<'a, 'tcx> ArgType<'tcx> {
                 //   bitcasting to the struct type yields invalid cast errors.
 
                 // We instead thus allocate some scratch space...
-                let llscratch = bcx.alloca(ty, "abi_cast");
+                let llscratch = bcx.alloca(ty, "abi_cast", None);
                 base::Lifetime::Start.call(bcx, llscratch);
 
                 // ...where we first store the value...
@@ -746,13 +746,13 @@ impl<'a, 'tcx> FnType<'tcx> {
                 // `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as
                 // both `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely
                 // on memory dependencies rather than pointer equality
-                let interior_unsafe = mt.ty.type_contents(ccx.tcx()).interior_unsafe();
+                let is_freeze = ccx.shared().type_is_freeze(mt.ty);
 
-                if mt.mutbl != hir::MutMutable && !interior_unsafe {
+                if mt.mutbl != hir::MutMutable && is_freeze {
                     arg.attrs.set(ArgAttribute::NoAlias);
                 }
 
-                if mt.mutbl == hir::MutImmutable && !interior_unsafe {
+                if mt.mutbl == hir::MutImmutable && is_freeze {
                     arg.attrs.set(ArgAttribute::ReadOnly);
                 }
 
diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs
index 87ca410dece..d1c1dd7436a 100644
--- a/src/librustc_trans/adt.rs
+++ b/src/librustc_trans/adt.rs
@@ -90,12 +90,12 @@ pub fn compute_fields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>,
 /// and fill in the actual contents in a second pass to prevent
 /// unbounded recursion; see also the comments in `trans::type_of`.
 pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
-    generic_type_of(cx, t, None, false, false)
+    generic_type_of(cx, t, None)
 }
 
 pub fn incomplete_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                     t: Ty<'tcx>, name: &str) -> Type {
-    generic_type_of(cx, t, Some(name), false, false)
+    generic_type_of(cx, t, Some(name))
 }
 
 pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
@@ -114,7 +114,7 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 _ => unreachable!()
             };
             let fields = compute_fields(cx, t, nonnull_variant_index as usize, true);
-            llty.set_struct_body(&struct_llfields(cx, &fields, nonnull_variant, false, false),
+            llty.set_struct_body(&struct_llfields(cx, &fields, nonnull_variant),
                                  packed)
         },
         _ => bug!("This function cannot handle {} with layout {:#?}", t, l)
@@ -123,12 +123,9 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
 fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                              t: Ty<'tcx>,
-                             name: Option<&str>,
-                             sizing: bool,
-                             dst: bool) -> Type {
+                             name: Option<&str>) -> Type {
     let l = cx.layout_of(t);
-    debug!("adt::generic_type_of t: {:?} name: {:?} sizing: {} dst: {}",
-           t, name, sizing, dst);
+    debug!("adt::generic_type_of t: {:?} name: {:?}", t, name);
     match *l {
         layout::CEnum { discr, .. } => Type::from_integer(cx, discr),
         layout::RawNullablePointer { nndiscr, .. } => {
@@ -148,11 +145,10 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let fields = compute_fields(cx, t, nndiscr as usize, false);
             match name {
                 None => {
-                    Type::struct_(cx, &struct_llfields(cx, &fields, nonnull, sizing, dst),
+                    Type::struct_(cx, &struct_llfields(cx, &fields, nonnull),
                                   nonnull.packed)
                 }
                 Some(name) => {
-                    assert_eq!(sizing, false);
                     Type::named_struct(cx, name)
                 }
             }
@@ -163,13 +159,12 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let fields = compute_fields(cx, t, 0, true);
             match name {
                 None => {
-                    let fields = struct_llfields(cx, &fields, &variant, sizing, dst);
+                    let fields = struct_llfields(cx, &fields, &variant);
                     Type::struct_(cx, &fields, variant.packed)
                 }
                 Some(name) => {
                     // Hypothesis: named_struct's can never need a
                     // drop flag. (... needs validation.)
-                    assert_eq!(sizing, false);
                     Type::named_struct(cx, name)
                 }
             }
@@ -190,7 +185,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
         }
-        layout::General { discr, size, align, .. } => {
+        layout::General { discr, size, align, primitive_align, .. } => {
             // We need a representation that has:
             // * The alignment of the most-aligned field
             // * The size of the largest variant (rounded up to that alignment)
@@ -203,14 +198,15 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             // of the size.
             let size = size.bytes();
             let align = align.abi();
+            let primitive_align = primitive_align.abi();
             assert!(align <= std::u32::MAX as u64);
             let discr_ty = Type::from_integer(cx, discr);
             let discr_size = discr.size().bytes();
             let padded_discr_size = roundup(discr_size, align as u32);
             let variant_part_size = size-padded_discr_size;
-            let variant_fill = union_fill(cx, variant_part_size, align);
+            let variant_fill = union_fill(cx, variant_part_size, primitive_align);
 
-            assert_eq!(machine::llalign_of_min(cx, variant_fill), align as u32);
+            assert_eq!(machine::llalign_of_min(cx, variant_fill), primitive_align as u32);
             assert_eq!(padded_discr_size % discr_size, 0); // Ensure discr_ty can fill pad evenly
             let fields: Vec<Type> =
                 [discr_ty,
@@ -245,15 +241,60 @@ fn union_fill(cx: &CrateContext, size: u64, align: u64) -> Type {
 }
 
 
-fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fields: &Vec<Ty<'tcx>>,
-                             variant: &layout::Struct,
-                             sizing: bool, _dst: bool) -> Vec<Type> {
-    let fields = variant.field_index_by_increasing_offset().map(|i| fields[i as usize]);
-    if sizing {
-        bug!()
+// Double index to account for padding (FieldPath already uses `Struct::memory_index`)
+fn struct_llfields_path(discrfield: &layout::FieldPath) -> Vec<usize> {
+    discrfield.iter().map(|&i| (i as usize) << 1).collect::<Vec<_>>()
+}
+
+
+// Lookup `Struct::memory_index` and double it to account for padding
+pub fn struct_llfields_index(variant: &layout::Struct, index: usize) -> usize {
+    (variant.memory_index[index] as usize) << 1
+}
+
+
+pub fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, field_tys: &Vec<Ty<'tcx>>,
+                             variant: &layout::Struct) -> Vec<Type> {
+    debug!("struct_llfields: variant: {:?}", variant);
+    let mut first_field = true;
+    let mut min_offset = 0;
+    let mut result: Vec<Type> = Vec::with_capacity(field_tys.len() * 2);
+    let field_iter = variant.field_index_by_increasing_offset().map(|i| {
+        (i, field_tys[i as usize], variant.offsets[i as usize].bytes()) });
+    for (index, ty, target_offset) in field_iter {
+        if first_field {
+            debug!("struct_llfields: {} ty: {} min_offset: {} target_offset: {}",
+                index, ty, min_offset, target_offset);
+            first_field = false;
+        } else {
+            assert!(target_offset >= min_offset);
+            let padding_bytes = if variant.packed { 0 } else { target_offset - min_offset };
+            result.push(Type::array(&Type::i8(cx), padding_bytes));
+            debug!("struct_llfields: {} ty: {} pad_bytes: {} min_offset: {} target_offset: {}",
+                index, ty, padding_bytes, min_offset, target_offset);
+        }
+        let llty = type_of::in_memory_type_of(cx, ty);
+        result.push(llty);
+        let layout = cx.layout_of(ty);
+        let target_size = layout.size(&cx.tcx().data_layout).bytes();
+        min_offset = target_offset + target_size;
+    }
+    if variant.sized && !field_tys.is_empty() {
+        if variant.stride().bytes() < min_offset {
+            bug!("variant: {:?} stride: {} min_offset: {}", variant, variant.stride().bytes(),
+            min_offset);
+        }
+        let padding_bytes = variant.stride().bytes() - min_offset;
+        debug!("struct_llfields: pad_bytes: {} min_offset: {} min_size: {} stride: {}\n",
+               padding_bytes, min_offset, variant.min_size.bytes(), variant.stride().bytes());
+        result.push(Type::array(&Type::i8(cx), padding_bytes));
+        assert!(result.len() == (field_tys.len() * 2));
     } else {
-        fields.map(|ty| type_of::in_memory_type_of(cx, ty)).collect()
+        debug!("struct_llfields: min_offset: {} min_size: {} stride: {}\n",
+               min_offset, variant.min_size.bytes(), variant.stride().bytes());
     }
+
+    result
 }
 
 pub fn is_discr_signed<'tcx>(l: &layout::Layout) -> bool {
@@ -309,8 +350,8 @@ fn struct_wrapped_nullable_bitdiscr(
     scrutinee: ValueRef,
     alignment: Alignment,
 ) -> ValueRef {
-    let llptrptr = bcx.gepi(scrutinee,
-        &discrfield.iter().map(|f| *f as usize).collect::<Vec<_>>());
+    let path = struct_llfields_path(discrfield);
+    let llptrptr = bcx.gepi(scrutinee, &path);
     let llptr = bcx.load(llptrptr, alignment.to_align());
     let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
     bcx.icmp(cmp, llptr, C_null(val_ty(llptr)))
@@ -380,7 +421,7 @@ pub fn trans_set_discr<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, val: Valu
                     let align = C_i32(bcx.ccx, nonnull.align.abi() as i32);
                     base::call_memset(bcx, llptr, fill_byte, size, align, false);
                 } else {
-                    let path = discrfield.iter().map(|&i| i as usize).collect::<Vec<_>>();
+                    let path = struct_llfields_path(discrfield);
                     let llptrptr = bcx.gepi(val, &path);
                     let llptrty = val_ty(llptrptr).element_type();
                     bcx.store(C_null(llptrty), llptrptr, None);
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index 8b1010d89fd..5103ca5c5e1 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -477,24 +477,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn alloca(&self, ty: Type, name: &str) -> ValueRef {
+    pub fn alloca(&self, ty: Type, name: &str, align: Option<u32>) -> ValueRef {
         let builder = Builder::with_ccx(self.ccx);
         builder.position_at_start(unsafe {
             llvm::LLVMGetFirstBasicBlock(self.llfn())
         });
-        builder.dynamic_alloca(ty, name)
+        builder.dynamic_alloca(ty, name, align)
     }
 
-    pub fn dynamic_alloca(&self, ty: Type, name: &str) -> ValueRef {
+    pub fn dynamic_alloca(&self, ty: Type, name: &str, align: Option<u32>) -> ValueRef {
         self.count_insn("alloca");
         unsafe {
-            if name.is_empty() {
+            let alloca = if name.is_empty() {
                 llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
             } else {
                 let name = CString::new(name).unwrap();
                 llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(),
                                       name.as_ptr())
+            };
+            if let Some(align) = align {
+                llvm::LLVMSetAlignment(alloca, align as c_uint);
             }
+            alloca
         }
     }
 
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 7a53a03344f..eb3ac309be1 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -261,8 +261,7 @@ pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // As an optimization, all shared statics which do not have interior
         // mutability are placed into read-only memory.
         if m != hir::MutMutable {
-            let tcontents = ty.type_contents(ccx.tcx());
-            if !tcontents.interior_unsafe() {
+            if ccx.shared().type_is_freeze(ty) {
                 llvm::LLVMSetGlobalConstant(g, llvm::True);
             }
         }
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index c3770470bfd..1d1921bf7b9 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -392,13 +392,17 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
     }
 
     pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
-        self.tcx.type_needs_drop_given_env(ty, &self.empty_param_env)
+        ty.needs_drop(self.tcx, &self.empty_param_env)
     }
 
     pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
         ty.is_sized(self.tcx, &self.empty_param_env, DUMMY_SP)
     }
 
+    pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
+        ty.is_freeze(self.tcx, &self.empty_param_env, DUMMY_SP)
+    }
+
     pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet {
         &self.exported_symbols
     }
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index 7077eade611..54e20f590c6 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -778,7 +778,7 @@ fn trans_msvc_try<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
         //
         // More information can be found in libstd's seh.rs implementation.
         let i64p = Type::i64(ccx).ptr_to();
-        let slot = bcx.alloca(i64p, "slot");
+        let slot = bcx.alloca(i64p, "slot", None);
         bcx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(),
             None);
 
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 0f5a38ac7f6..d94d7f4430b 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -15,6 +15,7 @@ use rustc::ty::{self, TypeFoldable};
 use rustc::ty::layout::{self, LayoutTyper};
 use rustc::mir;
 use abi::{Abi, FnType, ArgType};
+use adt;
 use base::{self, Lifetime};
 use callee;
 use builder::Builder;
@@ -177,7 +178,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                     };
                     let llslot = match op.val {
                         Immediate(_) | Pair(..) => {
-                            let llscratch = bcx.alloca(ret.memory_ty(bcx.ccx), "ret");
+                            let llscratch = bcx.alloca(ret.memory_ty(bcx.ccx), "ret", None);
                             self.store_operand(&bcx, llscratch, None, op);
                             llscratch
                         }
@@ -630,7 +631,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
         let (mut llval, align, by_ref) = match op.val {
             Immediate(_) | Pair(..) => {
                 if arg.is_indirect() || arg.cast.is_some() {
-                    let llscratch = bcx.alloca(arg.memory_ty(bcx.ccx), "arg");
+                    let llscratch = bcx.alloca(arg.memory_ty(bcx.ccx), "arg", None);
                     self.store_operand(bcx, llscratch, None, op);
                     (llscratch, Alignment::AbiAligned, true)
                 } else {
@@ -642,7 +643,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't
                 // have scary latent bugs around.
 
-                let llscratch = bcx.alloca(arg.memory_ty(bcx.ccx), "arg");
+                let llscratch = bcx.alloca(arg.memory_ty(bcx.ccx), "arg", None);
                 base::memcpy_ty(bcx, llscratch, llval, op.ty, Some(1));
                 (llscratch, Alignment::AbiAligned, true)
             }
@@ -711,7 +712,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                     bug!("Not a tuple.");
                 };
                 for (n, &ty) in arg_types.iter().enumerate() {
-                    let mut elem = bcx.extract_value(llval, v.memory_index[n] as usize);
+                    let mut elem = bcx.extract_value(
+                        llval, adt::struct_llfields_index(v, n));
                     // Truncate bools to i1, if needed
                     if ty.is_bool() && common::val_ty(elem) != Type::i1(bcx.ccx) {
                         elem = bcx.trunc(elem, Type::i1(bcx.ccx));
@@ -750,7 +752,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
             slot
         } else {
             let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
-            let slot = bcx.alloca(llretty, "personalityslot");
+            let slot = bcx.alloca(llretty, "personalityslot", None);
             self.llpersonalityslot = Some(slot);
             slot
         }
diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs
index fc889604ab8..88e46b5c99a 100644
--- a/src/librustc_trans/mir/lvalue.rs
+++ b/src/librustc_trans/mir/lvalue.rs
@@ -97,7 +97,8 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
 
     pub fn alloca(bcx: &Builder<'a, 'tcx>, ty: Ty<'tcx>, name: &str) -> LvalueRef<'tcx> {
         debug!("alloca({:?}: {:?})", name, ty);
-        let tmp = bcx.alloca(type_of::type_of(bcx.ccx, ty), name);
+        let tmp = bcx.alloca(
+            type_of::type_of(bcx.ccx, ty), name, bcx.ccx.over_align_of(ty));
         assert!(!ty.has_param_types());
         Self::new_sized_ty(tmp, ty, Alignment::AbiAligned)
     }
@@ -131,11 +132,9 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
 
         let alignment = self.alignment | Alignment::from_packed(st.packed);
 
+        let llfields = adt::struct_llfields(ccx, fields, st);
         let ptr_val = if needs_cast {
-            let fields = st.field_index_by_increasing_offset().map(|i| {
-                type_of::in_memory_type_of(ccx, fields[i])
-            }).collect::<Vec<_>>();
-            let real_ty = Type::struct_(ccx, &fields[..], st.packed);
+            let real_ty = Type::struct_(ccx, &llfields[..], st.packed);
             bcx.pointercast(self.llval, real_ty.ptr_to())
         } else {
             self.llval
@@ -147,14 +146,16 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
         //   * Field is sized - pointer is properly aligned already
         if st.offsets[ix] == layout::Size::from_bytes(0) || st.packed ||
             bcx.ccx.shared().type_is_sized(fty) {
-                return (bcx.struct_gep(ptr_val, st.memory_index[ix] as usize), alignment);
+                return (bcx.struct_gep(
+                        ptr_val, adt::struct_llfields_index(st, ix)), alignment);
             }
 
         // If the type of the last field is [T] or str, then we don't need to do
         // any adjusments
         match fty.sty {
             ty::TySlice(..) | ty::TyStr => {
-                return (bcx.struct_gep(ptr_val, st.memory_index[ix] as usize), alignment);
+                return (bcx.struct_gep(
+                        ptr_val, adt::struct_llfields_index(st, ix)), alignment);
             }
             _ => ()
         }
@@ -163,7 +164,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
         if !self.has_extra() {
             debug!("Unsized field `{}`, of `{:?}` has no metadata for adjustment",
                 ix, Value(ptr_val));
-            return (bcx.struct_gep(ptr_val, ix), alignment);
+            return (bcx.struct_gep(ptr_val, adt::struct_llfields_index(st, ix)), alignment);
         }
 
         // We need to get the pointer manually now.
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index 3d8c5085462..d39a91405c1 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -524,7 +524,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
             // doesn't actually strip the offset when splitting the closure
             // environment into its components so it ends up out of bounds.
             let env_ptr = if !env_ref {
-                let alloc = bcx.alloca(common::val_ty(llval), "__debuginfo_env_ptr");
+                let alloc = bcx.alloca(common::val_ty(llval), "__debuginfo_env_ptr", None);
                 bcx.store(llval, alloc, None);
                 alloc
             } else {
diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs
index c31142323c8..6889b5064b6 100644
--- a/src/librustc_trans/mir/operand.rs
+++ b/src/librustc_trans/mir/operand.rs
@@ -15,6 +15,7 @@ use rustc::mir;
 use rustc::mir::tcx::LvalueTy;
 use rustc_data_structures::indexed_vec::Idx;
 
+use adt;
 use base;
 use common::{self, CrateContext, C_null};
 use builder::Builder;
@@ -134,6 +135,12 @@ impl<'a, 'tcx> OperandRef<'tcx> {
                 if common::val_ty(elem) == Type::i1(bcx.ccx) {
                     elem = bcx.zext(elem, Type::i8(bcx.ccx));
                 }
+                let layout = bcx.ccx.layout_of(self.ty);
+                let i = if let Layout::Univariant { ref variant, .. } = *layout {
+                    adt::struct_llfields_index(variant, i)
+                } else {
+                    i
+                };
                 llpair = bcx.insert_value(llpair, elem, i);
             }
             self.val = OperandValue::Immediate(llpair);
@@ -183,14 +190,17 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
             let (lldata, llextra) = base::load_fat_ptr(bcx, llval, align, ty);
             OperandValue::Pair(lldata, llextra)
         } else if common::type_is_imm_pair(bcx.ccx, ty) {
-            let f_align = match *bcx.ccx.layout_of(ty) {
-                Layout::Univariant { ref variant, .. } =>
-                    Alignment::from_packed(variant.packed) | align,
-                _ => align
+            let (ix0, ix1, f_align) = match *bcx.ccx.layout_of(ty) {
+                Layout::Univariant { ref variant, .. } => {
+                    (adt::struct_llfields_index(variant, 0),
+                    adt::struct_llfields_index(variant, 1),
+                    Alignment::from_packed(variant.packed) | align)
+                },
+                _ => (0, 1, align)
             };
             let [a_ty, b_ty] = common::type_pair_fields(bcx.ccx, ty).unwrap();
-            let a_ptr = bcx.struct_gep(llval, 0);
-            let b_ptr = bcx.struct_gep(llval, 1);
+            let a_ptr = bcx.struct_gep(llval, ix0);
+            let b_ptr = bcx.struct_gep(llval, ix1);
 
             OperandValue::Pair(
                 base::load_ty(bcx, a_ptr, f_align, a_ty),
@@ -302,17 +312,19 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 bcx.store(base::from_immediate(bcx, s), lldest, align);
             }
             OperandValue::Pair(a, b) => {
-                let f_align = match *bcx.ccx.layout_of(operand.ty) {
-                    Layout::Univariant { ref variant, .. } if variant.packed => {
-                        Some(1)
+                let (ix0, ix1, f_align) = match *bcx.ccx.layout_of(operand.ty) {
+                    Layout::Univariant { ref variant, .. } => {
+                        (adt::struct_llfields_index(variant, 0),
+                        adt::struct_llfields_index(variant, 1),
+                        if variant.packed { Some(1) } else { None })
                     }
-                    _ => align
+                    _ => (0, 1, align)
                 };
 
                 let a = base::from_immediate(bcx, a);
                 let b = base::from_immediate(bcx, b);
-                bcx.store(a, bcx.struct_gep(lldest, 0), f_align);
-                bcx.store(b, bcx.struct_gep(lldest, 1), f_align);
+                bcx.store(a, bcx.struct_gep(lldest, ix0), f_align);
+                bcx.store(b, bcx.struct_gep(lldest, ix1), f_align);
             }
         }
     }
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 98e9008f829..de1c1e492f3 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -130,10 +130,12 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                     _ => {
                         // If this is a tuple or closure, we need to translate GEP indices.
                         let layout = bcx.ccx.layout_of(dest.ty.to_ty(bcx.tcx()));
-                        let translation = if let Layout::Univariant { ref variant, .. } = *layout {
-                            Some(&variant.memory_index)
-                        } else {
-                            None
+                        let get_memory_index = |i| {
+                            if let Layout::Univariant { ref variant, .. } = *layout {
+                                adt::struct_llfields_index(variant, i)
+                            } else {
+                                i
+                            }
                         };
                         let alignment = dest.alignment;
                         for (i, operand) in operands.iter().enumerate() {
@@ -143,11 +145,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                                 // Note: perhaps this should be StructGep, but
                                 // note that in some cases the values here will
                                 // not be structs but arrays.
-                                let i = if let Some(ref t) = translation {
-                                    t[i] as usize
-                                } else {
-                                    i
-                                };
+                                let i = get_memory_index(i);
                                 let dest = bcx.gepi(dest.llval, &[0, i]);
                                 self.store_operand(&bcx, dest, alignment.to_align(), op);
                             }
diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs
index d4ab6b07828..9f9126ba83a 100644
--- a/src/librustc_trans/type_of.rs
+++ b/src/librustc_trans/type_of.rs
@@ -214,6 +214,16 @@ impl<'a, 'tcx> CrateContext<'a, 'tcx> {
     pub fn size_of(&self, ty: Ty<'tcx>) -> machine::llsize {
         self.layout_of(ty).size(self).bytes() as machine::llsize
     }
+
+    pub fn over_align_of(&self, t: Ty<'tcx>)
+                              -> Option<machine::llalign> {
+        let layout = self.layout_of(t);
+        if let Some(align) = layout.over_align(&self.tcx().data_layout) {
+            Some(align as machine::llalign)
+        } else {
+            None
+        }
+    }
 }
 
 fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> String {
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index c6a1f6cfc0d..d21b5f739bd 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -78,6 +78,7 @@ use errors::DiagnosticBuilder;
 use syntax::abi;
 use syntax::feature_gate;
 use syntax::ptr::P;
+use syntax_pos;
 
 use std::collections::VecDeque;
 use std::ops::Deref;
@@ -722,6 +723,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         Ok(target)
     }
 
+    /// Same as `try_coerce()`, but without side-effects.
+    pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
+        let source = self.resolve_type_vars_with_obligations(expr_ty);
+        debug!("coercion::can({:?} -> {:?})", source, target);
+
+        let cause = self.cause(syntax_pos::DUMMY_SP, ObligationCauseCode::ExprAssignable);
+        let coerce = Coerce::new(self, cause);
+        self.probe(|_| coerce.coerce::<hir::Expr>(&[], source, target)).is_ok()
+    }
+
     /// Given some expressions, their known unified type and another expression,
     /// tries to unify the types, potentially inserting coercions on any of the
     /// provided expressions and returns their LUB (aka "common supertype").
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index e922c7447ff..4cc3f2dacdf 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -10,15 +10,14 @@
 
 
 use check::FnCtxt;
-use rustc::ty::Ty;
-use rustc::infer::{InferOk};
+use rustc::infer::InferOk;
 use rustc::traits::ObligationCause;
 
 use syntax::ast;
 use syntax_pos::{self, Span};
 use rustc::hir;
 use rustc::hir::def::Def;
-use rustc::ty::{self, AssociatedItem};
+use rustc::ty::{self, Ty, AssociatedItem};
 use errors::DiagnosticBuilder;
 
 use super::method::probe;
@@ -80,18 +79,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         if let Err(e) = self.try_coerce(expr, checked_ty, self.diverges.get(), expected) {
             let cause = self.misc(expr.span);
             let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
-            let mode = probe::Mode::MethodCall;
-            let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
-                                                         mode,
-                                                         expected,
-                                                         checked_ty,
-                                                         ast::DUMMY_NODE_ID);
             let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
-            if suggestions.len() > 0 {
-                err.help(&format!("here are some functions which \
-                                   might fulfill your needs:\n{}",
-                                  self.get_best_match(&suggestions).join("\n")));
-            };
+            if let Some(suggestion) = self.check_ref(expr,
+                                                     checked_ty,
+                                                     expected) {
+                err.help(&suggestion);
+            } else {
+                let mode = probe::Mode::MethodCall;
+                let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
+                                                             mode,
+                                                             expected,
+                                                             checked_ty,
+                                                             ast::DUMMY_NODE_ID);
+                if suggestions.len() > 0 {
+                    err.help(&format!("here are some functions which \
+                                       might fulfill your needs:\n{}",
+                                      self.get_best_match(&suggestions).join("\n")));
+                }
+            }
             err.emit();
         }
     }
@@ -140,4 +145,60 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             _ => false,
         }
     }
+
+    /// This function is used to determine potential "simple" improvements or users' errors and
+    /// provide them useful help. For example:
+    ///
+    /// ```
+    /// fn some_fn(s: &str) {}
+    ///
+    /// let x = "hey!".to_owned();
+    /// some_fn(x); // error
+    /// ```
+    ///
+    /// No need to find every potential function which could make a coercion to transform a
+    /// `String` into a `&str` since a `&` would do the trick!
+    ///
+    /// In addition of this check, it also checks between references mutability state. If the
+    /// expected is mutable but the provided isn't, maybe we could just say "Hey, try with
+    /// `&mut`!".
+    fn check_ref(&self,
+                 expr: &hir::Expr,
+                 checked_ty: Ty<'tcx>,
+                 expected: Ty<'tcx>)
+                 -> Option<String> {
+        match (&expected.sty, &checked_ty.sty) {
+            (&ty::TyRef(_, _), &ty::TyRef(_, _)) => None,
+            (&ty::TyRef(_, mutability), _) => {
+                // Check if it can work when put into a ref. For example:
+                //
+                // ```
+                // fn bar(x: &mut i32) {}
+                //
+                // let x = 0u32;
+                // bar(&x); // error, expected &mut
+                // ```
+                let ref_ty = match mutability.mutbl {
+                    hir::Mutability::MutMutable => self.tcx.mk_mut_ref(
+                                                       self.tcx.mk_region(ty::ReStatic),
+                                                       checked_ty),
+                    hir::Mutability::MutImmutable => self.tcx.mk_imm_ref(
+                                                       self.tcx.mk_region(ty::ReStatic),
+                                                       checked_ty),
+                };
+                if self.can_coerce(ref_ty, expected) {
+                    if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
+                        return Some(format!("try with `{}{}`",
+                                            match mutability.mutbl {
+                                                hir::Mutability::MutMutable => "&mut ",
+                                                hir::Mutability::MutImmutable => "&",
+                                            },
+                                            &src));
+                    }
+                }
+                None
+            }
+            _ => None,
+        }
+    }
 }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 902cfb889f8..839af0fa670 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -953,6 +953,12 @@ fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     if def.repr.simd() {
         check_simd(tcx, span, def_id);
     }
+
+    // if struct is packed and not aligned, check fields for alignment.
+    // Checks for combining packed and align attrs on single struct are done elsewhere.
+    if tcx.lookup_adt_def(def_id).repr.packed() && tcx.lookup_adt_def(def_id).repr.align == 0 {
+        check_packed(tcx, span, def_id);
+    }
 }
 
 fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -1371,6 +1377,47 @@ pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId
     }
 }
 
+fn check_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) {
+    if check_packed_inner(tcx, def_id, &mut Vec::new()) {
+        struct_span_err!(tcx.sess, sp, E0588,
+            "packed struct cannot transitively contain a `[repr(align)]` struct").emit();
+    }
+}
+
+fn check_packed_inner<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                def_id: DefId,
+                                stack: &mut Vec<DefId>) -> bool {
+    let t = tcx.item_type(def_id);
+    if stack.contains(&def_id) {
+        debug!("check_packed_inner: {:?} is recursive", t);
+        return false;
+    }
+    match t.sty {
+        ty::TyAdt(def, substs) if def.is_struct() => {
+            if tcx.lookup_adt_def(def.did).repr.align > 0 {
+                return true;
+            }
+            // push struct def_id before checking fields
+            stack.push(def_id);
+            for field in &def.struct_variant().fields {
+                let f = field.ty(tcx, substs);
+                match f.sty {
+                    ty::TyAdt(def, _) => {
+                        if check_packed_inner(tcx, def.did, stack) {
+                            return true;
+                        }
+                    }
+                    _ => ()
+                }
+            }
+            // only need to pop if not early out
+            stack.pop();
+        }
+        _ => ()
+    }
+    false
+}
+
 #[allow(trivial_numeric_casts)]
 pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             sp: Span,
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 68afcae2b67..c50156fa5f2 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -4168,5 +4168,6 @@ register_diagnostics! {
            // but `{}` was found in the type `{}`
     E0567, // auto traits can not have type parameters
     E0568, // auto-traits can not have predicates,
+    E0588, // packed struct cannot transitively contain a `[repr(align)]` struct
     E0592, // duplicate definitions with name `{}`
 }
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index b02b60531d1..4bf856240f6 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -492,7 +492,7 @@ pub fn old_find_testable_code(doc: &str, tests: &mut ::test::Collector, position
                     text: *const hoedown_buffer,
                     lang: *const hoedown_buffer,
                     data: *const hoedown_renderer_data,
-                    line: libc::size_t) {
+                    _line: libc::size_t) {
         unsafe {
             if text.is_null() { return }
             let block_info = if lang.is_null() {
@@ -503,11 +503,15 @@ pub fn old_find_testable_code(doc: &str, tests: &mut ::test::Collector, position
                 LangString::parse(s)
             };
             if !block_info.rust { return }
+            let text = (*text).as_bytes();
             let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
             let tests = &mut *((*opaque).opaque as *mut ::test::Collector);
-            let line = tests.get_line() + line;
+            let text = str::from_utf8(text).unwrap();
+            let lines = text.lines().map(|l| {
+                stripped_filtered_line(l).unwrap_or(l)
+            });
             let filename = tests.get_filename();
-            tests.add_old_test(line, filename);
+            tests.add_old_test(lines.collect::<Vec<&str>>().join("\n"), filename);
         }
     }
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index d5b997001bb..0ca267bb82d 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -27,6 +27,7 @@
 #![feature(staged_api)]
 #![feature(test)]
 #![feature(unicode)]
+#![feature(vec_remove_item)]
 
 extern crate arena;
 extern crate getopts;
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index fb681b20065..3206b502107 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::collections::HashMap;
 use std::env;
 use std::ffi::OsString;
 use std::io::prelude::*;
@@ -381,7 +382,7 @@ fn partition_source(s: &str) -> (String, String) {
 pub struct Collector {
     pub tests: Vec<testing::TestDescAndFn>,
     // to be removed when hoedown will be definitely gone
-    pub old_tests: Vec<String>,
+    pub old_tests: HashMap<String, Vec<String>>,
     names: Vec<String>,
     cfgs: Vec<String>,
     libs: SearchPaths,
@@ -403,7 +404,7 @@ impl Collector {
                codemap: Option<Rc<CodeMap>>, filename: Option<String>) -> Collector {
         Collector {
             tests: Vec::new(),
-            old_tests: Vec::new(),
+            old_tests: HashMap::new(),
             names: Vec::new(),
             cfgs: cfgs,
             libs: libs,
@@ -432,9 +433,24 @@ impl Collector {
         }
     }
 
-    pub fn add_old_test(&mut self, line: usize, filename: String) {
-        let name = self.generate_name(line, &filename);
-        self.old_tests.push(name);
+    // to be removed once hoedown is gone
+    fn generate_name_beginning(&self, filename: &str) -> String {
+        if self.use_headers {
+            if let Some(ref header) = self.current_header {
+                format!("{} - {} (line", filename, header)
+            } else {
+                format!("{} - (line", filename)
+            }
+        } else {
+            format!("{} - {} (line", filename, self.names.join("::"))
+        }
+    }
+
+    pub fn add_old_test(&mut self, test: String, filename: String) {
+        let name_beg = self.generate_name_beginning(&filename);
+        let entry = self.old_tests.entry(name_beg)
+                                  .or_insert(Vec::new());
+        entry.push(test.trim().to_owned());
     }
 
     pub fn add_test(&mut self, test: String,
@@ -442,7 +458,14 @@ impl Collector {
                     as_test_harness: bool, compile_fail: bool, error_codes: Vec<String>,
                     line: usize, filename: String) {
         let name = self.generate_name(line, &filename);
-        if self.old_tests.iter().find(|&x| x == &name).is_none() {
+        let name_beg = self.generate_name_beginning(&filename);
+        let mut found = false;
+        // to be removed when hoedown is removed
+        let test = test.trim().to_owned();
+        if let Some(entry) = self.old_tests.get_mut(&name_beg) {
+            found = entry.remove_item(&test).is_some();
+        }
+        if !found {
             let _ = writeln!(&mut io::stderr(),
                              "WARNING: {} Code block is not currently run as a test, but will in \
                               future versions of rustdoc. Please ensure this code block is a \
diff --git a/src/libstd/os/android/raw.rs b/src/libstd/os/android/raw.rs
index 5e473a933a6..60ad8fcc54c 100644
--- a/src/libstd/os/android/raw.rs
+++ b/src/libstd/os/android/raw.rs
@@ -165,3 +165,66 @@ mod arch {
     }
 }
 
+#[cfg(target_arch = "x86_64")]
+mod arch {
+    use os::raw::{c_uint, c_long, c_ulong};
+    use os::unix::raw::{uid_t, gid_t};
+
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type dev_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type mode_t = u32;
+
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type blkcnt_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type blksize_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type ino_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type nlink_t = u32;
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type off_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type time_t = i64;
+
+    #[repr(C)]
+    #[derive(Clone)]
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub struct stat {
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_dev: dev_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ino: ino_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_nlink: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mode: c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_uid: uid_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_gid: gid_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_rdev: dev_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_size: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blksize: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blocks: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime_nsec: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime_nsec: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime_nsec: c_ulong,
+        __unused: [c_long; 3],
+    }
+}
+
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 812b65b61e7..15bc74a8340 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1189,8 +1189,13 @@ impl PathBuf {
     /// If [`self.file_name`] was [`None`], this is equivalent to pushing
     /// `file_name`.
     ///
+    /// Otherwise it is equivalent to calling [`pop`] and then pushing
+    /// `file_name`. The new path will be a sibling of the original path.
+    /// (That is, it will have the same parent.)
+    ///
     /// [`self.file_name`]: struct.PathBuf.html#method.file_name
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`pop`]: struct.PathBuf.html#method.pop
     ///
     /// # Examples
     ///
@@ -1725,7 +1730,10 @@ impl Path {
         })
     }
 
-    /// Returns the final component of the `Path`, if it is a normal file.
+    /// Returns the final component of the `Path`, if there is one.
+    ///
+    /// If the path is a normal file, this is the file name. If it's the path of a directory, this
+    /// is the directory name.
     ///
     /// Returns [`None`] If the path terminates in `..`.
     ///
@@ -1737,10 +1745,12 @@ impl Path {
     /// use std::path::Path;
     /// use std::ffi::OsStr;
     ///
-    /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt").file_name());
+    /// assert_eq!(Some(OsStr::new("bin")), Path::new("/usr/bin/").file_name());
+    /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("tmp/foo.txt").file_name());
     /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.").file_name());
     /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.//").file_name());
     /// assert_eq!(None, Path::new("foo.txt/..").file_name());
+    /// assert_eq!(None, Path::new("/").file_name());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn file_name(&self) -> Option<&OsStr> {
@@ -1926,6 +1936,9 @@ impl Path {
     ///
     /// let path = Path::new("/tmp/foo.txt");
     /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
+    ///
+    /// let path = Path::new("/tmp");
+    /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 3795c42f5ef..4ec9076de61 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -73,6 +73,15 @@ use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 /// spawning process and can itself be constructed using a builder-style
 /// interface.
 ///
+/// There is no implementation of [`Drop`] for child processes,
+/// so if you do not ensure the `Child` has exited then it will continue to
+/// run, even after the `Child` handle to the child process has gone out of
+/// scope.
+///
+/// Calling [`wait`](#method.wait) (or other functions that wrap around it) will make
+/// the parent process wait until the child has actually exited before
+/// continuing.
+///
 /// # Examples
 ///
 /// ```should_panic
@@ -89,17 +98,6 @@ use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 /// assert!(ecode.success());
 /// ```
 ///
-/// # Note
-///
-/// Take note that there is no implementation of [`Drop`] for child processes,
-/// so if you do not ensure the `Child` has exited then it will continue to
-/// run, even after the `Child` handle to the child process has gone out of
-/// scope.
-///
-/// Calling [`wait`][`wait`] (or other functions that wrap around it) will make
-/// the parent process wait until the child has actually exited before
-/// continuing.
-///
 /// [`Command`]: struct.Command.html
 /// [`Drop`]: ../../core/ops/trait.Drop.html
 /// [`wait`]: #method.wait
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 6f5f52ff1e9..82492d97627 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -147,6 +147,24 @@ impl NestedMetaItem {
         self.meta_item().and_then(|meta_item| meta_item.value_str())
     }
 
+    /// Returns a name and single literal value tuple of the MetaItem.
+    pub fn name_value_literal(&self) -> Option<(Name, &Lit)> {
+        self.meta_item().and_then(
+            |meta_item| meta_item.meta_item_list().and_then(
+                |meta_item_list| {
+                    if meta_item_list.len() == 1 {
+                        let nested_item = &meta_item_list[0];
+                        if nested_item.is_literal() {
+                            Some((meta_item.name(), nested_item.literal().unwrap()))
+                        } else {
+                            None
+                        }
+                    }
+                    else {
+                        None
+                    }}))
+    }
+
     /// Returns a MetaItem if self is a MetaItem with Kind Word.
     pub fn word(&self) -> Option<&MetaItem> {
         self.meta_item().and_then(|meta_item| if meta_item.is_word() {
@@ -931,6 +949,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                     continue
                 }
 
+                let mut recognised = false;
                 if let Some(mi) = item.word() {
                     let word = &*mi.name().as_str();
                     let hint = match word {
@@ -941,20 +960,43 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                         _ => match int_type_of_word(word) {
                             Some(ity) => Some(ReprInt(ity)),
                             None => {
-                                // Not a word we recognize
-                                span_err!(diagnostic, item.span, E0552,
-                                          "unrecognized representation hint");
                                 None
                             }
                         }
                     };
 
                     if let Some(h) = hint {
+                        recognised = true;
                         acc.push(h);
                     }
-                } else {
-                    span_err!(diagnostic, item.span, E0553,
-                              "unrecognized enum representation hint");
+                } else if let Some((name, value)) = item.name_value_literal() {
+                    if name == "align" {
+                        recognised = true;
+                        let mut align_error = None;
+                        if let ast::LitKind::Int(align, ast::LitIntType::Unsuffixed) = value.node {
+                            if align.is_power_of_two() {
+                                // rustc::ty::layout::Align restricts align to <= 32768
+                                if align <= 32768 {
+                                    acc.push(ReprAlign(align as u16));
+                                } else {
+                                    align_error = Some("larger than 32768");
+                                }
+                            } else {
+                                align_error = Some("not a power of two");
+                            }
+                        } else {
+                            align_error = Some("not an unsuffixed integer");
+                        }
+                        if let Some(align_error) = align_error {
+                            span_err!(diagnostic, item.span, E0589,
+                                      "invalid `repr(align)` attribute: {}", align_error);
+                        }
+                    }
+                }
+                if !recognised {
+                    // Not a word we recognize
+                    span_err!(diagnostic, item.span, E0552,
+                              "unrecognized representation hint");
                 }
             }
         }
@@ -986,6 +1028,7 @@ pub enum ReprAttr {
     ReprExtern,
     ReprPacked,
     ReprSimd,
+    ReprAlign(u16),
 }
 
 #[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
index 2d59051ec4a..01d1277ea62 100644
--- a/src/libsyntax/diagnostic_list.rs
+++ b/src/libsyntax/diagnostic_list.rs
@@ -287,10 +287,10 @@ register_diagnostics! {
     E0550, // multiple deprecated attributes
     E0551, // incorrect meta item
     E0552, // unrecognized representation hint
-    E0553, // unrecognized enum representation hint
     E0554, // #[feature] may not be used on the [] release channel
     E0555, // malformed feature attribute, expected #![feature(...)]
     E0556, // malformed feature, expected just one word
     E0557, // feature has been removed
     E0584, // file for module `..` found at both .. and ..
+    E0589, // invalid `repr(align)` attribute
 }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 680bd7599ac..842398ea02b 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -205,6 +205,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         module.directory.pop();
         self.cx.current_expansion.module = Rc::new(module);
 
+        let orig_mod_span = krate.module.inner;
+
         let krate_item = Expansion::Items(SmallVector::one(P(ast::Item {
             attrs: krate.attrs,
             span: krate.span,
@@ -214,11 +216,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             vis: ast::Visibility::Public,
         })));
 
-        match self.expand(krate_item).make_items().pop().unwrap().unwrap() {
-            ast::Item { attrs, node: ast::ItemKind::Mod(module), .. } => {
+        match self.expand(krate_item).make_items().pop().map(P::unwrap) {
+            Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
                 krate.attrs = attrs;
                 krate.module = module;
             },
+            None => {
+                // Resolution failed so we return an empty expansion
+                krate.attrs = vec![];
+                krate.module = ast::Mod {
+                    inner: orig_mod_span,
+                    items: vec![],
+                };
+            },
             _ => unreachable!(),
         };
 
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 81ab1a348d6..fa0e45194dc 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -335,6 +335,9 @@ declare_features! (
     // Allows the `catch {...}` expression
     (active, catch_expr, "1.17.0", Some(31436)),
 
+    // Allows `repr(align(u16))` struct attribute (RFC 1358)
+    (active, repr_align, "1.17.0", Some(33626)),
+
     // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
     (active, rvalue_static_promotion, "1.15.1", Some(38865)),
 
@@ -1185,6 +1188,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                                     and possibly buggy");
 
                             }
+                            if item.check_name("align") {
+                                gate_feature_post!(&self, repr_align, i.span,
+                                                   "the struct `#[repr(align(u16))]` attribute \
+                                                    is experimental");
+                            }
                         }
                     }
                 }
diff --git a/src/libsyntax/test_snippet.rs b/src/libsyntax/test_snippet.rs
index a74f59b004b..dc9b22c37e2 100644
--- a/src/libsyntax/test_snippet.rs
+++ b/src/libsyntax/test_snippet.rs
@@ -128,9 +128,9 @@ error: foo
  --> test.rs:2:10
   |
 2 |   fn foo() {
-  |  __________^ starting here...
+  |  __________^
 3 | | }
-  | |_^ ...ending here: test
+  | |_^ test
 
 "#);
 }
@@ -161,11 +161,11 @@ error: foo
  --> test.rs:2:10
   |
 2 |   fn foo() {
-  |  __________^ starting here...
+  |  __________^
 3 | |
 4 | |
 5 | |   }
-  | |___^ ...ending here: test
+  | |___^ test
 
 "#);
 }
@@ -207,14 +207,14 @@ error: foo
  --> test.rs:3:3
   |
 3 |      X0 Y0
-  |  ____^__- starting here...
+  |  ____^__-
   | | ___|
-  | ||   starting here...
+  | ||
 4 | ||   X1 Y1
 5 | ||   X2 Y2
-  | ||____^__- ...ending here: `Y` is a good letter too
+  | ||____^__- `Y` is a good letter too
   |  |____|
-  |       ...ending here: `X` is a good letter
+  |       `X` is a good letter
 
 "#);
 }
@@ -256,13 +256,13 @@ error: foo
  --> test.rs:3:3
   |
 3 |      X0 Y0
-  |  ____^__- starting here...
+  |  ____^__-
   | | ___|
-  | ||   starting here...
+  | ||
 4 | ||   Y1 X1
-  | ||____-__^ ...ending here: `X` is a good letter
+  | ||____-__^ `X` is a good letter
   | |_____|
-  |       ...ending here: `Y` is a good letter too
+  |       `Y` is a good letter too
 
 "#);
 }
@@ -306,13 +306,13 @@ error: foo
  --> test.rs:3:6
   |
 3 |      X0 Y0 Z0
-  |   ______^ starting here...
+  |   ______^
 4 |  |   X1 Y1 Z1
-  |  |_________- starting here...
+  |  |_________-
 5 | ||   X2 Y2 Z2
-  | ||____^ ...ending here: `X` is a good letter
+  | ||____^ `X` is a good letter
 6 | |    X3 Y3 Z3
-  | |_____- ...ending here: `Y` is a good letter too
+  | |_____- `Y` is a good letter too
 
 "#);
 }
@@ -366,16 +366,16 @@ error: foo
  --> test.rs:3:3
   |
 3 |       X0 Y0 Z0
-  |  _____^__-__- starting here...
+  |  _____^__-__-
   | | ____|__|
-  | || ___|  starting here...
-  | |||   starting here...
+  | || ___|
+  | |||
 4 | |||   X1 Y1 Z1
 5 | |||   X2 Y2 Z2
-  | |||____^__-__- ...ending here: `Z` label
+  | |||____^__-__- `Z` label
   |  ||____|__|
-  |   |____|  ...ending here: `Y` is a good letter too
-  |        ...ending here: `X` is a good letter
+  |   |____|  `Y` is a good letter too
+  |        `X` is a good letter
 
 "#);
 }
@@ -430,17 +430,17 @@ error: foo
  --> test.rs:3:6
   |
 3 |      X0 Y0 Z0
-  |   ______^ starting here...
+  |   ______^
 4 |  |   X1 Y1 Z1
-  |  |____^_- starting here...
+  |  |____^_-
   | ||____|
-  | |     ...ending here: `X` is a good letter
+  | |     `X` is a good letter
 5 | |    X2 Y2 Z2
-  | |____-______- ...ending here: `Y` is a good letter too
+  | |____-______- `Y` is a good letter too
   |  ____|
-  | |    starting here...
+  | |
 6 | |    X3 Y3 Z3
-  | |________- ...ending here: `Z`
+  | |________- `Z`
 
 "#);
 }
@@ -458,7 +458,7 @@ fn foo() {
     vec![
         SpanLabel {
             start: Position {
-                string: "Y0",
+                string: "X0",
                 count: 1,
             },
             end: Position {
@@ -481,16 +481,15 @@ fn foo() {
     ],
     r#"
 error: foo
- --> test.rs:3:6
+ --> test.rs:3:3
   |
-3 |     X0 Y0 Z0
-  |  ______^ starting here...
+3 | /   X0 Y0 Z0
 4 | |   X1 Y1 Z1
-  | |____^ ...ending here: `X` is a good letter
+  | |____^ `X` is a good letter
 5 |     X2 Y2 Z2
-  |  ______- starting here...
+  |  ______-
 6 | |   X3 Y3 Z3
-  | |__________- ...ending here: `Y` is a good letter too
+  | |__________- `Y` is a good letter too
 
 "#);
 }
@@ -534,14 +533,14 @@ error: foo
  --> test.rs:3:6
   |
 3 |      X0 Y0 Z0
-  |   ______^ starting here...
+  |   ______^
 4 |  |   X1 Y1 Z1
-  |  |____^____- starting here...
+  |  |____^____-
   | ||____|
-  | |     ...ending here: `X` is a good letter
+  | |     `X` is a good letter
 5 | |    X2 Y2 Z2
 6 | |    X3 Y3 Z3
-  | |___________- ...ending here: `Y` is a good letter too
+  | |___________- `Y` is a good letter too
 
 "#);
 }
@@ -982,18 +981,18 @@ error: foo
   --> test.rs:3:6
    |
 3  |      X0 Y0 Z0
-   |   ______^ starting here...
+   |   ______^
 4  |  |   X1 Y1 Z1
-   |  |____^____- starting here...
+   |  |____^____-
    | ||____|
-   | |     ...ending here: `X` is a good letter
+   | |     `X` is a good letter
 5  | |  1
 6  | |  2
 7  | |  3
 ...  |
 15 | |    X2 Y2 Z2
 16 | |    X3 Y3 Z3
-   | |___________- ...ending here: `Y` is a good letter too
+   | |___________- `Y` is a good letter too
 
 "#);
 }
@@ -1047,21 +1046,21 @@ error: foo
   --> test.rs:3:6
    |
 3  |      X0 Y0 Z0
-   |   ______^ starting here...
+   |   ______^
 4  |  | 1
 5  |  | 2
 6  |  | 3
 7  |  |   X1 Y1 Z1
-   |  |_________- starting here...
+   |  |_________-
 8  | || 4
 9  | || 5
 10 | || 6
 11 | ||   X2 Y2 Z2
-   | ||__________- ...ending here: `Z` is a good letter too
+   | ||__________- `Z` is a good letter too
 ...   |
 15 |  | 10
 16 |  |   X3 Y3 Z3
-   |  |_______^ ...ending here: `Y` is a good letter
+   |  |_______^ `Y` is a good letter
 
 "#);
 }
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 1ff0fec1c96..e96883c26f3 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -773,7 +773,7 @@ fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> &
     for a in type_attrs {
         for r in &attr::find_repr_attrs(diagnostic, a) {
             repr_type_name = match *r {
-                attr::ReprPacked | attr::ReprSimd => continue,
+                attr::ReprPacked | attr::ReprSimd | attr::ReprAlign(_) => continue,
                 attr::ReprExtern => "i32",
 
                 attr::ReprInt(attr::SignedInt(ast::IntTy::Is)) => "isize",
diff --git a/src/rtstartup/rsbegin.rs b/src/rtstartup/rsbegin.rs
index 65c85697ce7..e8b92aab1da 100644
--- a/src/rtstartup/rsbegin.rs
+++ b/src/rtstartup/rsbegin.rs
@@ -22,7 +22,7 @@
 // object (usually called `crtX.o), which then invokes initialization callbacks
 // of other runtime components (registered via yet another special image section).
 
-#![feature(no_core, lang_items)]
+#![feature(no_core, lang_items, optin_builtin_traits)]
 #![crate_type="rlib"]
 #![no_core]
 #![allow(non_camel_case_types)]
@@ -31,9 +31,12 @@
 trait Sized {}
 #[lang = "sync"]
 trait Sync {}
+impl Sync for .. {}
 #[lang = "copy"]
 trait Copy {}
-impl<T> Sync for T {}
+#[cfg_attr(not(stage0), lang = "freeze")]
+trait Freeze {}
+impl Freeze for .. {}
 
 #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
 pub mod eh_frames {
diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/issue-41211.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/issue-41211.rs
new file mode 100644
index 00000000000..99400bd147c
--- /dev/null
+++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/issue-41211.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.
+
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn emit_unchanged(_args: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/compile-fail-fulldeps/proc-macro/issue-41211.rs b/src/test/compile-fail-fulldeps/proc-macro/issue-41211.rs
new file mode 100644
index 00000000000..17237912be4
--- /dev/null
+++ b/src/test/compile-fail-fulldeps/proc-macro/issue-41211.rs
@@ -0,0 +1,22 @@
+// 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.
+
+// aux-build:issue-41211.rs
+
+// FIXME: https://github.com/rust-lang/rust/issues/41430
+// This is a temporary regression test for the ICE reported in #41211
+
+#![feature(proc_macro)]
+#![emit_unchanged]
+//~^ ERROR: cannot find attribute macro `emit_unchanged` in this scope
+extern crate issue_41211;
+use issue_41211::emit_unchanged;
+
+fn main() {}
diff --git a/src/test/compile-fail/attr-usage-repr.rs b/src/test/compile-fail/attr-usage-repr.rs
index b07d3e2f906..c0bfd3690c8 100644
--- a/src/test/compile-fail/attr-usage-repr.rs
+++ b/src/test/compile-fail/attr-usage-repr.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![allow(dead_code)]
+#![feature(attr_literals)]
 #![feature(repr_simd)]
 
 #[repr(C)] //~ ERROR: attribute should be applied to struct, enum or union
@@ -29,6 +30,9 @@ struct SInt(f64, f64);
 #[repr(C)]
 enum EExtern { A, B }
 
+#[repr(align(8))] //~ ERROR: attribute should be applied to struct
+enum EAlign { A, B }
+
 #[repr(packed)] //~ ERROR: attribute should be applied to struct
 enum EPacked { A, B }
 
diff --git a/src/test/compile-fail/coercion-slice.rs b/src/test/compile-fail/coercion-slice.rs
index 6b468ff9662..7c5a4e0c3c6 100644
--- a/src/test/compile-fail/coercion-slice.rs
+++ b/src/test/compile-fail/coercion-slice.rs
@@ -14,6 +14,5 @@ fn main() {
     let _: &[i32] = [0];
     //~^ ERROR mismatched types
     //~| expected type `&[i32]`
-    //~| found type `[{integer}; 1]`
     //~| expected &[i32], found array of 1 elements
 }
diff --git a/src/test/compile-fail/conflicting-repr-hints.rs b/src/test/compile-fail/conflicting-repr-hints.rs
index 9e0c0d845ca..01fa3ffbaa6 100644
--- a/src/test/compile-fail/conflicting-repr-hints.rs
+++ b/src/test/compile-fail/conflicting-repr-hints.rs
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustc_attrs)]
 #![allow(dead_code)]
+#![feature(attr_literals)]
+#![feature(repr_align)]
 
 #[repr(C)]
 enum A { A }
@@ -26,5 +27,7 @@ enum D { D }
 #[repr(C, packed)]
 struct E(i32);
 
-#[rustc_error]
-fn main() {} //~ ERROR compilation successful
+#[repr(packed, align(8))] //~ ERROR conflicting packed and align representation hints
+struct F(i32);
+
+fn main() {}
diff --git a/src/test/compile-fail/cross-borrow-trait.rs b/src/test/compile-fail/cross-borrow-trait.rs
index e5afccb9cf3..847a82c0826 100644
--- a/src/test/compile-fail/cross-borrow-trait.rs
+++ b/src/test/compile-fail/cross-borrow-trait.rs
@@ -17,7 +17,7 @@ impl Trait for Foo {}
 
 pub fn main() {
     let x: Box<Trait> = Box::new(Foo);
-    let _y: &Trait = x; //~  ERROR mismatched types
+    let _y: &Trait = x; //~ ERROR E0308
                         //~| expected type `&Trait`
                         //~| found type `std::boxed::Box<Trait>`
 }
diff --git a/src/test/compile-fail/feature-gate-repr_align.rs b/src/test/compile-fail/feature-gate-repr_align.rs
new file mode 100644
index 00000000000..8e986e197f2
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-repr_align.rs
@@ -0,0 +1,15 @@
+// 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(attr_literals)]
+
+#[repr(align(64))]
+struct Foo(u64, u64); //~ error: the struct `#[repr(align(u16))]` attribute is experimental
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-11374.rs b/src/test/compile-fail/issue-11374.rs
index f78786a2889..1e444a6bebf 100644
--- a/src/test/compile-fail/issue-11374.rs
+++ b/src/test/compile-fail/issue-11374.rs
@@ -33,5 +33,5 @@ pub fn for_stdin<'a>() -> Container<'a> {
 fn main() {
     let mut c = for_stdin();
     let mut v = Vec::new();
-    c.read_to(v); //~ ERROR mismatched types
+    c.read_to(v); //~ ERROR E0308
 }
diff --git a/src/test/compile-fail/issue-13058.rs b/src/test/compile-fail/issue-13058.rs
index 408c6d411de..ed163444149 100644
--- a/src/test/compile-fail/issue-13058.rs
+++ b/src/test/compile-fail/issue-13058.rs
@@ -35,4 +35,5 @@ fn check<'r, I: Iterator<Item=usize>, T: Itble<'r, usize, I>>(cont: &T) -> bool
 fn main() {
     check((3, 5));
 //~^ ERROR mismatched types
+//~| HELP try with `&(3, 5)`
 }
diff --git a/src/test/compile-fail/repr-align.rs b/src/test/compile-fail/repr-align.rs
new file mode 100644
index 00000000000..eb0b27fe9c0
--- /dev/null
+++ b/src/test/compile-fail/repr-align.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.
+#![allow(dead_code)]
+#![feature(attr_literals)]
+#![feature(repr_align)]
+
+#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
+struct A(i32);
+
+#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
+struct B(i32);
+
+#[repr(align(65536))] //~ ERROR: invalid `repr(align)` attribute: larger than 32768
+struct C(i32);
+
+fn main() {}
diff --git a/src/test/compile-fail/repr-packed-contains-align.rs b/src/test/compile-fail/repr-packed-contains-align.rs
new file mode 100644
index 00000000000..c584dcf3e59
--- /dev/null
+++ b/src/test/compile-fail/repr-packed-contains-align.rs
@@ -0,0 +1,25 @@
+// 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(attr_literals)]
+#![feature(repr_align)]
+#![allow(dead_code)]
+
+#[repr(align(16))]
+struct A(i32);
+
+struct B(A);
+
+#[repr(packed)]
+struct C(A); //~ ERROR: packed struct cannot transitively contain a `[repr(align)]` struct
+
+#[repr(packed)]
+struct D(B); //~ ERROR: packed struct cannot transitively contain a `[repr(align)]` struct
+
+fn main() {}
diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs
index 49fec6f3619..8ab8f471575 100644
--- a/src/test/run-make/simd-ffi/simd.rs
+++ b/src/test/run-make/simd-ffi/simd.rs
@@ -12,7 +12,7 @@
 #![crate_type = "lib"]
 // we can compile to a variety of platforms, because we don't need
 // cross-compiled standard libraries.
-#![feature(no_core)]
+#![feature(no_core, optin_builtin_traits)]
 #![no_core]
 
 #![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items)]
@@ -78,3 +78,7 @@ pub trait Copy { }
 pub mod marker {
     pub use Copy;
 }
+
+#[lang = "freeze"]
+trait Freeze {}
+impl Freeze for .. {}
diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make/target-specs/foo.rs
index 15b56977232..af24c3b460b 100644
--- a/src/test/run-make/target-specs/foo.rs
+++ b/src/test/run-make/target-specs/foo.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(lang_items, no_core)]
+#![feature(lang_items, no_core, optin_builtin_traits)]
 #![no_core]
 
 #[lang="copy"]
@@ -17,6 +17,10 @@ trait Copy { }
 #[lang="sized"]
 trait Sized { }
 
+#[lang = "freeze"]
+trait Freeze {}
+impl Freeze for .. {}
+
 #[lang="start"]
 fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { 0 }
 
diff --git a/src/test/run-pass/align-struct.rs b/src/test/run-pass/align-struct.rs
new file mode 100644
index 00000000000..0b9a3594502
--- /dev/null
+++ b/src/test/run-pass/align-struct.rs
@@ -0,0 +1,196 @@
+// 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(attr_literals)]
+#![feature(repr_align)]
+
+use std::mem;
+
+// Raising alignment
+#[repr(align(16))]
+struct Align16(i32);
+
+// Lowering has no effect
+#[repr(align(1))]
+struct Align1(i32);
+
+// Multiple attributes take the max
+#[repr(align(4))]
+#[repr(align(16))]
+#[repr(align(8))]
+struct AlignMany(i32);
+
+// Raising alignment may not alter size.
+#[repr(align(8))]
+#[allow(dead_code)]
+struct Align8Many {
+    a: i32,
+    b: i32,
+    c: i32,
+    d: u8,
+}
+
+enum Enum {
+    #[allow(dead_code)]
+    A(i32),
+    B(Align16)
+}
+
+// Nested alignment - use `#[repr(C)]` to suppress field reordering for sizeof test
+#[repr(C)]
+struct Nested {
+    a: i32,
+    b: i32,
+    c: Align16,
+    d: i8,
+}
+
+#[repr(packed)]
+struct Packed(i32);
+
+#[repr(align(16))]
+struct AlignContainsPacked {
+    a: Packed,
+    b: Packed,
+}
+
+impl Align16 {
+    // return aligned type
+    pub fn new(i: i32) -> Align16 {
+        Align16(i)
+    }
+    // pass aligned type
+    pub fn consume(a: Align16) -> i32 {
+        a.0
+    }
+}
+
+const CONST_ALIGN16: Align16 = Align16(7);
+static STATIC_ALIGN16: Align16 = Align16(8);
+
+// Check the actual address is aligned
+fn is_aligned_to<T>(p: &T, align: usize) -> bool {
+    let addr = p as *const T as usize;
+    (addr & (align - 1)) == 0
+}
+
+pub fn main() {
+    // check alignment and size by type and value
+    assert_eq!(mem::align_of::<Align16>(), 16);
+    assert_eq!(mem::size_of::<Align16>(), 16);
+
+    let a = Align16(7);
+    assert_eq!(a.0, 7);
+    assert_eq!(mem::align_of_val(&a), 16);
+    assert_eq!(mem::size_of_val(&a), 16);
+
+    assert!(is_aligned_to(&a, 16));
+
+    // lowering should have no effect
+    assert_eq!(mem::align_of::<Align1>(), 4);
+    assert_eq!(mem::size_of::<Align1>(), 4);
+    let a = Align1(7);
+    assert_eq!(a.0, 7);
+    assert_eq!(mem::align_of_val(&a), 4);
+    assert_eq!(mem::size_of_val(&a), 4);
+    assert!(is_aligned_to(&a, 4));
+
+    // when multiple attributes are specified the max should be used
+    assert_eq!(mem::align_of::<AlignMany>(), 16);
+    assert_eq!(mem::size_of::<AlignMany>(), 16);
+    let a = AlignMany(7);
+    assert_eq!(a.0, 7);
+    assert_eq!(mem::align_of_val(&a), 16);
+    assert_eq!(mem::size_of_val(&a), 16);
+    assert!(is_aligned_to(&a, 16));
+
+    // raising alignment should not reduce size
+    assert_eq!(mem::align_of::<Align8Many>(), 8);
+    assert_eq!(mem::size_of::<Align8Many>(), 16);
+    let a = Align8Many { a: 1, b: 2, c: 3, d: 4 };
+    assert_eq!(a.a, 1);
+    assert_eq!(mem::align_of_val(&a), 8);
+    assert_eq!(mem::size_of_val(&a), 16);
+    assert!(is_aligned_to(&a, 8));
+
+    // return type
+    let a = Align16::new(1);
+    assert_eq!(mem::align_of_val(&a), 16);
+    assert_eq!(mem::size_of_val(&a), 16);
+    assert_eq!(a.0, 1);
+    assert!(is_aligned_to(&a, 16));
+    assert_eq!(Align16::consume(a), 1);
+
+    // check const alignment, size and value
+    assert_eq!(mem::align_of_val(&CONST_ALIGN16), 16);
+    assert_eq!(mem::size_of_val(&CONST_ALIGN16), 16);
+    assert_eq!(CONST_ALIGN16.0, 7);
+    assert!(is_aligned_to(&CONST_ALIGN16, 16));
+
+    // check global static alignment, size and value
+    assert_eq!(mem::align_of_val(&STATIC_ALIGN16), 16);
+    assert_eq!(mem::size_of_val(&STATIC_ALIGN16), 16);
+    assert_eq!(STATIC_ALIGN16.0, 8);
+    assert!(is_aligned_to(&STATIC_ALIGN16, 16));
+
+    // Note that the size of Nested may change if struct field re-ordering is enabled
+    assert_eq!(mem::align_of::<Nested>(), 16);
+    assert_eq!(mem::size_of::<Nested>(), 48);
+    let a = Nested{ a: 1, b: 2, c: Align16(3), d: 4};
+    assert_eq!(mem::align_of_val(&a), 16);
+    assert_eq!(mem::align_of_val(&a.b), 4);
+    assert_eq!(mem::align_of_val(&a.c), 16);
+    assert_eq!(mem::size_of_val(&a), 48);
+    assert!(is_aligned_to(&a, 16));
+    // check the correct fields are indexed
+    assert_eq!(a.a, 1);
+    assert_eq!(a.b, 2);
+    assert_eq!(a.c.0, 3);
+    assert_eq!(a.d, 4);
+
+    // enum should be aligned to max alignment
+    assert_eq!(mem::align_of::<Enum>(), 16);
+    assert_eq!(mem::align_of_val(&Enum::B(Align16(0))), 16);
+    let e = Enum::B(Align16(15));
+    match e {
+        Enum::B(ref a) => {
+            assert_eq!(a.0, 15);
+            assert_eq!(mem::align_of_val(a), 16);
+            assert_eq!(mem::size_of_val(a), 16);
+        },
+        _ => ()
+    }
+    assert!(is_aligned_to(&e, 16));
+
+    // arrays of aligned elements should also be aligned
+    assert_eq!(mem::align_of::<[Align16;2]>(), 16);
+    assert_eq!(mem::size_of::<[Align16;2]>(), 32);
+
+    let a = [Align16(0), Align16(1)];
+    assert_eq!(mem::align_of_val(&a[0]), 16);
+    assert_eq!(mem::align_of_val(&a[1]), 16);
+    assert!(is_aligned_to(&a, 16));
+
+    // check heap value is aligned
+    assert_eq!(mem::align_of_val(Box::new(Align16(0)).as_ref()), 16);
+
+    // check heap array is aligned
+    let a = vec!(Align16(0), Align16(1));
+    assert_eq!(mem::align_of_val(&a[0]), 16);
+    assert_eq!(mem::align_of_val(&a[1]), 16);
+
+    assert_eq!(mem::align_of::<AlignContainsPacked>(), 16);
+    assert_eq!(mem::size_of::<AlignContainsPacked>(), 16);
+    let a = AlignContainsPacked { a: Packed(1), b: Packed(2) };
+    assert_eq!(mem::align_of_val(&a), 16);
+    assert_eq!(mem::align_of_val(&a.a), 1);
+    assert_eq!(mem::align_of_val(&a.b), 1);
+    assert_eq!(mem::size_of_val(&a), 16);
+    assert!(is_aligned_to(&a, 16));
+}
diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr
index 12b0ecabcc7..af974d50183 100644
--- a/src/test/ui/compare-method/region-extra-2.stderr
+++ b/src/test/ui/compare-method/region-extra-2.stderr
@@ -4,12 +4,11 @@ error[E0276]: impl has stricter requirements than trait
 15 |       fn renew<'b: 'a>(self) -> &'b mut [T];
    |       -------------------------------------- definition of `renew` from trait
 ...
-19 |       fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b {
-   |  _____^ starting here...
+19 | /     fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b {
 20 | |         //~^ ERROR E0276
 21 | |         &mut self[..]
 22 | |     }
-   | |_____^ ...ending here: impl has extra requirement `'a: 'b`
+   | |_____^ impl has extra requirement `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr
index 77b056f6978..622e144c53a 100644
--- a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr
+++ b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr
@@ -4,12 +4,11 @@ error[E0276]: impl has stricter requirements than trait
 19 |       fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>;
    |       ------------------------------------------------------------------ definition of `zip` from trait
 ...
-23 |       fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
-   |  _____^ starting here...
+23 | /     fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
 24 | |     //~^ ERROR E0276
 25 | |         ZipIterator{a: self, b: other}
 26 | |     }
-   | |_____^ ...ending here: impl has extra requirement `U: Iterator<B>`
+   | |_____^ impl has extra requirement `U: Iterator<B>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr
index 29ff0cee3af..8e8773eba3e 100644
--- a/src/test/ui/did_you_mean/issue-40006.stderr
+++ b/src/test/ui/did_you_mean/issue-40006.stderr
@@ -2,17 +2,17 @@ error: missing `fn`, `type`, or `const` for impl-item declaration
   --> $DIR/issue-40006.rs:11:9
    |
 11 |   impl X {
-   |  _________^ starting here...
+   |  _________^
 12 | |     Y
-   | |____^ ...ending here: missing `fn`, `type`, or `const`
+   | |____^ missing `fn`, `type`, or `const`
 
 error: missing `fn`, `type`, or `const` for trait-item declaration
   --> $DIR/issue-40006.rs:17:10
    |
 17 |   trait X {
-   |  __________^ starting here...
+   |  __________^
 18 | |     X() {}
-   | |____^ ...ending here: missing `fn`, `type`, or `const`
+   | |____^ missing `fn`, `type`, or `const`
 
 error: expected `[`, found `#`
   --> $DIR/issue-40006.rs:19:17
@@ -24,17 +24,17 @@ error: missing `fn`, `type`, or `const` for trait-item declaration
   --> $DIR/issue-40006.rs:19:21
    |
 19 |       fn xxx() { ### }
-   |  _____________________^ starting here...
+   |  _____________________^
 20 | |     L = M;
-   | |____^ ...ending here: missing `fn`, `type`, or `const`
+   | |____^ missing `fn`, `type`, or `const`
 
 error: missing `fn`, `type`, or `const` for trait-item declaration
   --> $DIR/issue-40006.rs:20:11
    |
 20 |       L = M;
-   |  ___________^ starting here...
+   |  ___________^
 21 | |     Z = { 2 + 3 };
-   | |____^ ...ending here: missing `fn`, `type`, or `const`
+   | |____^ missing `fn`, `type`, or `const`
 
 error: expected one of `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;`
   --> $DIR/issue-40006.rs:21:18
diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
index 92e2fe8e936..2c788e952ed 100644
--- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
+++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
@@ -1,26 +1,24 @@
 error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
   --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:32:1
    |
-32 |   impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
-   |  _^ starting here...
+32 | / impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
 33 | |     //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
 34 | |
 35 | |     // (unsafe to access self.1  due to #[may_dangle] on A)
 36 | |     fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
 37 | | }
-   | |_^ ...ending here
+   | |_^
 
 error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
   --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:38:1
    |
-38 |   impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
-   |  _^ starting here...
+38 | / impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
 39 | |     //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
 40 | |
 41 | |     // (unsafe to access self.1 due to #[may_dangle] on 'a)
 42 | |     fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
 43 | | }
-   | |_^ ...ending here
+   | |_^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr
index 5a63d235a7f..b51b683a1ac 100644
--- a/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr
+++ b/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr
@@ -1,11 +1,10 @@
 error: reached the type-length limit while instantiating `<T as Foo><(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(), &()), &(&()...`
   --> $DIR/issue-37311.rs:23:5
    |
-23 |       fn recurse(&self) {
-   |  _____^ starting here...
+23 | /     fn recurse(&self) {
 24 | |         (self, self).recurse();
 25 | |     }
-   | |_____^ ...ending here
+   | |_____^
    |
    = note: consider adding a `#![type_length_limit="2097152"]` attribute to your crate
 
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr
index 85e05422ab3..cf272b63128 100644
--- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr
@@ -8,18 +8,18 @@ note: ...the reference is valid for the lifetime 'a as defined on the body at 11
   --> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
    |
 11 |   fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
-   |  ____________________________________________^ starting here...
+   |  ____________________________________________^
 12 | |     if x > y { x } else { y }
 13 | | }
-   | |_^ ...ending here
+   | |_^
 note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the body at 11:43
   --> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
    |
 11 |   fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
-   |  ____________________________________________^ starting here...
+   |  ____________________________________________^
 12 | |     if x > y { x } else { y }
 13 | | }
-   | |_^ ...ending here
+   | |_^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr
index 6956a043cc6..6e03e66dd25 100644
--- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr
+++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr
@@ -10,18 +10,18 @@ note: the anonymous lifetime #2 defined on the body at 15:51...
   --> $DIR/ex2a-push-one-existing-name.rs:15:52
    |
 15 |   fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
-   |  ____________________________________________________^ starting here...
+   |  ____________________________________________________^
 16 | |     x.push(y);
 17 | | }
-   | |_^ ...ending here
+   | |_^
 note: ...does not necessarily outlive the lifetime 'a as defined on the body at 15:51
   --> $DIR/ex2a-push-one-existing-name.rs:15:52
    |
 15 |   fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
-   |  ____________________________________________________^ starting here...
+   |  ____________________________________________________^
 16 | |     x.push(y);
 17 | | }
-   | |_^ ...ending here
+   | |_^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr
index 990ae65ba98..028f54ce978 100644
--- a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr
+++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr
@@ -10,18 +10,18 @@ note: the anonymous lifetime #3 defined on the body at 15:43...
   --> $DIR/ex2b-push-no-existing-names.rs:15:44
    |
 15 |   fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
-   |  ____________________________________________^ starting here...
+   |  ____________________________________________^
 16 | |     x.push(y);
 17 | | }
-   | |_^ ...ending here
+   | |_^
 note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 15:43
   --> $DIR/ex2b-push-no-existing-names.rs:15:44
    |
 15 |   fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
-   |  ____________________________________________^ starting here...
+   |  ____________________________________________^
 16 | |     x.push(y);
 17 | | }
-   | |_^ ...ending here
+   | |_^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr
index 82f6c71ec1c..4621214419e 100644
--- a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr
+++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr
@@ -8,11 +8,11 @@ note: first, the lifetime cannot outlive the lifetime 'c as defined on the body
   --> $DIR/ex2c-push-inference-variable.rs:15:67
    |
 15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^ starting here...
+   |  ___________________________________________________________________^
 16 | |     let z = Ref { data: y.data };
 17 | |     x.push(z);
 18 | | }
-   | |_^ ...ending here
+   | |_^
 note: ...so that reference does not outlive borrowed content
   --> $DIR/ex2c-push-inference-variable.rs:16:25
    |
@@ -22,11 +22,11 @@ note: but, the lifetime must be valid for the lifetime 'b as defined on the body
   --> $DIR/ex2c-push-inference-variable.rs:15:67
    |
 15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^ starting here...
+   |  ___________________________________________________________________^
 16 | |     let z = Ref { data: y.data };
 17 | |     x.push(z);
 18 | | }
-   | |_^ ...ending here
+   | |_^
 note: ...so that expression is assignable (expected Ref<'b, _>, found Ref<'_, _>)
   --> $DIR/ex2c-push-inference-variable.rs:17:12
    |
diff --git a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr
index daa6ea2d91a..a69694fdc2e 100644
--- a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr
+++ b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr
@@ -8,12 +8,12 @@ note: first, the lifetime cannot outlive the lifetime 'c as defined on the body
   --> $DIR/ex2d-push-inference-variable-2.rs:15:67
    |
 15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^ starting here...
+   |  ___________________________________________________________________^
 16 | |     let a: &mut Vec<Ref<i32>> = x;
 17 | |     let b = Ref { data: y.data };
 18 | |     a.push(b);
 19 | | }
-   | |_^ ...ending here
+   | |_^
 note: ...so that reference does not outlive borrowed content
   --> $DIR/ex2d-push-inference-variable-2.rs:17:25
    |
@@ -23,12 +23,12 @@ note: but, the lifetime must be valid for the lifetime 'b as defined on the body
   --> $DIR/ex2d-push-inference-variable-2.rs:15:67
    |
 15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^ starting here...
+   |  ___________________________________________________________________^
 16 | |     let a: &mut Vec<Ref<i32>> = x;
 17 | |     let b = Ref { data: y.data };
 18 | |     a.push(b);
 19 | | }
-   | |_^ ...ending here
+   | |_^
 note: ...so that expression is assignable (expected &mut std::vec::Vec<Ref<'_, i32>>, found &mut std::vec::Vec<Ref<'b, i32>>)
   --> $DIR/ex2d-push-inference-variable-2.rs:16:33
    |
diff --git a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr
index b679532a4d9..eff15bb794b 100644
--- a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr
+++ b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr
@@ -8,12 +8,12 @@ note: first, the lifetime cannot outlive the lifetime 'c as defined on the body
   --> $DIR/ex2e-push-inference-variable-3.rs:15:67
    |
 15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^ starting here...
+   |  ___________________________________________________________________^
 16 | |     let a: &mut Vec<Ref<i32>> = x;
 17 | |     let b = Ref { data: y.data };
 18 | |     Vec::push(a, b);
 19 | | }
-   | |_^ ...ending here
+   | |_^
 note: ...so that reference does not outlive borrowed content
   --> $DIR/ex2e-push-inference-variable-3.rs:17:25
    |
@@ -23,12 +23,12 @@ note: but, the lifetime must be valid for the lifetime 'b as defined on the body
   --> $DIR/ex2e-push-inference-variable-3.rs:15:67
    |
 15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^ starting here...
+   |  ___________________________________________________________________^
 16 | |     let a: &mut Vec<Ref<i32>> = x;
 17 | |     let b = Ref { data: y.data };
 18 | |     Vec::push(a, b);
 19 | | }
-   | |_^ ...ending here
+   | |_^
 note: ...so that expression is assignable (expected &mut std::vec::Vec<Ref<'_, i32>>, found &mut std::vec::Vec<Ref<'b, i32>>)
   --> $DIR/ex2e-push-inference-variable-3.rs:16:33
    |
diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr
index c67c6113d17..36bdec8d43a 100644
--- a/src/test/ui/mismatched_types/abridged.stderr
+++ b/src/test/ui/mismatched_types/abridged.stderr
@@ -37,15 +37,14 @@ error[E0308]: mismatched types
 error[E0308]: mismatched types
   --> $DIR/abridged.rs:42:5
    |
-42 |       X {
-   |  _____^ starting here...
+42 | /     X {
 43 | |         x: X {
 44 | |             x: "".to_string(),
 45 | |             y: 2,
 46 | |         },
 47 | |         y: 3,
 48 | |     }
-   | |_____^ ...ending here: expected struct `std::string::String`, found integral variable
+   | |_____^ expected struct `std::string::String`, found integral variable
    |
    = note: expected type `X<X<_, std::string::String>, std::string::String>`
               found type `X<X<_, {integer}>, {integer}>`
@@ -53,15 +52,14 @@ error[E0308]: mismatched types
 error[E0308]: mismatched types
   --> $DIR/abridged.rs:52:5
    |
-52 |       X {
-   |  _____^ starting here...
+52 | /     X {
 53 | |         x: X {
 54 | |             x: "".to_string(),
 55 | |             y: 2,
 56 | |         },
 57 | |         y: "".to_string(),
 58 | |     }
-   | |_____^ ...ending here: expected struct `std::string::String`, found integral variable
+   | |_____^ expected struct `std::string::String`, found integral variable
    |
    = note: expected type `X<X<_, std::string::String>, _>`
               found type `X<X<_, {integer}>, _>`
diff --git a/src/test/ui/mismatched_types/main.stderr b/src/test/ui/mismatched_types/main.stderr
index 5dd124ebcdf..c8941fbf950 100644
--- a/src/test/ui/mismatched_types/main.stderr
+++ b/src/test/ui/mismatched_types/main.stderr
@@ -2,9 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/main.rs:12:18
    |
 12 |       let x: u32 = (
-   |  __________________^ starting here...
+   |  __________________^
 13 | |     );
-   | |_____^ ...ending here: expected u32, found ()
+   | |_____^ expected u32, found ()
    |
    = note: expected type `u32`
               found type `()`
diff --git a/src/test/ui/missing-items/m2.stderr b/src/test/ui/missing-items/m2.stderr
index 33135434544..503ce5618d4 100644
--- a/src/test/ui/missing-items/m2.stderr
+++ b/src/test/ui/missing-items/m2.stderr
@@ -3,10 +3,9 @@ error: main function not found
 error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method`
   --> $DIR/m2.rs:20:1
    |
-20 |   impl m1::X for X {
-   |  _^ starting here...
+20 | / impl m1::X for X {
 21 | | }
-   | |_^ ...ending here: missing `CONSTANT`, `Type`, `method` in implementation
+   | |_^ missing `CONSTANT`, `Type`, `method` in implementation
    |
    = note: `CONSTANT` from trait: `const CONSTANT: u32;`
    = note: `Type` from trait: `type Type;`
diff --git a/src/test/ui/print_type_sizes/repr-align.rs b/src/test/ui/print_type_sizes/repr-align.rs
new file mode 100644
index 00000000000..e9b43145de4
--- /dev/null
+++ b/src/test/ui/print_type_sizes/repr-align.rs
@@ -0,0 +1,43 @@
+// Copyright 2016 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: -Z print-type-sizes
+
+// This file illustrates how padding is handled: alignment
+// requirements can lead to the introduction of padding, either before
+// fields or at the end of the structure as a whole.
+//
+// It avoids using u64/i64 because on some targets that is only 4-byte
+// aligned (while on most it is 8-byte aligned) and so the resulting
+// padding and overall computed sizes can be quite different.
+#![feature(attr_literals)]
+#![feature(repr_align)]
+#![allow(dead_code)]
+
+#[repr(align(16))]
+#[derive(Default)]
+struct A(i32);
+
+enum E {
+    A(i32),
+    B(A)
+}
+
+#[derive(Default)]
+struct S {
+    a: i32,
+    b: i32,
+    c: A,
+    d: i8,
+}
+
+fn main() {
+    let _s: S = Default::default();
+}
diff --git a/src/test/ui/print_type_sizes/repr-align.stdout b/src/test/ui/print_type_sizes/repr-align.stdout
new file mode 100644
index 00000000000..7df12f040b1
--- /dev/null
+++ b/src/test/ui/print_type_sizes/repr-align.stdout
@@ -0,0 +1,16 @@
+print-type-size type: `E`: 32 bytes, alignment: 16 bytes
+print-type-size     discriminant: 4 bytes
+print-type-size     variant `A`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size     variant `B`: 28 bytes
+print-type-size         padding: 12 bytes
+print-type-size         field `.0`: 16 bytes, alignment: 16 bytes
+print-type-size type: `S`: 32 bytes, alignment: 16 bytes
+print-type-size     field `.c`: 16 bytes
+print-type-size     field `.a`: 4 bytes
+print-type-size     field `.b`: 4 bytes
+print-type-size     field `.d`: 1 bytes
+print-type-size     end padding: 7 bytes
+print-type-size type: `A`: 16 bytes, alignment: 16 bytes
+print-type-size     field `.0`: 4 bytes
+print-type-size     end padding: 12 bytes
diff --git a/src/test/ui/span/coerce-suggestions.rs b/src/test/ui/span/coerce-suggestions.rs
index 3177e858ff4..bc3122bf71c 100644
--- a/src/test/ui/span/coerce-suggestions.rs
+++ b/src/test/ui/span/coerce-suggestions.rs
@@ -32,7 +32,6 @@ fn main() {
     //~| NOTE types differ in mutability
     //~| NOTE expected type `&mut std::string::String`
     //~| NOTE found type `&std::string::String`
-    //~| HELP try with `&mut y`
     test2(&y);
     //~^ ERROR E0308
     //~| NOTE types differ in mutability
diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr
index 6a70b8ff851..220b2f471da 100644
--- a/src/test/ui/span/coerce-suggestions.stderr
+++ b/src/test/ui/span/coerce-suggestions.stderr
@@ -18,11 +18,7 @@ error[E0308]: mismatched types
    |
    = note: expected type `&str`
               found type `std::string::String`
-   = help: here are some functions which might fulfill your needs:
-           - .as_str()
-           - .trim()
-           - .trim_left()
-           - .trim_right()
+   = help: try with `&String::new()`
 
 error[E0308]: mismatched types
   --> $DIR/coerce-suggestions.rs:30:10
@@ -34,18 +30,18 @@ error[E0308]: mismatched types
               found type `&std::string::String`
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-suggestions.rs:36:11
+  --> $DIR/coerce-suggestions.rs:35:11
    |
-36 |     test2(&y);
+35 |     test2(&y);
    |           ^^ types differ in mutability
    |
    = note: expected type `&mut i32`
               found type `&std::string::String`
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-suggestions.rs:42:9
+  --> $DIR/coerce-suggestions.rs:41:9
    |
-42 |     f = box f;
+41 |     f = box f;
    |         ^^^^^ cyclic type of infinite size
    |
    = note: expected type `_`
diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr
index 367af12bb6b..ae290b3b11a 100644
--- a/src/test/ui/span/impl-wrong-item-for-trait.stderr
+++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr
@@ -19,15 +19,14 @@ error[E0046]: not all trait items implemented, missing: `bar`
 16 |       fn bar(&self);
    |       -------------- `bar` from trait
 ...
-22 |   impl Foo for FooConstForMethod {
-   |  _^ starting here...
+22 | / impl Foo for FooConstForMethod {
 23 | |     //~^ ERROR E0046
 24 | |     //~| NOTE missing `bar` in implementation
 25 | |     const bar: u64 = 1;
 ...  |
 28 | |     const MY_CONST: u32 = 1;
 29 | | }
-   | |_^ ...ending here: missing `bar` in implementation
+   | |_^ missing `bar` in implementation
 
 error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `Foo`
   --> $DIR/impl-wrong-item-for-trait.rs:37:5
@@ -44,15 +43,14 @@ error[E0046]: not all trait items implemented, missing: `MY_CONST`
 17 |       const MY_CONST: u32;
    |       -------------------- `MY_CONST` from trait
 ...
-33 |   impl Foo for FooMethodForConst {
-   |  _^ starting here...
+33 | / impl Foo for FooMethodForConst {
 34 | |     //~^ ERROR E0046
 35 | |     //~| NOTE missing `MY_CONST` in implementation
 36 | |     fn bar(&self) {}
 ...  |
 39 | |     //~| NOTE does not match trait
 40 | | }
-   | |_^ ...ending here: missing `MY_CONST` in implementation
+   | |_^ missing `MY_CONST` in implementation
 
 error[E0325]: item `bar` is an associated type, which doesn't match its trait `Foo`
   --> $DIR/impl-wrong-item-for-trait.rs:47:5
@@ -69,23 +67,21 @@ error[E0046]: not all trait items implemented, missing: `bar`
 16 |       fn bar(&self);
    |       -------------- `bar` from trait
 ...
-44 |   impl Foo for FooTypeForMethod {
-   |  _^ starting here...
+44 | / impl Foo for FooTypeForMethod {
 45 | |     //~^ ERROR E0046
 46 | |     //~| NOTE missing `bar` in implementation
 47 | |     type bar = u64;
 ...  |
 50 | |     const MY_CONST: u32 = 1;
 51 | | }
-   | |_^ ...ending here: missing `bar` in implementation
+   | |_^ missing `bar` in implementation
 
 error[E0046]: not all trait items implemented, missing: `fmt`
   --> $DIR/impl-wrong-item-for-trait.rs:53:1
    |
-53 |   impl Debug for FooTypeForMethod {
-   |  _^ starting here...
+53 | / impl Debug for FooTypeForMethod {
 54 | | }
-   | |_^ ...ending here: missing `fmt` in implementation
+   | |_^ missing `fmt` in implementation
    |
    = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
 
diff --git a/src/test/ui/span/issue-23729.stderr b/src/test/ui/span/issue-23729.stderr
index 701576ff6f4..d9f4bacce35 100644
--- a/src/test/ui/span/issue-23729.stderr
+++ b/src/test/ui/span/issue-23729.stderr
@@ -1,15 +1,14 @@
 error[E0046]: not all trait items implemented, missing: `Item`
   --> $DIR/issue-23729.rs:20:9
    |
-20 |           impl Iterator for Recurrence {
-   |  _________^ starting here...
+20 | /         impl Iterator for Recurrence {
 21 | |             //~^ ERROR E0046
 22 | |             //~| NOTE missing `Item` in implementation
 23 | |             //~| NOTE `Item` from trait: `type Item;`
 ...  |
 36 | |             }
 37 | |         }
-   | |_________^ ...ending here: missing `Item` in implementation
+   | |_________^ missing `Item` in implementation
    |
    = note: `Item` from trait: `type Item;`
 
diff --git a/src/test/ui/span/issue-23827.stderr b/src/test/ui/span/issue-23827.stderr
index 457fed34ff1..3127af157a6 100644
--- a/src/test/ui/span/issue-23827.stderr
+++ b/src/test/ui/span/issue-23827.stderr
@@ -1,15 +1,14 @@
 error[E0046]: not all trait items implemented, missing: `Output`
   --> $DIR/issue-23827.rs:36:1
    |
-36 |   impl<C: Component> FnOnce<(C,)> for Prototype {
-   |  _^ starting here...
+36 | / impl<C: Component> FnOnce<(C,)> for Prototype {
 37 | |     //~^ ERROR E0046
 38 | |     //~| NOTE missing `Output` in implementation
 39 | |     //~| NOTE `Output` from trait: `type Output;`
 ...  |
 42 | |     }
 43 | | }
-   | |_^ ...ending here: missing `Output` in implementation
+   | |_^ missing `Output` in implementation
    |
    = note: `Output` from trait: `type Output;`
 
diff --git a/src/test/ui/span/issue-24356.stderr b/src/test/ui/span/issue-24356.stderr
index 963f4bd9bbc..71ab82d98b8 100644
--- a/src/test/ui/span/issue-24356.stderr
+++ b/src/test/ui/span/issue-24356.stderr
@@ -1,14 +1,13 @@
 error[E0046]: not all trait items implemented, missing: `Target`
   --> $DIR/issue-24356.rs:30:9
    |
-30 |           impl Deref for Thing {
-   |  _________^ starting here...
+30 | /         impl Deref for Thing {
 31 | |             //~^ ERROR E0046
 32 | |             //~| NOTE missing `Target` in implementation
 33 | |             //~| NOTE `Target` from trait: `type Target;`
 34 | |             fn deref(&self) -> i8 { self.0 }
 35 | |         }
-   | |_________^ ...ending here: missing `Target` in implementation
+   | |_________^ missing `Target` in implementation
    |
    = note: `Target` from trait: `type Target;`
 
diff --git a/src/test/ui/span/issue-33884.rs b/src/test/ui/span/issue-33884.rs
new file mode 100644
index 00000000000..93aa502ee15
--- /dev/null
+++ b/src/test/ui/span/issue-33884.rs
@@ -0,0 +1,27 @@
+// 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.
+
+use std::net::TcpListener;
+use std::net::TcpStream;
+use std::io::{self, Read, Write};
+
+fn handle_client(stream: TcpStream) -> io::Result<()> {
+    stream.write_fmt(format!("message received"))
+}
+
+fn main() {
+    if let Ok(listener) = TcpListener::bind("127.0.0.1:8080") {
+        for incoming in listener.incoming() {
+            if let Ok(stream) = incoming {
+                handle_client(stream);
+            }
+        }
+    }
+}
diff --git a/src/test/ui/span/issue-33884.stderr b/src/test/ui/span/issue-33884.stderr
new file mode 100644
index 00000000000..2a874181c7a
--- /dev/null
+++ b/src/test/ui/span/issue-33884.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-33884.rs:16:22
+   |
+16 |     stream.write_fmt(format!("message received"))
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::fmt::Arguments`, found struct `std::string::String`
+   |
+   = note: expected type `std::fmt::Arguments<'_>`
+              found type `std::string::String`
+   = note: this error originates in a macro outside of the current crate
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr
index 765aceffe65..8b813220d78 100644
--- a/src/test/ui/span/issue-7575.stderr
+++ b/src/test/ui/span/issue-7575.stderr
@@ -38,11 +38,10 @@ error: no method named `fff` found for type `Myisize` in the current scope
 note: candidate #1 is defined in an impl for the type `Myisize`
   --> $DIR/issue-7575.rs:51:5
    |
-51 |       fn fff(i: isize) -> isize { //~ NOTE candidate
-   |  _____^ starting here...
+51 | /     fn fff(i: isize) -> isize { //~ NOTE candidate
 52 | |         i
 53 | |     }
-   | |_____^ ...ending here
+   | |_____^
 
 error: no method named `is_str` found for type `T` in the current scope
   --> $DIR/issue-7575.rs:85:7
@@ -54,11 +53,10 @@ error: no method named `is_str` found for type `T` in the current scope
 note: candidate #1 is defined in the trait `ManyImplTrait`
   --> $DIR/issue-7575.rs:57:5
    |
-57 |       fn is_str() -> bool { //~ NOTE candidate
-   |  _____^ starting here...
+57 | /     fn is_str() -> bool { //~ NOTE candidate
 58 | |         false
 59 | |     }
-   | |_____^ ...ending here
+   | |_____^
    = help: to disambiguate the method call, write `ManyImplTrait::is_str(t)` instead
    = help: items from traits can only be used if the trait is implemented and in scope; the following trait defines an item `is_str`, perhaps you need to implement it:
    = help: candidate #1: `ManyImplTrait`
diff --git a/src/test/ui/span/lint-unused-unsafe.stderr b/src/test/ui/span/lint-unused-unsafe.stderr
index 0df3fa43022..f4998e08907 100644
--- a/src/test/ui/span/lint-unused-unsafe.stderr
+++ b/src/test/ui/span/lint-unused-unsafe.stderr
@@ -49,68 +49,62 @@ note: because it's nested under this `unsafe` fn
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:33:9
    |
-33 |           unsafe {                         //~ ERROR: unnecessary `unsafe` block
-   |  _________^ starting here...
+33 | /         unsafe {                         //~ ERROR: unnecessary `unsafe` block
 34 | |             unsf()
 35 | |         }
-   | |_________^ ...ending here: unnecessary `unsafe` block
+   | |_________^ unnecessary `unsafe` block
    |
 note: because it's nested under this `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:32:5
    |
-32 |       unsafe {                             // don't put the warning here
-   |  _____^ starting here...
+32 | /     unsafe {                             // don't put the warning here
 33 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
 34 | |             unsf()
 35 | |         }
 36 | |     }
-   | |_____^ ...ending here
+   | |_____^
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:39:5
    |
-39 |       unsafe {                             //~ ERROR: unnecessary `unsafe` block
-   |  _____^ starting here...
+39 | /     unsafe {                             //~ ERROR: unnecessary `unsafe` block
 40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
 41 | |             unsf()
 42 | |         }
 43 | |     }
-   | |_____^ ...ending here: unnecessary `unsafe` block
+   | |_____^ unnecessary `unsafe` block
    |
 note: because it's nested under this `unsafe` fn
   --> $DIR/lint-unused-unsafe.rs:38:1
    |
-38 |   unsafe fn bad7() {
-   |  _^ starting here...
+38 | / unsafe fn bad7() {
 39 | |     unsafe {                             //~ ERROR: unnecessary `unsafe` block
 40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
 41 | |             unsf()
 42 | |         }
 43 | |     }
 44 | | }
-   | |_^ ...ending here
+   | |_^
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:40:9
    |
-40 |           unsafe {                         //~ ERROR: unnecessary `unsafe` block
-   |  _________^ starting here...
+40 | /         unsafe {                         //~ ERROR: unnecessary `unsafe` block
 41 | |             unsf()
 42 | |         }
-   | |_________^ ...ending here: unnecessary `unsafe` block
+   | |_________^ unnecessary `unsafe` block
    |
 note: because it's nested under this `unsafe` fn
   --> $DIR/lint-unused-unsafe.rs:38:1
    |
-38 |   unsafe fn bad7() {
-   |  _^ starting here...
+38 | / unsafe fn bad7() {
 39 | |     unsafe {                             //~ ERROR: unnecessary `unsafe` block
 40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
 41 | |             unsf()
 42 | |         }
 43 | |     }
 44 | | }
-   | |_^ ...ending here
+   | |_^
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr
index 58cdc502300..9c6816e7363 100644
--- a/src/test/ui/span/multiline-span-E0072.stderr
+++ b/src/test/ui/span/multiline-span-E0072.stderr
@@ -1,14 +1,13 @@
 error[E0072]: recursive type `ListNode` has infinite size
   --> $DIR/multiline-span-E0072.rs:12:1
    |
-12 |   struct
-   |  _^ starting here...
+12 | / struct
 13 | | ListNode
 14 | | {
 15 | |     head: u8,
 16 | |     tail: Option<ListNode>,
 17 | | }
-   | |_^ ...ending here: recursive type has infinite size
+   | |_^ recursive type has infinite size
    |
    = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
 
diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr
index 161b6ca48b2..843c1e811d5 100644
--- a/src/test/ui/span/multiline-span-simple.stderr
+++ b/src/test/ui/span/multiline-span-simple.stderr
@@ -2,12 +2,12 @@ error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied
   --> $DIR/multiline-span-simple.rs:23:9
    |
 23 |       foo(1 as u32 +
-   |  _________^ starting here...
+   |  _________^
 24 | |
 25 | |         bar(x,
 26 | |
 27 | |             y),
-   | |______________^ ...ending here: the trait `std::ops::Add<()>` is not implemented for `u32`
+   | |______________^ the trait `std::ops::Add<()>` is not implemented for `u32`
    |
    = note: no implementation for `u32 + ()`
 
diff --git a/src/test/ui/type-check/issue-40294.stderr b/src/test/ui/type-check/issue-40294.stderr
index 5c388c9d602..7a76799889b 100644
--- a/src/test/ui/type-check/issue-40294.stderr
+++ b/src/test/ui/type-check/issue-40294.stderr
@@ -1,15 +1,14 @@
 error[E0282]: type annotations needed
   --> $DIR/issue-40294.rs:15:1
    |
-15 |   fn foo<'a,'b,T>(x: &'a T, y: &'b T)
-   |  _^ starting here...
+15 | / fn foo<'a,'b,T>(x: &'a T, y: &'b T)
 16 | |     where &'a T : Foo,
 17 | |           &'b T : Foo
 18 | | {
 19 | |     x.foo();
 20 | |     y.foo();
 21 | | }
-   | |_^ ...ending here: cannot infer type for `&'a T`
+   | |_^ cannot infer type for `&'a T`
 
 error: aborting due to previous error
 
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 28c8d227073..a8cb30da435 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -81,6 +81,7 @@ static TARGETS: &'static [&'static str] = &[
     "s390x-unknown-linux-gnu",
     "sparc64-unknown-linux-gnu",
     "wasm32-unknown-emscripten",
+    "x86_64-linux-android",
     "x86_64-apple-darwin",
     "x86_64-apple-ios",
     "x86_64-pc-windows-gnu",