about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--RELEASES.md2
-rw-r--r--src/bootstrap/bootstrap.py2
-rw-r--r--src/bootstrap/compile.rs65
-rw-r--r--src/bootstrap/config.rs6
-rw-r--r--src/bootstrap/test.rs14
-rwxr-xr-xsrc/ci/docker/x86_64-gnu-tools/checktools.sh8
-rw-r--r--src/liballoc/collections/btree/map.rs17
-rw-r--r--src/librustc/hir/intravisit.rs7
-rw-r--r--src/librustc/hir/lowering.rs29
-rw-r--r--src/librustc/hir/map/definitions.rs8
-rw-r--r--src/librustc/hir/mod.rs12
-rw-r--r--src/librustc/hir/print.rs9
-rw-r--r--src/librustc/ich/fingerprint.rs12
-rw-r--r--src/librustc/ich/impls_hir.rs38
-rw-r--r--src/librustc/middle/resolve_lifetime.rs191
-rw-r--r--src/librustc_codegen_llvm/debuginfo/source_loc.rs14
-rw-r--r--src/librustc_codegen_llvm/mono_item.rs5
-rw-r--r--src/librustc_llvm/lib.rs6
-rw-r--r--src/librustc_privacy/lib.rs44
-rw-r--r--src/librustc_typeck/astconv.rs16
-rw-r--r--src/librustc_typeck/check/demand.rs16
-rw-r--r--src/librustc_typeck/collect.rs4
-rw-r--r--src/librustdoc/clean/mod.rs8
-rw-r--r--src/libstd/io/stdio.rs22
-rw-r--r--src/libstd/sys/unix/ext/fs.rs127
-rw-r--r--src/libstd/sys_common/remutex.rs4
-rw-r--r--src/libsyntax/attr/builtin.rs730
-rw-r--r--src/libsyntax/attr/mod.rs (renamed from src/libsyntax/attr.rs)688
-rw-r--r--src/test/ui/deprecation-sanity.rs (renamed from src/test/compile-fail/deprecation-sanity.rs)0
-rw-r--r--src/test/ui/deprecation-sanity.stderr46
-rw-r--r--src/test/ui/suggestions/issue-48364.rs16
-rw-r--r--src/test/ui/suggestions/issue-48364.stderr12
33 files changed, 1259 insertions, 921 deletions
diff --git a/.travis.yml b/.travis.yml
index 2e6722cf855..ba8a39f355c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -169,7 +169,7 @@ matrix:
     - env: IMAGE=x86_64-gnu-aux
       if: branch = auto
     - env: IMAGE=x86_64-gnu-tools
-      if: branch = auto
+      if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri)\b)/)
     - env: IMAGE=x86_64-gnu-debug
       if: branch = auto
     - env: IMAGE=x86_64-gnu-nopt
diff --git a/RELEASES.md b/RELEASES.md
index fba68ce043e..9d922f493d0 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -65,6 +65,7 @@ Cargo
 -----
 - [`cargo-metadata` now includes `authors`, `categories`, `keywords`,
   `readme`, and `repository` fields.][cargo/5386]
+- [`cargo-metadata` now includes a package's `metadata` table.][cargo/5360]
 - [Added the `--target-dir` optional argument.][cargo/5393] This allows you to specify
   a different directory than `target` for placing compilation artifacts.
 - [Cargo will be adding automatic target inference for binaries, benchmarks,
@@ -114,6 +115,7 @@ Compatibility Notes
 [cargo/5203]: https://github.com/rust-lang/cargo/pull/5203/
 [cargo/5335]: https://github.com/rust-lang/cargo/pull/5335/
 [cargo/5359]: https://github.com/rust-lang/cargo/pull/5359/
+[cargo/5360]: https://github.com/rust-lang/cargo/pull/5360/
 [cargo/5386]: https://github.com/rust-lang/cargo/pull/5386/
 [cargo/5393]: https://github.com/rust-lang/cargo/pull/5393/
 [`DoubleEndedIterator::rfind`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#method.rfind
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index a94792a2f9f..512d4d8c5b7 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -816,6 +816,8 @@ def bootstrap(help_triggered):
     env["BOOTSTRAP_PYTHON"] = sys.executable
     env["BUILD_DIR"] = build.build_dir
     env["RUSTC_BOOTSTRAP"] = '1'
+    env["CARGO"] = build.cargo()
+    env["RUSTC"] = build.rustc()
     run(args, env=env, verbose=build.verbose)
 
 
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 642f22b11ad..aef2df3e278 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -24,7 +24,6 @@ use std::io::prelude::*;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
 use std::str;
-use std::cmp::min;
 
 use build_helper::{output, mtime, up_to_date};
 use filetime::FileTime;
@@ -68,6 +67,18 @@ impl Step for Std {
         let target = self.target;
         let compiler = self.compiler;
 
+        if let Some(keep_stage) = builder.config.keep_stage {
+            if keep_stage <= compiler.stage {
+                println!("Warning: Using a potentially old libstd. This may not behave well.");
+                builder.ensure(StdLink {
+                    compiler: compiler,
+                    target_compiler: compiler,
+                    target,
+                });
+                return;
+            }
+        }
+
         builder.ensure(StartupObjects { compiler, target });
 
         if builder.force_use_stage1(compiler, target) {
@@ -351,6 +362,18 @@ impl Step for Test {
         let target = self.target;
         let compiler = self.compiler;
 
+        if let Some(keep_stage) = builder.config.keep_stage {
+            if keep_stage <= compiler.stage {
+                println!("Warning: Using a potentially old libtest. This may not behave well.");
+                builder.ensure(TestLink {
+                    compiler: compiler,
+                    target_compiler: compiler,
+                    target,
+                });
+                return;
+            }
+        }
+
         builder.ensure(Std { compiler, target });
 
         if builder.force_use_stage1(compiler, target) {
@@ -467,6 +490,18 @@ impl Step for Rustc {
         let compiler = self.compiler;
         let target = self.target;
 
+        if let Some(keep_stage) = builder.config.keep_stage {
+            if keep_stage <= compiler.stage {
+                println!("Warning: Using a potentially old librustc. This may not behave well.");
+                builder.ensure(RustcLink {
+                    compiler: compiler,
+                    target_compiler: compiler,
+                    target,
+                });
+                return;
+            }
+        }
+
         builder.ensure(Test { compiler, target });
 
         if builder.force_use_stage1(compiler, target) {
@@ -873,7 +908,7 @@ impl Step for Assemble {
     type Output = Compiler;
 
     fn should_run(run: ShouldRun) -> ShouldRun {
-        run.all_krates("rustc-main")
+        run.never()
     }
 
     /// Prepare a new compiler from the artifacts in `stage`
@@ -915,28 +950,16 @@ impl Step for Assemble {
         // link to these. (FIXME: Is that correct? It seems to be correct most
         // of the time but I think we do link to these for stage2/bin compilers
         // when not performing a full bootstrap).
-        if builder.config.keep_stage.map_or(false, |s| target_compiler.stage <= s) {
-            builder.verbose("skipping compilation of compiler due to --keep-stage");
-            let compiler = build_compiler;
-            for stage in 0..min(target_compiler.stage, builder.config.keep_stage.unwrap()) {
-                let target_compiler = builder.compiler(stage, target_compiler.host);
-                let target = target_compiler.host;
-                builder.ensure(StdLink { compiler, target_compiler, target });
-                builder.ensure(TestLink { compiler, target_compiler, target });
-                builder.ensure(RustcLink { compiler, target_compiler, target });
-            }
-        } else {
-            builder.ensure(Rustc {
+        builder.ensure(Rustc {
+            compiler: build_compiler,
+            target: target_compiler.host,
+        });
+        for &backend in builder.config.rust_codegen_backends.iter() {
+            builder.ensure(CodegenBackend {
                 compiler: build_compiler,
                 target: target_compiler.host,
+                backend,
             });
-            for &backend in builder.config.rust_codegen_backends.iter() {
-                builder.ensure(CodegenBackend {
-                    compiler: build_compiler,
-                    target: target_compiler.host,
-                    backend,
-                });
-            }
         }
 
         let lld_install = if builder.config.lld_enabled {
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index e4d467c9272..b3ed10257bd 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -23,7 +23,6 @@ use std::cmp;
 
 use num_cpus;
 use toml;
-use util::exe;
 use cache::{INTERNER, Interned};
 use flags::Flags;
 pub use flags::Subcommand;
@@ -367,9 +366,8 @@ impl Config {
         config.src = Config::path_from_python("SRC");
         config.out = Config::path_from_python("BUILD_DIR");
 
-        let stage0_root = config.out.join(&config.build).join("stage0/bin");
-        config.initial_rustc = stage0_root.join(exe("rustc", &config.build));
-        config.initial_cargo = stage0_root.join(exe("cargo", &config.build));
+        config.initial_rustc = Config::path_from_python("RUSTC");
+        config.initial_cargo = Config::path_from_python("CARGO");
 
         config
     }
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 90688b1c0e1..3adfbb5e36b 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1269,17 +1269,15 @@ impl Step for DocTest {
 
         files.sort();
 
+        let mut toolstate = ToolState::TestPass;
         for file in files {
-            let test_result = markdown_test(builder, compiler, &file);
-            if self.is_ext_doc {
-                let toolstate = if test_result {
-                    ToolState::TestPass
-                } else {
-                    ToolState::TestFail
-                };
-                builder.save_toolstate(self.name, toolstate);
+            if !markdown_test(builder, compiler, &file) {
+                toolstate = ToolState::TestFail;
             }
         }
+        if self.is_ext_doc {
+            builder.save_toolstate(self.name, toolstate);
+        }
     }
 }
 
diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh
index 56e637249f5..e8197e90851 100755
--- a/src/ci/docker/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh
@@ -79,11 +79,11 @@ status_check() {
     check_dispatch $1 beta nomicon src/doc/nomicon
     check_dispatch $1 beta reference src/doc/reference
     check_dispatch $1 beta rust-by-example src/doc/rust-by-example
-    check_dispatch $1 beta rls src/tool/rls
-    check_dispatch $1 beta rustfmt src/tool/rustfmt
+    check_dispatch $1 beta rls src/tools/rls
+    check_dispatch $1 beta rustfmt src/tools/rustfmt
     # these tools are not required for beta to successfully branch
-    check_dispatch $1 nightly clippy-driver src/tool/clippy
-    check_dispatch $1 nightly miri src/tool/miri
+    check_dispatch $1 nightly clippy-driver src/tools/clippy
+    check_dispatch $1 nightly miri src/tools/miri
 }
 
 # If this PR is intended to update one of these tools, do not let the build pass
diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs
index 2aad3149bb2..8c950cd06d9 100644
--- a/src/liballoc/collections/btree/map.rs
+++ b/src/liballoc/collections/btree/map.rs
@@ -149,12 +149,11 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for BTreeMap<K, V> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
     fn clone(&self) -> BTreeMap<K, V> {
-        fn clone_subtree<K: Clone, V: Clone>(node: node::NodeRef<marker::Immut,
-                                                                 K,
-                                                                 V,
-                                                                 marker::LeafOrInternal>)
-                                             -> BTreeMap<K, V> {
-
+        fn clone_subtree<'a, K: Clone, V: Clone>(
+            node: node::NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
+        ) -> BTreeMap<K, V>
+        where K: 'a, V: 'a,
+        {
             match node.force() {
                 Leaf(leaf) => {
                     let mut out_tree = BTreeMap {
@@ -1080,7 +1079,11 @@ impl<K: Ord, V> BTreeMap<K, V> {
 
     /// Calculates the number of elements if it is incorrect.
     fn recalc_length(&mut self) {
-        fn dfs<K, V>(node: NodeRef<marker::Immut, K, V, marker::LeafOrInternal>) -> usize {
+        fn dfs<'a, K, V>(
+            node: NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
+        ) -> usize
+        where K: 'a, V: 'a
+        {
             let mut res = node.len();
 
             if let Internal(node) = node.force() {
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 60e944e5aff..a7ed854d016 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -607,13 +607,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             }
             visitor.visit_lifetime(lifetime);
         }
-        TyImplTraitExistential(_, def_id, ref lifetimes) => {
-            // we are not recursing into the `existential` item, because it is already being visited
-            // as part of the surrounding module. The `NodeId` just exists so we don't have to look
-            // it up everywhere else in the compiler
-            visitor.visit_def_mention(Def::Existential(def_id));
-            walk_list!(visitor, visit_lifetime, lifetimes);
-        }
         TyTypeof(ref expression) => {
             visitor.visit_anon_const(expression)
         }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index e59e50ae9e6..5990340ae29 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1306,13 +1306,20 @@ impl<'a> LoweringContext<'a> {
             lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
 
             // `impl Trait` now just becomes `Foo<'a, 'b, ..>`
-            hir::TyImplTraitExistential(
-                hir::ItemId {
-                    id: exist_ty_id.node_id
-                },
-                DefId::local(exist_ty_def_index),
-                lifetimes,
-            )
+            let path = P(hir::Path {
+                span: exist_ty_span,
+                def: Def::Existential(DefId::local(exist_ty_def_index)),
+                segments: hir_vec![hir::PathSegment {
+                    infer_types: false,
+                    ident: Ident::new(keywords::Invalid.name(), exist_ty_span),
+                    args: Some(P(hir::GenericArgs {
+                        parenthesized: false,
+                        bindings: HirVec::new(),
+                        args: lifetimes,
+                    }))
+                }],
+            });
+            hir::TyPath(hir::QPath::Resolved(None, path))
         })
     }
 
@@ -1321,7 +1328,7 @@ impl<'a> LoweringContext<'a> {
         exist_ty_id: NodeId,
         parent_index: DefIndex,
         bounds: &hir::GenericBounds,
-    ) -> (HirVec<hir::Lifetime>, HirVec<hir::GenericParam>) {
+    ) -> (HirVec<hir::GenericArg>, HirVec<hir::GenericParam>) {
         // This visitor walks over impl trait bounds and creates defs for all lifetimes which
         // appear in the bounds, excluding lifetimes that are created within the bounds.
         // e.g. 'a, 'b, but not 'c in `impl for<'c> SomeTrait<'a, 'b, 'c>`
@@ -1332,7 +1339,7 @@ impl<'a> LoweringContext<'a> {
             collect_elided_lifetimes: bool,
             currently_bound_lifetimes: Vec<hir::LifetimeName>,
             already_defined_lifetimes: HashSet<hir::LifetimeName>,
-            output_lifetimes: Vec<hir::Lifetime>,
+            output_lifetimes: Vec<hir::GenericArg>,
             output_lifetime_params: Vec<hir::GenericParam>,
         }
 
@@ -1416,11 +1423,11 @@ impl<'a> LoweringContext<'a> {
                     && !self.already_defined_lifetimes.contains(&name) {
                     self.already_defined_lifetimes.insert(name);
 
-                    self.output_lifetimes.push(hir::Lifetime {
+                    self.output_lifetimes.push(hir::GenericArg::Lifetime(hir::Lifetime {
                         id: self.context.next_id().node_id,
                         span: lifetime.span,
                         name,
-                    });
+                    }));
 
                     // We need to manually create the ids here, because the
                     // definitions will go into the explicit `existential type`
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index fa01a1ccca5..328cb822547 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -23,6 +23,7 @@ use rustc_data_structures::indexed_vec::{IndexVec};
 use rustc_data_structures::stable_hasher::StableHasher;
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use session::CrateDisambiguator;
+use std::borrow::Borrow;
 use std::fmt::Write;
 use std::hash::Hash;
 use syntax::ast;
@@ -389,6 +390,13 @@ pub struct DefPathHash(pub Fingerprint);
 
 impl_stable_hash_for!(tuple_struct DefPathHash { fingerprint });
 
+impl Borrow<Fingerprint> for DefPathHash {
+    #[inline]
+    fn borrow(&self) -> &Fingerprint {
+        &self.0
+    }
+}
+
 impl Definitions {
     /// Create new empty definition map.
     pub fn new() -> Definitions {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index b0b81316148..8d83dd3279c 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1692,18 +1692,6 @@ pub enum Ty_ {
     /// A trait object type `Bound1 + Bound2 + Bound3`
     /// where `Bound` is a trait or a lifetime.
     TyTraitObject(HirVec<PolyTraitRef>, Lifetime),
-    /// An existentially quantified (there exists a type satisfying) `impl
-    /// Bound1 + Bound2 + Bound3` type where `Bound` is a trait or a lifetime.
-    ///
-    /// The `Item` is the generated
-    /// `existential type Foo<'a, 'b>: MyTrait<'a, 'b>;`.
-    ///
-    /// The `HirVec<Lifetime>` is the list of lifetimes applied as parameters
-    /// to the `abstract type`, e.g. the `'c` and `'d` in `-> Foo<'c, 'd>`.
-    /// This list is only a list of lifetimes and not type parameters
-    /// because all in-scope type parameters are captured by `impl Trait`,
-    /// so they are resolved directly through the parent `Generics`.
-    TyImplTraitExistential(ItemId, DefId, HirVec<Lifetime>),
     /// Unused for now
     TyTypeof(AnonConst),
     /// TyInfer means the type should be inferred instead of it having been
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 255009c94c6..4d0969d898e 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -420,15 +420,6 @@ impl<'a> State<'a> {
                     self.print_lifetime(lifetime)?;
                 }
             }
-            hir::TyImplTraitExistential(hir_id, _def_id, ref _lifetimes) => {
-                match self.ann.try_fetch_item(hir_id.id).map(|it| &it.node) {
-                    None => self.word_space("impl {{Trait}}")?,
-                    Some(&hir::ItemExistential(ref exist_ty)) => {
-                        self.print_bounds("impl", &exist_ty.bounds)?;
-                    },
-                    other => bug!("impl Trait pointed to {:#?}", other),
-                }
-            }
             hir::TyArray(ref ty, ref length) => {
                 self.s.word("[")?;
                 self.print_type(&ty)?;
diff --git a/src/librustc/ich/fingerprint.rs b/src/librustc/ich/fingerprint.rs
index 2a3b1ce6a36..a6e35d78dcb 100644
--- a/src/librustc/ich/fingerprint.rs
+++ b/src/librustc/ich/fingerprint.rs
@@ -45,6 +45,18 @@ impl Fingerprint {
         )
     }
 
+    // Combines two hashes in an order independent way. Make sure this is what
+    // you want.
+    #[inline]
+    pub fn combine_commutative(self, other: Fingerprint) -> Fingerprint {
+        let a = (self.1 as u128) << 64 | self.0 as u128;
+        let b = (other.1 as u128) << 64 | other.0 as u128;
+
+        let c = a.wrapping_add(b);
+
+        Fingerprint((c >> 64) as u64, c as u64)
+    }
+
     pub fn to_hex(&self) -> String {
         format!("{:x}{:x}", self.0, self.1)
     }
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 0c7baea85ad..8b62ba119eb 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -14,7 +14,7 @@
 use hir;
 use hir::map::DefPathHash;
 use hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX};
-use ich::{StableHashingContext, NodeIdHashingMode};
+use ich::{StableHashingContext, NodeIdHashingMode, Fingerprint};
 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
                                            StableHasher, StableHasherResult};
 use std::mem;
@@ -340,7 +340,6 @@ impl_stable_hash_for!(enum hir::Ty_ {
     TyTup(ts),
     TyPath(qpath),
     TyTraitObject(trait_refs, lifetime),
-    TyImplTraitExistential(existty, def_id, lifetimes),
     TyTypeof(body_id),
     TyErr,
     TyInfer
@@ -756,13 +755,34 @@ impl_stable_hash_for!(enum hir::ImplPolarity {
     Negative
 });
 
-impl_stable_hash_for!(struct hir::Mod {
-    inner,
-    // We are not hashing the IDs of the items contained in the module.
-    // This is harmless and matches the current behavior but it's not
-    // actually correct. See issue #40876.
-    item_ids -> _,
-});
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        let hir::Mod {
+            inner: ref inner_span,
+            ref item_ids,
+        } = *self;
+
+        inner_span.hash_stable(hcx, hasher);
+
+        // Combining the DefPathHashes directly is faster than feeding them
+        // into the hasher. Because we use a commutative combine, we also don't
+        // have to sort the array.
+        let item_ids_hash = item_ids
+            .iter()
+            .map(|id| {
+                let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx);
+                debug_assert_eq!(local_id, hir::ItemLocalId(0));
+                def_path_hash.0
+            }).fold(Fingerprint::ZERO, |a, b| {
+                a.combine_commutative(b)
+            });
+
+        item_ids.len().hash_stable(hcx, hasher);
+        item_ids_hash.hash_stable(hcx, hasher);
+    }
+}
 
 impl_stable_hash_for!(struct hir::ForeignMod {
     abi,
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index ed2b9c50689..369f65c214a 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -625,122 +625,131 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 };
                 self.with(scope, |_, this| this.visit_ty(&mt.ty));
             }
-            hir::TyImplTraitExistential(item_id, _, ref lifetimes) => {
-                // Resolve the lifetimes that are applied to the existential type.
-                // These are resolved in the current scope.
-                // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
-                // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
-                //          ^                 ^this gets resolved in the current scope
-                for lifetime in lifetimes {
-                    self.visit_lifetime(lifetime);
-
-                    // Check for predicates like `impl for<'a> SomeTrait<impl OtherTrait<'a>>`
-                    // and ban them. Type variables instantiated inside binders aren't
-                    // well-supported at the moment, so this doesn't work.
-                    // In the future, this should be fixed and this error should be removed.
-                    let def = self.map.defs.get(&lifetime.id).cloned();
-                    if let Some(Region::LateBound(_, def_id, _)) = def {
-                        if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
-                            // Ensure that the parent of the def is an item, not HRTB
-                            let parent_id = self.tcx.hir.get_parent_node(node_id);
-                            let parent_impl_id = hir::ImplItemId { node_id: parent_id };
-                            let parent_trait_id = hir::TraitItemId { node_id: parent_id };
-                            let krate = self.tcx.hir.forest.krate();
-                            if !(krate.items.contains_key(&parent_id)
-                                || krate.impl_items.contains_key(&parent_impl_id)
-                                || krate.trait_items.contains_key(&parent_trait_id))
-                            {
-                                span_err!(
-                                    self.tcx.sess,
-                                    lifetime.span,
-                                    E0657,
-                                    "`impl Trait` can only capture lifetimes \
-                                     bound at the fn or impl level"
-                                );
-                                self.uninsert_lifetime_on_error(lifetime, def.unwrap());
+            hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
+                if let Def::Existential(exist_ty_did) = path.def {
+                    assert!(exist_ty_did.is_local());
+                    // Resolve the lifetimes that are applied to the existential type.
+                    // These are resolved in the current scope.
+                    // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
+                    // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
+                    //          ^                 ^this gets resolved in the current scope
+                    for lifetime in &path.segments[0].args.as_ref().unwrap().args {
+                        if let hir::GenericArg::Lifetime(lifetime) = lifetime {
+                            self.visit_lifetime(lifetime);
+
+                            // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
+                            // and ban them. Type variables instantiated inside binders aren't
+                            // well-supported at the moment, so this doesn't work.
+                            // In the future, this should be fixed and this error should be removed.
+                            let def = self.map.defs.get(&lifetime.id).cloned();
+                            if let Some(Region::LateBound(_, def_id, _)) = def {
+                                if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
+                                    // Ensure that the parent of the def is an item, not HRTB
+                                    let parent_id = self.tcx.hir.get_parent_node(node_id);
+                                    let parent_impl_id = hir::ImplItemId { node_id: parent_id };
+                                    let parent_trait_id = hir::TraitItemId { node_id: parent_id };
+                                    let krate = self.tcx.hir.forest.krate();
+                                    if !(krate.items.contains_key(&parent_id)
+                                        || krate.impl_items.contains_key(&parent_impl_id)
+                                        || krate.trait_items.contains_key(&parent_trait_id))
+                                    {
+                                        span_err!(
+                                            self.tcx.sess,
+                                            lifetime.span,
+                                            E0657,
+                                            "`impl Trait` can only capture lifetimes \
+                                            bound at the fn or impl level"
+                                        );
+                                        self.uninsert_lifetime_on_error(lifetime, def.unwrap());
+                                    }
+                                }
                             }
                         }
                     }
-                }
 
-                // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
-                // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
-                // `abstract type MyAnonTy<'b>: MyTrait<'b>;`
-                //                          ^            ^ this gets resolved in the scope of
-                //                                         the exist_ty generics
-                let (generics, bounds) = match self.tcx.hir.expect_item(item_id.id).node {
-                    hir::ItemExistential(hir::ExistTy{ ref generics, ref bounds, .. }) => (
-                        generics,
-                        bounds,
-                    ),
-                    ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i),
-                };
+                    let id = self.tcx.hir.as_local_node_id(exist_ty_did).unwrap();
+
+                    // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
+                    // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
+                    // `abstract type MyAnonTy<'b>: MyTrait<'b>;`
+                    //                          ^            ^ this gets resolved in the scope of
+                    //                                         the exist_ty generics
+                    let (generics, bounds) = match self.tcx.hir.expect_item(id).node {
+                        hir::ItemExistential(hir::ExistTy{ ref generics, ref bounds, .. }) => (
+                            generics,
+                            bounds,
+                        ),
+                        ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i),
+                    };
 
-                // We want to start our early-bound indices at the end of the parent scope,
-                // not including any parent `impl Trait`s.
-                let mut index = self.next_early_index_for_abstract_type();
-                debug!("visit_ty: index = {}", index);
+                    // We want to start our early-bound indices at the end of the parent scope,
+                    // not including any parent `impl Trait`s.
+                    let mut index = self.next_early_index_for_abstract_type();
+                    debug!("visit_ty: index = {}", index);
 
-                let mut elision = None;
-                let mut lifetimes = FxHashMap();
-                let mut type_count = 0;
-                for param in &generics.params {
-                    match param.kind {
-                        GenericParamKind::Lifetime { .. } => {
-                            let (name, reg) = Region::early(&self.tcx.hir, &mut index, &param);
-                            if let hir::ParamName::Plain(param_name) = name {
-                                if param_name.name == keywords::UnderscoreLifetime.name() {
-                                    // Pick the elided lifetime "definition" if one exists
-                                    // and use it to make an elision scope.
-                                    elision = Some(reg);
+                    let mut elision = None;
+                    let mut lifetimes = FxHashMap();
+                    let mut type_count = 0;
+                    for param in &generics.params {
+                        match param.kind {
+                            GenericParamKind::Lifetime { .. } => {
+                                let (name, reg) = Region::early(&self.tcx.hir, &mut index, &param);
+                                if let hir::ParamName::Plain(param_name) = name {
+                                    if param_name.name == keywords::UnderscoreLifetime.name() {
+                                        // Pick the elided lifetime "definition" if one exists
+                                        // and use it to make an elision scope.
+                                        elision = Some(reg);
+                                    } else {
+                                        lifetimes.insert(name, reg);
+                                    }
                                 } else {
                                     lifetimes.insert(name, reg);
                                 }
-                            } else {
-                                lifetimes.insert(name, reg);
                             }
-                        }
-                        GenericParamKind::Type { .. } => {
-                            type_count += 1;
+                            GenericParamKind::Type { .. } => {
+                                type_count += 1;
+                            }
                         }
                     }
-                }
-                let next_early_index = index + type_count;
+                    let next_early_index = index + type_count;
 
-                if let Some(elision_region) = elision {
-                    let scope = Scope::Elision {
-                        elide: Elide::Exact(elision_region),
-                        s: self.scope,
-                    };
-                    self.with(scope, |_old_scope, this| {
+                    if let Some(elision_region) = elision {
+                        let scope = Scope::Elision {
+                            elide: Elide::Exact(elision_region),
+                            s: self.scope,
+                        };
+                        self.with(scope, |_old_scope, this| {
+                            let scope = Scope::Binder {
+                                lifetimes,
+                                next_early_index,
+                                s: this.scope,
+                                track_lifetime_uses: true,
+                                abstract_type_parent: false,
+                            };
+                            this.with(scope, |_old_scope, this| {
+                                this.visit_generics(generics);
+                                for bound in bounds {
+                                    this.visit_param_bound(bound);
+                                }
+                            });
+                        });
+                    } else {
                         let scope = Scope::Binder {
                             lifetimes,
                             next_early_index,
-                            s: this.scope,
+                            s: self.scope,
                             track_lifetime_uses: true,
                             abstract_type_parent: false,
                         };
-                        this.with(scope, |_old_scope, this| {
+                        self.with(scope, |_old_scope, this| {
                             this.visit_generics(generics);
                             for bound in bounds {
                                 this.visit_param_bound(bound);
                             }
                         });
-                    });
+                    }
                 } else {
-                    let scope = Scope::Binder {
-                        lifetimes,
-                        next_early_index,
-                        s: self.scope,
-                        track_lifetime_uses: true,
-                        abstract_type_parent: false,
-                    };
-                    self.with(scope, |_old_scope, this| {
-                        this.visit_generics(generics);
-                        for bound in bounds {
-                            this.visit_param_bound(bound);
-                        }
-                    });
+                    intravisit::walk_ty(self, ty)
                 }
             }
             _ => intravisit::walk_ty(self, ty),
diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs
index eb37e7f931c..958d09413ed 100644
--- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs
+++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs
@@ -81,16 +81,22 @@ impl InternalDebugLocation {
 
 pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) {
     let metadata_node = match debug_location {
-        KnownLocation { scope, line, .. } => {
-            // Always set the column to zero like Clang and GCC
-            let col = UNKNOWN_COLUMN_NUMBER;
+        KnownLocation { scope, line, col } => {
+            // For MSVC, set the column number to zero.
+            // Otherwise, emit it. This mimics clang behaviour.
+            // See discussion in https://github.com/rust-lang/rust/issues/42921
+            let col_used =  if bx.cx.sess().target.target.options.is_like_msvc {
+                UNKNOWN_COLUMN_NUMBER
+            } else {
+                col as c_uint
+            };
             debug!("setting debug location to {} {}", line, col);
 
             unsafe {
                 llvm::LLVMRustDIBuilderCreateDebugLocation(
                     debug_context(bx.cx).llcontext,
                     line as c_uint,
-                    col as c_uint,
+                    col_used,
                     scope,
                     ptr::null_mut())
             }
diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs
index 6ba3582f014..c4a23ac653c 100644
--- a/src/librustc_codegen_llvm/mono_item.rs
+++ b/src/librustc_codegen_llvm/mono_item.rs
@@ -25,11 +25,10 @@ use monomorphize::Instance;
 use type_of::LayoutLlvmExt;
 use rustc::hir;
 use rustc::hir::def::Def;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::mono::{Linkage, Visibility};
 use rustc::ty::TypeFoldable;
 use rustc::ty::layout::LayoutOf;
-use syntax::attr;
 use std::fmt;
 
 pub use rustc::mir::mono::MonoItem;
@@ -173,7 +172,7 @@ fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     // visibility as we're going to link this object all over the place but
     // don't want the symbols to get exported.
     if linkage != Linkage::Internal && linkage != Linkage::Private &&
-       attr::contains_name(cx.tcx.hir.krate_attrs(), "compiler_builtins") {
+       cx.tcx.is_compiler_builtins(LOCAL_CRATE) {
         unsafe {
             llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden);
         }
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 07830d54d0c..741758cb954 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -331,6 +331,12 @@ pub fn initialize_available_targets() {
                  LLVMInitializeAArch64TargetMC,
                  LLVMInitializeAArch64AsmPrinter,
                  LLVMInitializeAArch64AsmParser);
+    init_target!(llvm_component = "amdgpu",
+                 LLVMInitializeAMDGPUTargetInfo,
+                 LLVMInitializeAMDGPUTarget,
+                 LLVMInitializeAMDGPUTargetMC,
+                 LLVMInitializeAMDGPUAsmPrinter,
+                 LLVMInitializeAMDGPUAsmParser);
     init_target!(llvm_component = "mips",
                  LLVMInitializeMipsTargetInfo,
                  LLVMInitializeMipsTarget,
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index c55d57cb916..3919ba13076 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -229,8 +229,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
             hir::ItemUse(..) => {}
             // The interface is empty
             hir::ItemGlobalAsm(..) => {}
-            // Checked by visit_ty
-            hir::ItemExistential(..) => {}
+            hir::ItemExistential(..) => {
+                if item_level.is_some() {
+                    // Reach the (potentially private) type and the API being exposed
+                    self.reach(item.id).ty().predicates();
+                }
+            }
             // Visit everything
             hir::ItemConst(..) | hir::ItemStatic(..) |
             hir::ItemFn(..) | hir::ItemTy(..) => {
@@ -390,17 +394,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
             module_id = self.tcx.hir.get_parent_node(module_id);
         }
     }
-
-    fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
-        if let hir::TyImplTraitExistential(item_id, _, _) = ty.node {
-            if self.get(item_id.id).is_some() {
-                // Reach the (potentially private) type and the API being exposed
-                self.reach(item_id.id).ty().predicates();
-            }
-        }
-
-        intravisit::walk_ty(self, ty);
-    }
 }
 
 impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
@@ -1568,8 +1561,15 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             hir::ItemUse(..) => {}
             // No subitems
             hir::ItemGlobalAsm(..) => {}
-            // Checked in visit_ty
-            hir::ItemExistential(..) => {}
+            hir::ItemExistential(..) => {
+                // Check the traits being exposed, as they're separate,
+                // e.g. `impl Iterator<Item=T>` has two predicates,
+                // `X: Iterator` and `<X as Iterator>::Item == T`,
+                // where `X` is the `impl Iterator<Item=T>` itself,
+                // stored in `predicates_of`, not in the `Ty` itself.
+
+                self.check(item.id, self.inner_visibility).predicates();
+            }
             // Subitems of these items have inherited publicity
             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
             hir::ItemTy(..) => {
@@ -1667,20 +1667,6 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
         // handled in `visit_item` above
     }
 
-    fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
-        if let hir::TyImplTraitExistential(ref exist_item, _, _) = ty.node {
-            // Check the traits being exposed, as they're separate,
-            // e.g. `impl Iterator<Item=T>` has two predicates,
-            // `X: Iterator` and `<X as Iterator>::Item == T`,
-            // where `X` is the `impl Iterator<Item=T>` itself,
-            // stored in `predicates_of`, not in the `Ty` itself.
-
-            self.check(exist_item.id, self.inner_visibility).predicates();
-        }
-
-        intravisit::walk_ty(self, ty);
-    }
-
     // Don't recurse into expressions in array sizes or const initializers
     fn visit_expr(&mut self, _: &'tcx hir::Expr) {}
     // Don't recurse into patterns in function arguments
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 762dc5d26f5..2e467d315be 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1095,6 +1095,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                     hir::TyStr => tcx.mk_str()
                 }
             }
+            Def::Existential(exist_ty_did) => {
+                assert!(exist_ty_did.is_local());
+                let lifetimes = &path.segments[0].args.as_ref().unwrap().args;
+                self.impl_trait_ty_to_ty(exist_ty_did, lifetimes)
+            }
             Def::Err => {
                 self.set_tainted_by_errors();
                 return self.tcx().types.err;
@@ -1140,9 +1145,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             hir::TyTraitObject(ref bounds, ref lifetime) => {
                 self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime)
             }
-            hir::TyImplTraitExistential(_, def_id, ref lifetimes) => {
-                self.impl_trait_ty_to_ty(def_id, lifetimes)
-            }
             hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
                 debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| {
@@ -1195,7 +1197,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
     pub fn impl_trait_ty_to_ty(
         &self,
         def_id: DefId,
-        lifetimes: &[hir::Lifetime],
+        lifetimes: &[hir::GenericArg],
     ) -> Ty<'tcx> {
         debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
         let tcx = self.tcx();
@@ -1208,7 +1210,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 // Our own parameters are the resolved lifetimes.
                 match param.kind {
                     GenericParamDefKind::Lifetime => {
-                        self.ast_region_to_region(&lifetimes[i], None).into()
+                        if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] {
+                            self.ast_region_to_region(lifetime, None).into()
+                        } else {
+                            bug!()
+                        }
                     }
                     _ => bug!()
                 }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 08d8dd2e498..aee64ad3b55 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -264,9 +264,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 (&ty::TyStr, &ty::TySlice(arr)) if arr == self.tcx.types.u8 => {
                     if let hir::ExprLit(_) = expr.node {
                         if let Ok(src) = cm.span_to_snippet(sp) {
-                            return Some((sp,
-                                         "consider removing the leading `b`",
-                                         src[1..].to_string()));
+                            if src.starts_with("b\"") {
+                                return Some((sp,
+                                             "consider removing the leading `b`",
+                                             src[1..].to_string()));
+                            }
                         }
                     }
                 },
@@ -274,9 +276,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 (&ty::TySlice(arr), &ty::TyStr) if arr == self.tcx.types.u8 => {
                     if let hir::ExprLit(_) = expr.node {
                         if let Ok(src) = cm.span_to_snippet(sp) {
-                            return Some((sp,
-                                         "consider adding a leading `b`",
-                                         format!("b{}", src)));
+                            if src.starts_with("\"") {
+                                return Some((sp,
+                                             "consider adding a leading `b`",
+                                             format!("b{}", src)));
+                            }
                         }
                     }
                 }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 852603ac51c..4931cbfa5ac 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -875,10 +875,6 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
         }
 
-        NodeTy(&hir::Ty { node: hir::TyImplTraitExistential(..), .. }) => {
-            bug!("impl Trait is desugared to existential type items");
-        }
-
         _ => &no_generics,
     };
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index b8abb98edec..f71d62d5a04 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2987,14 +2987,6 @@ impl Clean<Type> for hir::Ty {
                 }
             }
             TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
-            TyImplTraitExistential(hir_id, _, _) => {
-                match cx.tcx.hir.expect_item(hir_id.id).node {
-                    hir::ItemExistential(ref exist_ty) => {
-                        ImplTrait(exist_ty.bounds.clean(cx))
-                    },
-                    ref other => panic!("impl Trait pointed to {:#?}", other),
-                }
-            },
             TyInfer | TyErr => Infer,
             TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
         }
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 2472bed5ba4..fce85a200ba 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -712,10 +712,32 @@ pub fn _eprint(args: fmt::Arguments) {
 
 #[cfg(test)]
 mod tests {
+    use panic::{UnwindSafe, RefUnwindSafe};
     use thread;
     use super::*;
 
     #[test]
+    fn stdout_unwind_safe() {
+        assert_unwind_safe::<Stdout>();
+    }
+    #[test]
+    fn stdoutlock_unwind_safe() {
+        assert_unwind_safe::<StdoutLock>();
+        assert_unwind_safe::<StdoutLock<'static>>();
+    }
+    #[test]
+    fn stderr_unwind_safe() {
+        assert_unwind_safe::<Stderr>();
+    }
+    #[test]
+    fn stderrlock_unwind_safe() {
+        assert_unwind_safe::<StderrLock>();
+        assert_unwind_safe::<StderrLock<'static>>();
+    }
+
+    fn assert_unwind_safe<T: UnwindSafe + RefUnwindSafe>() {}
+
+    #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
     fn panic_doesnt_poison() {
         thread::spawn(|| {
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index 4e981012669..507e9d88171 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -59,6 +59,78 @@ pub trait FileExt {
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
 
+    /// Reads the exact number of byte required to fill `buf` from the given offset.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
+    ///
+    /// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
+    /// [`read_at`]: #tymethod.read_at
+    ///
+    /// # Errors
+    ///
+    /// If this function encounters an error of the kind
+    /// [`ErrorKind::Interrupted`] then the error is ignored and the operation
+    /// will continue.
+    ///
+    /// If this function encounters an "end of file" before completely filling
+    /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
+    /// The contents of `buf` are unspecified in this case.
+    ///
+    /// If any other read error is encountered then this function immediately
+    /// returns. The contents of `buf` are unspecified in this case.
+    ///
+    /// If this function returns an error, it is unspecified how many bytes it
+    /// has read, but it will never read more than would be necessary to
+    /// completely fill the buffer.
+    ///
+    /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
+    /// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(rw_exact_all_at)]
+    /// use std::io;
+    /// use std::fs::File;
+    /// use std::os::unix::prelude::FileExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut buf = [0u8; 8];
+    ///     let file = File::open("foo.txt")?;
+    ///
+    ///     // We now read exactly 8 bytes from the offset 10.
+    ///     file.read_exact_at(&mut buf, 10)?;
+    ///     println!("read {} bytes: {:?}", buf.len(), buf);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "rw_exact_all_at", issue = "51984")]
+    fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
+        while !buf.is_empty() {
+            match self.read_at(buf, offset) {
+                Ok(0) => break,
+                Ok(n) => {
+                    let tmp = buf;
+                    buf = &mut tmp[n..];
+                    offset += n as u64;
+                }
+                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+                Err(e) => return Err(e),
+            }
+        }
+        if !buf.is_empty() {
+            Err(io::Error::new(io::ErrorKind::UnexpectedEof,
+                               "failed to fill whole buffer"))
+        } else {
+            Ok(())
+        }
+    }
+
     /// Writes a number of bytes starting from a given offset.
     ///
     /// Returns the number of bytes written.
@@ -93,6 +165,61 @@ pub trait FileExt {
     /// ```
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
+
+    /// Attempts to write an entire buffer starting from a given offset.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// This method will continuously call [`write_at`] until there is no more data
+    /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
+    /// returned. This method will not return until the entire buffer has been
+    /// successfully written or such an error occurs. The first error that is
+    /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
+    /// returned.
+    ///
+    /// # Errors
+    ///
+    /// This function will return the first error of
+    /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
+    ///
+    /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
+    /// [`write_at`]: #tymethod.write_at
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(rw_exact_all_at)]
+    /// use std::fs::File;
+    /// use std::io;
+    /// use std::os::unix::prelude::FileExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let file = File::open("foo.txt")?;
+    ///
+    ///     // We now write at the offset 10.
+    ///     file.write_all_at(b"sushi", 10)?;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "rw_exact_all_at", issue = "51984")]
+    fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
+        while !buf.is_empty() {
+            match self.write_at(buf, offset) {
+                Ok(0) => return Err(io::Error::new(io::ErrorKind::WriteZero,
+                                                   "failed to write whole buffer")),
+                Ok(n) => {
+                    buf = &buf[n..];
+                    offset += n as u64
+                }
+                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+                Err(e) => return Err(e),
+            }
+        }
+        Ok(())
+    }
 }
 
 #[stable(feature = "file_offset", since = "1.15.0")]
diff --git a/src/libstd/sys_common/remutex.rs b/src/libstd/sys_common/remutex.rs
index 022056f8a8a..071a3a25c7a 100644
--- a/src/libstd/sys_common/remutex.rs
+++ b/src/libstd/sys_common/remutex.rs
@@ -13,6 +13,7 @@ use marker;
 use ops::Deref;
 use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
 use sys::mutex as sys;
+use panic::{UnwindSafe, RefUnwindSafe};
 
 /// A re-entrant mutual exclusion
 ///
@@ -28,6 +29,9 @@ pub struct ReentrantMutex<T> {
 unsafe impl<T: Send> Send for ReentrantMutex<T> {}
 unsafe impl<T: Send> Sync for ReentrantMutex<T> {}
 
+impl<T> UnwindSafe for ReentrantMutex<T> {}
+impl<T> RefUnwindSafe for ReentrantMutex<T> {}
+
 
 /// An RAII implementation of a "scoped lock" of a mutex. When this structure is
 /// dropped (falls out of scope), the lock will be unlocked.
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
new file mode 100644
index 00000000000..ecd52a62eab
--- /dev/null
+++ b/src/libsyntax/attr/builtin.rs
@@ -0,0 +1,730 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Parsing and validation of builtin attributes
+
+use ast::{self, Attribute, MetaItem, Name, NestedMetaItemKind};
+use errors::{Applicability, Handler};
+use feature_gate::{Features, GatedCfg};
+use parse::ParseSess;
+use syntax_pos::{symbol::Symbol, Span};
+
+use super::{list_contains_name, mark_used, MetaItemKind};
+
+enum AttrError {
+    MultipleItem(Name),
+    UnknownMetaItem(Name, &'static [&'static str]),
+    MissingSince,
+    MissingFeature,
+    MultipleStabilityLevels,
+    UnsupportedLiteral
+}
+
+fn handle_errors(diag: &Handler, span: Span, error: AttrError) {
+    match error {
+        AttrError::MultipleItem(item) => span_err!(diag, span, E0538,
+                                                   "multiple '{}' items", item),
+        AttrError::UnknownMetaItem(item, expected) => {
+            let expected = expected
+                .iter()
+                .map(|name| format!("`{}`", name))
+                .collect::<Vec<_>>();
+            struct_span_err!(diag, span, E0541, "unknown meta item '{}'", item)
+                .span_label(span, format!("expected one of {}", expected.join(", ")))
+                .emit();
+        }
+        AttrError::MissingSince => span_err!(diag, span, E0542, "missing 'since'"),
+        AttrError::MissingFeature => span_err!(diag, span, E0546, "missing 'feature'"),
+        AttrError::MultipleStabilityLevels => span_err!(diag, span, E0544,
+                                                        "multiple stability levels"),
+        AttrError::UnsupportedLiteral => span_err!(diag, span, E0565, "unsupported literal"),
+    }
+}
+
+#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)]
+pub enum InlineAttr {
+    None,
+    Hint,
+    Always,
+    Never,
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum UnwindAttr {
+    Allowed,
+    Aborts,
+}
+
+/// Determine what `#[unwind]` attribute is present in `attrs`, if any.
+pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Option<UnwindAttr> {
+    let syntax_error = |attr: &Attribute| {
+        mark_used(attr);
+        diagnostic.map(|d| {
+            span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute");
+        });
+        None
+    };
+
+    attrs.iter().fold(None, |ia, attr| {
+        if attr.path != "unwind" {
+            return ia;
+        }
+        let meta = match attr.meta() {
+            Some(meta) => meta.node,
+            None => return ia,
+        };
+        match meta {
+            MetaItemKind::Word => {
+                syntax_error(attr)
+            }
+            MetaItemKind::List(ref items) => {
+                mark_used(attr);
+                if items.len() != 1 {
+                    syntax_error(attr)
+                } else if list_contains_name(&items[..], "allowed") {
+                    Some(UnwindAttr::Allowed)
+                } else if list_contains_name(&items[..], "aborts") {
+                    Some(UnwindAttr::Aborts)
+                } else {
+                    syntax_error(attr)
+                }
+            }
+            _ => ia,
+        }
+    })
+}
+
+/// Represents the #[stable], #[unstable], #[rustc_{deprecated,const_unstable}] attributes.
+#[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct Stability {
+    pub level: StabilityLevel,
+    pub feature: Symbol,
+    pub rustc_depr: Option<RustcDeprecation>,
+    pub rustc_const_unstable: Option<RustcConstUnstable>,
+}
+
+/// The available stability levels.
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+pub enum StabilityLevel {
+    // Reason for the current stability level and the relevant rust-lang issue
+    Unstable { reason: Option<Symbol>, issue: u32 },
+    Stable { since: Symbol },
+}
+
+impl StabilityLevel {
+    pub fn is_unstable(&self) -> bool {
+        if let StabilityLevel::Unstable {..} = *self {
+            true
+        } else {
+            false
+        }
+    }
+    pub fn is_stable(&self) -> bool {
+        if let StabilityLevel::Stable {..} = *self {
+            true
+        } else {
+            false
+        }
+    }
+}
+
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+pub struct RustcDeprecation {
+    pub since: Symbol,
+    pub reason: Symbol,
+}
+
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+pub struct RustcConstUnstable {
+    pub feature: Symbol,
+}
+
+/// Check if `attrs` contains an attribute like `#![feature(feature_name)]`.
+/// This will not perform any "sanity checks" on the form of the attributes.
+pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool {
+    attrs.iter().any(|item| {
+        item.check_name("feature") &&
+        item.meta_item_list().map(|list| {
+            list.iter().any(|mi| {
+                mi.word().map(|w| w.name() == feature_name)
+                         .unwrap_or(false)
+            })
+        }).unwrap_or(false)
+    })
+}
+
+/// Find the first stability attribute. `None` if none exists.
+pub fn find_stability(diagnostic: &Handler, attrs: &[Attribute],
+                      item_sp: Span) -> Option<Stability> {
+    find_stability_generic(diagnostic, attrs.iter(), item_sp)
+}
+
+fn find_stability_generic<'a, I>(diagnostic: &Handler,
+                                 attrs_iter: I,
+                                 item_sp: Span)
+                                 -> Option<Stability>
+    where I: Iterator<Item = &'a Attribute>
+{
+    use self::StabilityLevel::*;
+
+    let mut stab: Option<Stability> = None;
+    let mut rustc_depr: Option<RustcDeprecation> = None;
+    let mut rustc_const_unstable: Option<RustcConstUnstable> = None;
+
+    'outer: for attr in attrs_iter {
+        if ![
+            "rustc_deprecated",
+            "rustc_const_unstable",
+            "unstable",
+            "stable",
+        ].iter().any(|&s| attr.path == s) {
+            continue // not a stability level
+        }
+
+        mark_used(attr);
+
+        let meta = attr.meta();
+        if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta {
+            let meta = meta.as_ref().unwrap();
+            let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
+                if item.is_some() {
+                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
+                    return false
+                }
+                if let Some(v) = meta.value_str() {
+                    *item = Some(v);
+                    true
+                } else {
+                    span_err!(diagnostic, meta.span, E0539, "incorrect meta item");
+                    false
+                }
+            };
+
+            macro_rules! get_meta {
+                ($($name:ident),+) => {
+                    $(
+                        let mut $name = None;
+                    )+
+                    for meta in metas {
+                        if let Some(mi) = meta.meta_item() {
+                            match &*mi.name().as_str() {
+                                $(
+                                    stringify!($name)
+                                        => if !get(mi, &mut $name) { continue 'outer },
+                                )+
+                                _ => {
+                                    let expected = &[ $( stringify!($name) ),+ ];
+                                    handle_errors(
+                                        diagnostic,
+                                        mi.span,
+                                        AttrError::UnknownMetaItem(mi.name(), expected));
+                                    continue 'outer
+                                }
+                            }
+                        } else {
+                            handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
+                            continue 'outer
+                        }
+                    }
+                }
+            }
+
+            match &*meta.name().as_str() {
+                "rustc_deprecated" => {
+                    if rustc_depr.is_some() {
+                        span_err!(diagnostic, item_sp, E0540,
+                                  "multiple rustc_deprecated attributes");
+                        continue 'outer
+                    }
+
+                    get_meta!(since, reason);
+
+                    match (since, reason) {
+                        (Some(since), Some(reason)) => {
+                            rustc_depr = Some(RustcDeprecation {
+                                since,
+                                reason,
+                            })
+                        }
+                        (None, _) => {
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingSince);
+                            continue
+                        }
+                        _ => {
+                            span_err!(diagnostic, attr.span(), E0543, "missing 'reason'");
+                            continue
+                        }
+                    }
+                }
+                "rustc_const_unstable" => {
+                    if rustc_const_unstable.is_some() {
+                        span_err!(diagnostic, item_sp, E0553,
+                                  "multiple rustc_const_unstable attributes");
+                        continue 'outer
+                    }
+
+                    get_meta!(feature);
+                    if let Some(feature) = feature {
+                        rustc_const_unstable = Some(RustcConstUnstable {
+                            feature
+                        });
+                    } else {
+                        span_err!(diagnostic, attr.span(), E0629, "missing 'feature'");
+                        continue
+                    }
+                }
+                "unstable" => {
+                    if stab.is_some() {
+                        handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels);
+                        break
+                    }
+
+                    let mut feature = None;
+                    let mut reason = None;
+                    let mut issue = None;
+                    for meta in metas {
+                        if let Some(mi) = meta.meta_item() {
+                            match &*mi.name().as_str() {
+                                "feature" => if !get(mi, &mut feature) { continue 'outer },
+                                "reason" => if !get(mi, &mut reason) { continue 'outer },
+                                "issue" => if !get(mi, &mut issue) { continue 'outer },
+                                _ => {
+                                    handle_errors(
+                                        diagnostic,
+                                        meta.span,
+                                        AttrError::UnknownMetaItem(
+                                            mi.name(),
+                                            &["feature", "reason", "issue"]
+                                        ),
+                                    );
+                                    continue 'outer
+                                }
+                            }
+                        } else {
+                            handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
+                            continue 'outer
+                        }
+                    }
+
+                    match (feature, reason, issue) {
+                        (Some(feature), reason, Some(issue)) => {
+                            stab = Some(Stability {
+                                level: Unstable {
+                                    reason,
+                                    issue: {
+                                        if let Ok(issue) = issue.as_str().parse() {
+                                            issue
+                                        } else {
+                                            span_err!(diagnostic, attr.span(), E0545,
+                                                      "incorrect 'issue'");
+                                            continue
+                                        }
+                                    }
+                                },
+                                feature,
+                                rustc_depr: None,
+                                rustc_const_unstable: None,
+                            })
+                        }
+                        (None, _, _) => {
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingFeature);
+                            continue
+                        }
+                        _ => {
+                            span_err!(diagnostic, attr.span(), E0547, "missing 'issue'");
+                            continue
+                        }
+                    }
+                }
+                "stable" => {
+                    if stab.is_some() {
+                        handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels);
+                        break
+                    }
+
+                    let mut feature = None;
+                    let mut since = None;
+                    for meta in metas {
+                        if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
+                            match &*mi.name().as_str() {
+                                "feature" => if !get(mi, &mut feature) { continue 'outer },
+                                "since" => if !get(mi, &mut since) { continue 'outer },
+                                _ => {
+                                    handle_errors(
+                                        diagnostic,
+                                        meta.span,
+                                        AttrError::UnknownMetaItem(mi.name(), &["since", "note"]),
+                                    );
+                                    continue 'outer
+                                }
+                            }
+                        } else {
+                            handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
+                            continue 'outer
+                        }
+                    }
+
+                    match (feature, since) {
+                        (Some(feature), Some(since)) => {
+                            stab = Some(Stability {
+                                level: Stable {
+                                    since,
+                                },
+                                feature,
+                                rustc_depr: None,
+                                rustc_const_unstable: None,
+                            })
+                        }
+                        (None, _) => {
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingFeature);
+                            continue
+                        }
+                        _ => {
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingSince);
+                            continue
+                        }
+                    }
+                }
+                _ => unreachable!()
+            }
+        } else {
+            span_err!(diagnostic, attr.span(), E0548, "incorrect stability attribute type");
+            continue
+        }
+    }
+
+    // Merge the deprecation info into the stability info
+    if let Some(rustc_depr) = rustc_depr {
+        if let Some(ref mut stab) = stab {
+            stab.rustc_depr = Some(rustc_depr);
+        } else {
+            span_err!(diagnostic, item_sp, E0549,
+                      "rustc_deprecated attribute must be paired with \
+                       either stable or unstable attribute");
+        }
+    }
+
+    // Merge the const-unstable info into the stability info
+    if let Some(rustc_const_unstable) = rustc_const_unstable {
+        if let Some(ref mut stab) = stab {
+            stab.rustc_const_unstable = Some(rustc_const_unstable);
+        } else {
+            span_err!(diagnostic, item_sp, E0630,
+                      "rustc_const_unstable attribute must be paired with \
+                       either stable or unstable attribute");
+        }
+    }
+
+    stab
+}
+
+pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
+    super::first_attr_value_str_by_name(attrs, "crate_name")
+}
+
+/// Tests if a cfg-pattern matches the cfg set
+pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool {
+    eval_condition(cfg, sess, &mut |cfg| {
+        if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
+            gated_cfg.check_and_emit(sess, feats);
+        }
+        sess.config.contains(&(cfg.name(), cfg.value_str()))
+    })
+}
+
+/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
+/// evaluate individual items.
+pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
+                         -> bool
+    where F: FnMut(&ast::MetaItem) -> bool
+{
+    match cfg.node {
+        ast::MetaItemKind::List(ref mis) => {
+            for mi in mis.iter() {
+                if !mi.is_meta_item() {
+                    handle_errors(&sess.span_diagnostic, mi.span, AttrError::UnsupportedLiteral);
+                    return false;
+                }
+            }
+
+            // The unwraps below may look dangerous, but we've already asserted
+            // that they won't fail with the loop above.
+            match &*cfg.name().as_str() {
+                "any" => mis.iter().any(|mi| {
+                    eval_condition(mi.meta_item().unwrap(), sess, eval)
+                }),
+                "all" => mis.iter().all(|mi| {
+                    eval_condition(mi.meta_item().unwrap(), sess, eval)
+                }),
+                "not" => {
+                    if mis.len() != 1 {
+                        span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
+                        return false;
+                    }
+
+                    !eval_condition(mis[0].meta_item().unwrap(), sess, eval)
+                },
+                p => {
+                    span_err!(sess.span_diagnostic, cfg.span, E0537, "invalid predicate `{}`", p);
+                    false
+                }
+            }
+        },
+        ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => {
+            eval(cfg)
+        }
+    }
+}
+
+
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+pub struct Deprecation {
+    pub since: Option<Symbol>,
+    pub note: Option<Symbol>,
+}
+
+/// Find the deprecation attribute. `None` if none exists.
+pub fn find_deprecation(diagnostic: &Handler, attrs: &[Attribute],
+                        item_sp: Span) -> Option<Deprecation> {
+    find_deprecation_generic(diagnostic, attrs.iter(), item_sp)
+}
+
+fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
+                                   attrs_iter: I,
+                                   item_sp: Span)
+                                   -> Option<Deprecation>
+    where I: Iterator<Item = &'a Attribute>
+{
+    let mut depr: Option<Deprecation> = None;
+
+    'outer: for attr in attrs_iter {
+        if attr.path != "deprecated" {
+            continue
+        }
+
+        mark_used(attr);
+
+        if depr.is_some() {
+            span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes");
+            break
+        }
+
+        depr = if let Some(metas) = attr.meta_item_list() {
+            let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
+                if item.is_some() {
+                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
+                    return false
+                }
+                if let Some(v) = meta.value_str() {
+                    *item = Some(v);
+                    true
+                } else {
+                    span_err!(diagnostic, meta.span, E0551, "incorrect meta item");
+                    false
+                }
+            };
+
+            let mut since = None;
+            let mut note = None;
+            for meta in metas {
+                if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
+                    match &*mi.name().as_str() {
+                        "since" => if !get(mi, &mut since) { continue 'outer },
+                        "note" => if !get(mi, &mut note) { continue 'outer },
+                        _ => {
+                            handle_errors(
+                                diagnostic,
+                                meta.span,
+                                AttrError::UnknownMetaItem(mi.name(), &["since", "note"]),
+                            );
+                            continue 'outer
+                        }
+                    }
+                } else {
+                    handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
+                    continue 'outer
+                }
+            }
+
+            Some(Deprecation {since: since, note: note})
+        } else {
+            Some(Deprecation{since: None, note: None})
+        }
+    }
+
+    depr
+}
+
+#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
+pub enum ReprAttr {
+    ReprInt(IntType),
+    ReprC,
+    ReprPacked(u32),
+    ReprSimd,
+    ReprTransparent,
+    ReprAlign(u32),
+}
+
+#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
+pub enum IntType {
+    SignedInt(ast::IntTy),
+    UnsignedInt(ast::UintTy)
+}
+
+impl IntType {
+    #[inline]
+    pub fn is_signed(self) -> bool {
+        use self::IntType::*;
+
+        match self {
+            SignedInt(..) => true,
+            UnsignedInt(..) => false
+        }
+    }
+}
+
+/// Parse #[repr(...)] forms.
+///
+/// Valid repr contents: any of the primitive integral type names (see
+/// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
+/// the same discriminant size that the corresponding C enum would or C
+/// structure layout, `packed` to remove padding, and `transparent` to elegate representation
+/// concerns to the only non-ZST field.
+pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr> {
+    use self::ReprAttr::*;
+
+    let mut acc = Vec::new();
+    if attr.path == "repr" {
+        if let Some(items) = attr.meta_item_list() {
+            mark_used(attr);
+            for item in items {
+                if !item.is_meta_item() {
+                    handle_errors(diagnostic, item.span, AttrError::UnsupportedLiteral);
+                    continue
+                }
+
+                let mut recognised = false;
+                if let Some(mi) = item.word() {
+                    let word = &*mi.name().as_str();
+                    let hint = match word {
+                        "C" => Some(ReprC),
+                        "packed" => Some(ReprPacked(1)),
+                        "simd" => Some(ReprSimd),
+                        "transparent" => Some(ReprTransparent),
+                        _ => match int_type_of_word(word) {
+                            Some(ity) => Some(ReprInt(ity)),
+                            None => {
+                                None
+                            }
+                        }
+                    };
+
+                    if let Some(h) = hint {
+                        recognised = true;
+                        acc.push(h);
+                    }
+                } else if let Some((name, value)) = item.name_value_literal() {
+                    let parse_alignment = |node: &ast::LitKind| -> Result<u32, &'static str> {
+                        if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
+                            if literal.is_power_of_two() {
+                                // rustc::ty::layout::Align restricts align to <= 2^29
+                                if *literal <= 1 << 29 {
+                                    Ok(*literal as u32)
+                                } else {
+                                    Err("larger than 2^29")
+                                }
+                            } else {
+                                Err("not a power of two")
+                            }
+                        } else {
+                            Err("not an unsuffixed integer")
+                        }
+                    };
+
+                    let mut literal_error = None;
+                    if name == "align" {
+                        recognised = true;
+                        match parse_alignment(&value.node) {
+                            Ok(literal) => acc.push(ReprAlign(literal)),
+                            Err(message) => literal_error = Some(message)
+                        };
+                    }
+                    else if name == "packed" {
+                        recognised = true;
+                        match parse_alignment(&value.node) {
+                            Ok(literal) => acc.push(ReprPacked(literal)),
+                            Err(message) => literal_error = Some(message)
+                        };
+                    }
+                    if let Some(literal_error) = literal_error {
+                        span_err!(diagnostic, item.span, E0589,
+                                  "invalid `repr(align)` attribute: {}", literal_error);
+                    }
+                } else {
+                    if let Some(meta_item) = item.meta_item() {
+                        if meta_item.name() == "align" {
+                            if let MetaItemKind::NameValue(ref value) = meta_item.node {
+                                recognised = true;
+                                let mut err = struct_span_err!(diagnostic, item.span, E0693,
+                                    "incorrect `repr(align)` attribute format");
+                                match value.node {
+                                    ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
+                                        err.span_suggestion_with_applicability(
+                                            item.span,
+                                            "use parentheses instead",
+                                            format!("align({})", int),
+                                            Applicability::MachineApplicable
+                                        );
+                                    }
+                                    ast::LitKind::Str(s, _) => {
+                                        err.span_suggestion_with_applicability(
+                                            item.span,
+                                            "use parentheses instead",
+                                            format!("align({})", s),
+                                            Applicability::MachineApplicable
+                                        );
+                                    }
+                                    _ => {}
+                                }
+                                err.emit();
+                            }
+                        }
+                    }
+                }
+                if !recognised {
+                    // Not a word we recognize
+                    span_err!(diagnostic, item.span, E0552,
+                              "unrecognized representation hint");
+                }
+            }
+        }
+    }
+    acc
+}
+
+fn int_type_of_word(s: &str) -> Option<IntType> {
+    use self::IntType::*;
+
+    match s {
+        "i8" => Some(SignedInt(ast::IntTy::I8)),
+        "u8" => Some(UnsignedInt(ast::UintTy::U8)),
+        "i16" => Some(SignedInt(ast::IntTy::I16)),
+        "u16" => Some(UnsignedInt(ast::UintTy::U16)),
+        "i32" => Some(SignedInt(ast::IntTy::I32)),
+        "u32" => Some(UnsignedInt(ast::UintTy::U32)),
+        "i64" => Some(SignedInt(ast::IntTy::I64)),
+        "u64" => Some(UnsignedInt(ast::UintTy::U64)),
+        "i128" => Some(SignedInt(ast::IntTy::I128)),
+        "u128" => Some(UnsignedInt(ast::UintTy::U128)),
+        "isize" => Some(SignedInt(ast::IntTy::Isize)),
+        "usize" => Some(UnsignedInt(ast::UintTy::Usize)),
+        _ => None
+    }
+}
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr/mod.rs
index ded493fe395..4e27d6c1525 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -8,11 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Functions dealing with attributes and meta items
+//! Functions dealing with attributes and meta items
 
-pub use self::StabilityLevel::*;
-pub use self::ReprAttr::*;
+mod builtin;
+
+pub use self::builtin::{
+    cfg_matches, contains_feature_attr, eval_condition, find_crate_name, find_deprecation,
+    find_repr_attrs, find_stability, find_unwind_attr, Deprecation, InlineAttr, IntType, ReprAttr,
+    RustcConstUnstable, RustcDeprecation, Stability, StabilityLevel, UnwindAttr,
+};
 pub use self::IntType::*;
+pub use self::ReprAttr::*;
+pub use self::StabilityLevel::*;
 
 use ast;
 use ast::{AttrId, Attribute, Name, Ident, Path, PathSegment};
@@ -20,8 +27,6 @@ use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
 use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind, GenericParam};
 use codemap::{BytePos, Spanned, respan, dummy_spanned};
 use syntax_pos::Span;
-use errors::{Applicability, Handler};
-use feature_gate::{Features, GatedCfg};
 use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
 use parse::parser::Parser;
 use parse::{self, ParseSess, PResult};
@@ -34,29 +39,6 @@ use GLOBALS;
 
 use std::iter;
 
-enum AttrError {
-    MultipleItem(Name),
-    UnknownMetaItem(Name),
-    MissingSince,
-    MissingFeature,
-    MultipleStabilityLevels,
-    UnsupportedLiteral
-}
-
-fn handle_errors(diag: &Handler, span: Span, error: AttrError) {
-    match error {
-        AttrError::MultipleItem(item) => span_err!(diag, span, E0538,
-                                                   "multiple '{}' items", item),
-        AttrError::UnknownMetaItem(item) => span_err!(diag, span, E0541,
-                                                      "unknown meta item '{}'", item),
-        AttrError::MissingSince => span_err!(diag, span, E0542, "missing 'since'"),
-        AttrError::MissingFeature => span_err!(diag, span, E0546, "missing 'feature'"),
-        AttrError::MultipleStabilityLevels => span_err!(diag, span, E0544,
-                                                        "multiple stability levels"),
-        AttrError::UnsupportedLiteral => span_err!(diag, span, E0565, "unsupported literal"),
-    }
-}
-
 pub fn mark_used(attr: &Attribute) {
     debug!("Marking {:?} as used.", attr);
     let AttrId(id) = attr.id;
@@ -442,7 +424,6 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute
     }
 }
 
-
 /// Returns an outer attribute with the given value.
 pub fn mk_attr_outer(span: Span, id: AttrId, item: MetaItem) -> Attribute {
     mk_spanned_attr_outer(span, id, item)
@@ -495,655 +476,6 @@ pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option<S
         .and_then(|at| at.value_str())
 }
 
-/// Check if `attrs` contains an attribute like `#![feature(feature_name)]`.
-/// This will not perform any "sanity checks" on the form of the attributes.
-pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool {
-    attrs.iter().any(|item| {
-        item.check_name("feature") &&
-        item.meta_item_list().map(|list| {
-            list.iter().any(|mi| {
-                mi.word().map(|w| w.name() == feature_name)
-                         .unwrap_or(false)
-            })
-        }).unwrap_or(false)
-    })
-}
-
-/* Higher-level applications */
-
-pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
-    first_attr_value_str_by_name(attrs, "crate_name")
-}
-
-#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)]
-pub enum InlineAttr {
-    None,
-    Hint,
-    Always,
-    Never,
-}
-
-#[derive(Copy, Clone, PartialEq)]
-pub enum UnwindAttr {
-    Allowed,
-    Aborts,
-}
-
-/// Determine what `#[unwind]` attribute is present in `attrs`, if any.
-pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Option<UnwindAttr> {
-    let syntax_error = |attr: &Attribute| {
-        mark_used(attr);
-        diagnostic.map(|d| {
-            span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute");
-        });
-        None
-    };
-
-    attrs.iter().fold(None, |ia, attr| {
-        if attr.path != "unwind" {
-            return ia;
-        }
-        let meta = match attr.meta() {
-            Some(meta) => meta.node,
-            None => return ia,
-        };
-        match meta {
-            MetaItemKind::Word => {
-                syntax_error(attr)
-            }
-            MetaItemKind::List(ref items) => {
-                mark_used(attr);
-                if items.len() != 1 {
-                    syntax_error(attr)
-                } else if list_contains_name(&items[..], "allowed") {
-                    Some(UnwindAttr::Allowed)
-                } else if list_contains_name(&items[..], "aborts") {
-                    Some(UnwindAttr::Aborts)
-                } else {
-                    syntax_error(attr)
-                }
-            }
-            _ => ia,
-        }
-    })
-}
-
-
-/// Tests if a cfg-pattern matches the cfg set
-pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool {
-    eval_condition(cfg, sess, &mut |cfg| {
-        if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
-            gated_cfg.check_and_emit(sess, feats);
-        }
-        sess.config.contains(&(cfg.name(), cfg.value_str()))
-    })
-}
-
-/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
-/// evaluate individual items.
-pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
-                         -> bool
-    where F: FnMut(&ast::MetaItem) -> bool
-{
-    match cfg.node {
-        ast::MetaItemKind::List(ref mis) => {
-            for mi in mis.iter() {
-                if !mi.is_meta_item() {
-                    handle_errors(&sess.span_diagnostic, mi.span, AttrError::UnsupportedLiteral);
-                    return false;
-                }
-            }
-
-            // The unwraps below may look dangerous, but we've already asserted
-            // that they won't fail with the loop above.
-            match &*cfg.name().as_str() {
-                "any" => mis.iter().any(|mi| {
-                    eval_condition(mi.meta_item().unwrap(), sess, eval)
-                }),
-                "all" => mis.iter().all(|mi| {
-                    eval_condition(mi.meta_item().unwrap(), sess, eval)
-                }),
-                "not" => {
-                    if mis.len() != 1 {
-                        span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
-                        return false;
-                    }
-
-                    !eval_condition(mis[0].meta_item().unwrap(), sess, eval)
-                },
-                p => {
-                    span_err!(sess.span_diagnostic, cfg.span, E0537, "invalid predicate `{}`", p);
-                    false
-                }
-            }
-        },
-        ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => {
-            eval(cfg)
-        }
-    }
-}
-
-/// Represents the #[stable], #[unstable], #[rustc_{deprecated,const_unstable}] attributes.
-#[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct Stability {
-    pub level: StabilityLevel,
-    pub feature: Symbol,
-    pub rustc_depr: Option<RustcDeprecation>,
-    pub rustc_const_unstable: Option<RustcConstUnstable>,
-}
-
-/// The available stability levels.
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
-pub enum StabilityLevel {
-    // Reason for the current stability level and the relevant rust-lang issue
-    Unstable { reason: Option<Symbol>, issue: u32 },
-    Stable { since: Symbol },
-}
-
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
-pub struct RustcDeprecation {
-    pub since: Symbol,
-    pub reason: Symbol,
-}
-
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
-pub struct RustcConstUnstable {
-    pub feature: Symbol,
-}
-
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
-pub struct Deprecation {
-    pub since: Option<Symbol>,
-    pub note: Option<Symbol>,
-}
-
-impl StabilityLevel {
-    pub fn is_unstable(&self) -> bool { if let Unstable {..} = *self { true } else { false }}
-    pub fn is_stable(&self) -> bool { if let Stable {..} = *self { true } else { false }}
-}
-
-fn find_stability_generic<'a, I>(diagnostic: &Handler,
-                                 attrs_iter: I,
-                                 item_sp: Span)
-                                 -> Option<Stability>
-    where I: Iterator<Item = &'a Attribute>
-{
-    let mut stab: Option<Stability> = None;
-    let mut rustc_depr: Option<RustcDeprecation> = None;
-    let mut rustc_const_unstable: Option<RustcConstUnstable> = None;
-
-    'outer: for attr in attrs_iter {
-        if ![
-            "rustc_deprecated",
-            "rustc_const_unstable",
-            "unstable",
-            "stable",
-        ].iter().any(|&s| attr.path == s) {
-            continue // not a stability level
-        }
-
-        mark_used(attr);
-
-        let meta = attr.meta();
-        if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta {
-            let meta = meta.as_ref().unwrap();
-            let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
-                if item.is_some() {
-                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
-                    return false
-                }
-                if let Some(v) = meta.value_str() {
-                    *item = Some(v);
-                    true
-                } else {
-                    span_err!(diagnostic, meta.span, E0539, "incorrect meta item");
-                    false
-                }
-            };
-
-            macro_rules! get_meta {
-                ($($name:ident),+) => {
-                    $(
-                        let mut $name = None;
-                    )+
-                    for meta in metas {
-                        if let Some(mi) = meta.meta_item() {
-                            match &*mi.name().as_str() {
-                                $(
-                                    stringify!($name)
-                                        => if !get(mi, &mut $name) { continue 'outer },
-                                )+
-                                _ => {
-                                    handle_errors(diagnostic, mi.span,
-                                                  AttrError::UnknownMetaItem(mi.name()));
-                                    continue 'outer
-                                }
-                            }
-                        } else {
-                            handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
-                            continue 'outer
-                        }
-                    }
-                }
-            }
-
-            match &*meta.name().as_str() {
-                "rustc_deprecated" => {
-                    if rustc_depr.is_some() {
-                        span_err!(diagnostic, item_sp, E0540,
-                                  "multiple rustc_deprecated attributes");
-                        continue 'outer
-                    }
-
-                    get_meta!(since, reason);
-
-                    match (since, reason) {
-                        (Some(since), Some(reason)) => {
-                            rustc_depr = Some(RustcDeprecation {
-                                since,
-                                reason,
-                            })
-                        }
-                        (None, _) => {
-                            handle_errors(diagnostic, attr.span(), AttrError::MissingSince);
-                            continue
-                        }
-                        _ => {
-                            span_err!(diagnostic, attr.span(), E0543, "missing 'reason'");
-                            continue
-                        }
-                    }
-                }
-                "rustc_const_unstable" => {
-                    if rustc_const_unstable.is_some() {
-                        span_err!(diagnostic, item_sp, E0553,
-                                  "multiple rustc_const_unstable attributes");
-                        continue 'outer
-                    }
-
-                    get_meta!(feature);
-                    if let Some(feature) = feature {
-                        rustc_const_unstable = Some(RustcConstUnstable {
-                            feature
-                        });
-                    } else {
-                        span_err!(diagnostic, attr.span(), E0629, "missing 'feature'");
-                        continue
-                    }
-                }
-                "unstable" => {
-                    if stab.is_some() {
-                        handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels);
-                        break
-                    }
-
-                    let mut feature = None;
-                    let mut reason = None;
-                    let mut issue = None;
-                    for meta in metas {
-                        if let Some(mi) = meta.meta_item() {
-                            match &*mi.name().as_str() {
-                                "feature" => if !get(mi, &mut feature) { continue 'outer },
-                                "reason" => if !get(mi, &mut reason) { continue 'outer },
-                                "issue" => if !get(mi, &mut issue) { continue 'outer },
-                                _ => {
-                                    handle_errors(diagnostic, meta.span,
-                                                  AttrError::UnknownMetaItem(mi.name()));
-                                    continue 'outer
-                                }
-                            }
-                        } else {
-                            handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
-                            continue 'outer
-                        }
-                    }
-
-                    match (feature, reason, issue) {
-                        (Some(feature), reason, Some(issue)) => {
-                            stab = Some(Stability {
-                                level: Unstable {
-                                    reason,
-                                    issue: {
-                                        if let Ok(issue) = issue.as_str().parse() {
-                                            issue
-                                        } else {
-                                            span_err!(diagnostic, attr.span(), E0545,
-                                                      "incorrect 'issue'");
-                                            continue
-                                        }
-                                    }
-                                },
-                                feature,
-                                rustc_depr: None,
-                                rustc_const_unstable: None,
-                            })
-                        }
-                        (None, _, _) => {
-                            handle_errors(diagnostic, attr.span(), AttrError::MissingFeature);
-                            continue
-                        }
-                        _ => {
-                            span_err!(diagnostic, attr.span(), E0547, "missing 'issue'");
-                            continue
-                        }
-                    }
-                }
-                "stable" => {
-                    if stab.is_some() {
-                        handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels);
-                        break
-                    }
-
-                    let mut feature = None;
-                    let mut since = None;
-                    for meta in metas {
-                        if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
-                            match &*mi.name().as_str() {
-                                "feature" => if !get(mi, &mut feature) { continue 'outer },
-                                "since" => if !get(mi, &mut since) { continue 'outer },
-                                _ => {
-                                    handle_errors(diagnostic, meta.span,
-                                                  AttrError::UnknownMetaItem(mi.name()));
-                                    continue 'outer
-                                }
-                            }
-                        } else {
-                            handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
-                            continue 'outer
-                        }
-                    }
-
-                    match (feature, since) {
-                        (Some(feature), Some(since)) => {
-                            stab = Some(Stability {
-                                level: Stable {
-                                    since,
-                                },
-                                feature,
-                                rustc_depr: None,
-                                rustc_const_unstable: None,
-                            })
-                        }
-                        (None, _) => {
-                            handle_errors(diagnostic, attr.span(), AttrError::MissingFeature);
-                            continue
-                        }
-                        _ => {
-                            handle_errors(diagnostic, attr.span(), AttrError::MissingSince);
-                            continue
-                        }
-                    }
-                }
-                _ => unreachable!()
-            }
-        } else {
-            span_err!(diagnostic, attr.span(), E0548, "incorrect stability attribute type");
-            continue
-        }
-    }
-
-    // Merge the deprecation info into the stability info
-    if let Some(rustc_depr) = rustc_depr {
-        if let Some(ref mut stab) = stab {
-            stab.rustc_depr = Some(rustc_depr);
-        } else {
-            span_err!(diagnostic, item_sp, E0549,
-                      "rustc_deprecated attribute must be paired with \
-                       either stable or unstable attribute");
-        }
-    }
-
-    // Merge the const-unstable info into the stability info
-    if let Some(rustc_const_unstable) = rustc_const_unstable {
-        if let Some(ref mut stab) = stab {
-            stab.rustc_const_unstable = Some(rustc_const_unstable);
-        } else {
-            span_err!(diagnostic, item_sp, E0630,
-                      "rustc_const_unstable attribute must be paired with \
-                       either stable or unstable attribute");
-        }
-    }
-
-    stab
-}
-
-fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
-                                   attrs_iter: I,
-                                   item_sp: Span)
-                                   -> Option<Deprecation>
-    where I: Iterator<Item = &'a Attribute>
-{
-    let mut depr: Option<Deprecation> = None;
-
-    'outer: for attr in attrs_iter {
-        if attr.path != "deprecated" {
-            continue
-        }
-
-        mark_used(attr);
-
-        if depr.is_some() {
-            span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes");
-            break
-        }
-
-        depr = if let Some(metas) = attr.meta_item_list() {
-            let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
-                if item.is_some() {
-                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
-                    return false
-                }
-                if let Some(v) = meta.value_str() {
-                    *item = Some(v);
-                    true
-                } else {
-                    span_err!(diagnostic, meta.span, E0551, "incorrect meta item");
-                    false
-                }
-            };
-
-            let mut since = None;
-            let mut note = None;
-            for meta in metas {
-                if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
-                    match &*mi.name().as_str() {
-                        "since" => if !get(mi, &mut since) { continue 'outer },
-                        "note" => if !get(mi, &mut note) { continue 'outer },
-                        _ => {
-                            handle_errors(diagnostic, meta.span,
-                                          AttrError::UnknownMetaItem(mi.name()));
-                            continue 'outer
-                        }
-                    }
-                } else {
-                    handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
-                    continue 'outer
-                }
-            }
-
-            Some(Deprecation {since: since, note: note})
-        } else {
-            Some(Deprecation{since: None, note: None})
-        }
-    }
-
-    depr
-}
-
-/// Find the first stability attribute. `None` if none exists.
-pub fn find_stability(diagnostic: &Handler, attrs: &[Attribute],
-                      item_sp: Span) -> Option<Stability> {
-    find_stability_generic(diagnostic, attrs.iter(), item_sp)
-}
-
-/// Find the deprecation attribute. `None` if none exists.
-pub fn find_deprecation(diagnostic: &Handler, attrs: &[Attribute],
-                        item_sp: Span) -> Option<Deprecation> {
-    find_deprecation_generic(diagnostic, attrs.iter(), item_sp)
-}
-
-
-/// Parse #[repr(...)] forms.
-///
-/// Valid repr contents: any of the primitive integral type names (see
-/// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
-/// the same discriminant size that the corresponding C enum would or C
-/// structure layout, `packed` to remove padding, and `transparent` to elegate representation
-/// concerns to the only non-ZST field.
-pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr> {
-    let mut acc = Vec::new();
-    if attr.path == "repr" {
-        if let Some(items) = attr.meta_item_list() {
-            mark_used(attr);
-            for item in items {
-                if !item.is_meta_item() {
-                    handle_errors(diagnostic, item.span, AttrError::UnsupportedLiteral);
-                    continue
-                }
-
-                let mut recognised = false;
-                if let Some(mi) = item.word() {
-                    let word = &*mi.name().as_str();
-                    let hint = match word {
-                        "C" => Some(ReprC),
-                        "packed" => Some(ReprPacked(1)),
-                        "simd" => Some(ReprSimd),
-                        "transparent" => Some(ReprTransparent),
-                        _ => match int_type_of_word(word) {
-                            Some(ity) => Some(ReprInt(ity)),
-                            None => {
-                                None
-                            }
-                        }
-                    };
-
-                    if let Some(h) = hint {
-                        recognised = true;
-                        acc.push(h);
-                    }
-                } else if let Some((name, value)) = item.name_value_literal() {
-                    let parse_alignment = |node: &ast::LitKind| -> Result<u32, &'static str> {
-                        if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
-                            if literal.is_power_of_two() {
-                                // rustc::ty::layout::Align restricts align to <= 2^29
-                                if *literal <= 1 << 29 {
-                                    Ok(*literal as u32)
-                                } else {
-                                    Err("larger than 2^29")
-                                }
-                            } else {
-                                Err("not a power of two")
-                            }
-                        } else {
-                            Err("not an unsuffixed integer")
-                        }
-                    };
-
-                    let mut literal_error = None;
-                    if name == "align" {
-                        recognised = true;
-                        match parse_alignment(&value.node) {
-                            Ok(literal) => acc.push(ReprAlign(literal)),
-                            Err(message) => literal_error = Some(message)
-                        };
-                    }
-                    else if name == "packed" {
-                        recognised = true;
-                        match parse_alignment(&value.node) {
-                            Ok(literal) => acc.push(ReprPacked(literal)),
-                            Err(message) => literal_error = Some(message)
-                        };
-                    }
-                    if let Some(literal_error) = literal_error {
-                        span_err!(diagnostic, item.span, E0589,
-                                  "invalid `repr(align)` attribute: {}", literal_error);
-                    }
-                } else {
-                    if let Some(meta_item) = item.meta_item() {
-                        if meta_item.name() == "align" {
-                            if let MetaItemKind::NameValue(ref value) = meta_item.node {
-                                recognised = true;
-                                let mut err = struct_span_err!(diagnostic, item.span, E0693,
-                                    "incorrect `repr(align)` attribute format");
-                                match value.node {
-                                    ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
-                                        err.span_suggestion_with_applicability(
-                                            item.span,
-                                            "use parentheses instead",
-                                            format!("align({})", int),
-                                            Applicability::MachineApplicable
-                                        );
-                                    }
-                                    ast::LitKind::Str(s, _) => {
-                                        err.span_suggestion_with_applicability(
-                                            item.span,
-                                            "use parentheses instead",
-                                            format!("align({})", s),
-                                            Applicability::MachineApplicable
-                                        );
-                                    }
-                                    _ => {}
-                                }
-                                err.emit();
-                            }
-                        }
-                    }
-                }
-                if !recognised {
-                    // Not a word we recognize
-                    span_err!(diagnostic, item.span, E0552,
-                              "unrecognized representation hint");
-                }
-            }
-        }
-    }
-    acc
-}
-
-fn int_type_of_word(s: &str) -> Option<IntType> {
-    match s {
-        "i8" => Some(SignedInt(ast::IntTy::I8)),
-        "u8" => Some(UnsignedInt(ast::UintTy::U8)),
-        "i16" => Some(SignedInt(ast::IntTy::I16)),
-        "u16" => Some(UnsignedInt(ast::UintTy::U16)),
-        "i32" => Some(SignedInt(ast::IntTy::I32)),
-        "u32" => Some(UnsignedInt(ast::UintTy::U32)),
-        "i64" => Some(SignedInt(ast::IntTy::I64)),
-        "u64" => Some(UnsignedInt(ast::UintTy::U64)),
-        "i128" => Some(SignedInt(ast::IntTy::I128)),
-        "u128" => Some(UnsignedInt(ast::UintTy::U128)),
-        "isize" => Some(SignedInt(ast::IntTy::Isize)),
-        "usize" => Some(UnsignedInt(ast::UintTy::Usize)),
-        _ => None
-    }
-}
-
-#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
-pub enum ReprAttr {
-    ReprInt(IntType),
-    ReprC,
-    ReprPacked(u32),
-    ReprSimd,
-    ReprTransparent,
-    ReprAlign(u32),
-}
-
-#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
-pub enum IntType {
-    SignedInt(ast::IntTy),
-    UnsignedInt(ast::UintTy)
-}
-
-impl IntType {
-    #[inline]
-    pub fn is_signed(self) -> bool {
-        match self {
-            SignedInt(..) => true,
-            UnsignedInt(..) => false
-        }
-    }
-}
-
 impl MetaItem {
     fn tokens(&self) -> TokenStream {
         let mut idents = vec![];
diff --git a/src/test/compile-fail/deprecation-sanity.rs b/src/test/ui/deprecation-sanity.rs
index af2ac79ea80..af2ac79ea80 100644
--- a/src/test/compile-fail/deprecation-sanity.rs
+++ b/src/test/ui/deprecation-sanity.rs
diff --git a/src/test/ui/deprecation-sanity.stderr b/src/test/ui/deprecation-sanity.stderr
new file mode 100644
index 00000000000..967eb6e23a3
--- /dev/null
+++ b/src/test/ui/deprecation-sanity.stderr
@@ -0,0 +1,46 @@
+error[E0541]: unknown meta item 'reason'
+  --> $DIR/deprecation-sanity.rs:14:43
+   |
+LL |     #[deprecated(since = "a", note = "a", reason)] //~ ERROR unknown meta item 'reason'
+   |                                           ^^^^^^ expected one of `since`, `note`
+
+error[E0551]: incorrect meta item
+  --> $DIR/deprecation-sanity.rs:17:31
+   |
+LL |     #[deprecated(since = "a", note)] //~ ERROR incorrect meta item
+   |                               ^^^^
+
+error[E0551]: incorrect meta item
+  --> $DIR/deprecation-sanity.rs:20:18
+   |
+LL |     #[deprecated(since, note = "a")] //~ ERROR incorrect meta item
+   |                  ^^^^^
+
+error[E0551]: incorrect meta item
+  --> $DIR/deprecation-sanity.rs:23:31
+   |
+LL |     #[deprecated(since = "a", note(b))] //~ ERROR incorrect meta item
+   |                               ^^^^^^^
+
+error[E0551]: incorrect meta item
+  --> $DIR/deprecation-sanity.rs:26:18
+   |
+LL |     #[deprecated(since(b), note = "a")] //~ ERROR incorrect meta item
+   |                  ^^^^^^^^
+
+error[E0550]: multiple deprecated attributes
+  --> $DIR/deprecation-sanity.rs:32:1
+   |
+LL | fn multiple1() { } //~ ERROR multiple deprecated attributes
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0538]: multiple 'since' items
+  --> $DIR/deprecation-sanity.rs:34:27
+   |
+LL | #[deprecated(since = "a", since = "b", note = "c")] //~ ERROR multiple 'since' items
+   |                           ^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0538, E0541, E0550, E0551.
+For more information about an error, try `rustc --explain E0538`.
diff --git a/src/test/ui/suggestions/issue-48364.rs b/src/test/ui/suggestions/issue-48364.rs
new file mode 100644
index 00000000000..82cb722a656
--- /dev/null
+++ b/src/test/ui/suggestions/issue-48364.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo() -> bool {
+    b"".starts_with(stringify!(foo))
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-48364.stderr b/src/test/ui/suggestions/issue-48364.stderr
new file mode 100644
index 00000000000..b420654a32d
--- /dev/null
+++ b/src/test/ui/suggestions/issue-48364.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-48364.rs:12:21
+   |
+LL |     b"".starts_with(stringify!(foo))
+   |                     ^^^^^^^^^^^^^^^ expected slice, found str
+   |
+   = note: expected type `&[u8]`
+              found type `&'static str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.